Check in LLVM r95781.
diff --git a/lib/Parse/AttributeList.cpp b/lib/Parse/AttributeList.cpp
new file mode 100644
index 0000000..df48e3a
--- /dev/null
+++ b/lib/Parse/AttributeList.cpp
@@ -0,0 +1,119 @@
+//===--- AttributeList.cpp --------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the AttributeList class implementation
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Parse/AttributeList.h"
+#include "clang/Basic/IdentifierTable.h"
+#include "llvm/ADT/StringSwitch.h"
+using namespace clang;
+
+AttributeList::AttributeList(IdentifierInfo *aName, SourceLocation aLoc,
+                             IdentifierInfo *sName, SourceLocation sLoc,
+                             IdentifierInfo *pName, SourceLocation pLoc,
+                             ActionBase::ExprTy **ExprList, unsigned numArgs,
+                             AttributeList *n, bool declspec, bool cxx0x)
+  : AttrName(aName), AttrLoc(aLoc), ScopeName(sName), ScopeLoc(sLoc),
+    ParmName(pName), ParmLoc(pLoc), NumArgs(numArgs), Next(n),
+    DeclspecAttribute(declspec), CXX0XAttribute(cxx0x) {
+
+  if (numArgs == 0)
+    Args = 0;
+  else {
+    Args = new ActionBase::ExprTy*[numArgs];
+    memcpy(Args, ExprList, numArgs*sizeof(Args[0]));
+  }
+}
+
+AttributeList::~AttributeList() {
+  if (Args) {
+    // FIXME: before we delete the vector, we need to make sure the Expr's
+    // have been deleted. Since ActionBase::ExprTy is "void", we are dependent
+    // on the actions module for actually freeing the memory. The specific
+    // hooks are ActOnDeclarator, ActOnTypeName, ActOnParamDeclaratorType,
+    // ParseField, ParseTag. Once these routines have freed the expression,
+    // they should zero out the Args slot (to indicate the memory has been
+    // freed). If any element of the vector is non-null, we should assert.
+    delete [] Args;
+  }
+  delete Next;
+}
+
+AttributeList::Kind AttributeList::getKind(const IdentifierInfo *Name) {
+  llvm::StringRef AttrName = Name->getName();
+
+  // Normalize the attribute name, __foo__ becomes foo.
+  if (AttrName.startswith("__") && AttrName.endswith("__"))
+    AttrName = AttrName.substr(2, AttrName.size() - 4);
+
+  // FIXME: Hand generating this is neither smart nor efficient.
+  return llvm::StringSwitch<AttributeList::Kind>(AttrName)
+    .Case("weak", AT_weak)
+    .Case("pure", AT_pure)
+    .Case("mode", AT_mode)
+    .Case("used", AT_used)
+    .Case("alias", AT_alias)
+    .Case("align", AT_aligned)
+    .Case("final", AT_final)
+    .Case("cdecl", AT_cdecl)
+    .Case("const", AT_const)
+    .Case("blocks", AT_blocks)
+    .Case("format", AT_format)
+    .Case("hiding", AT_hiding)
+    .Case("malloc", AT_malloc)
+    .Case("packed", AT_packed)
+    .Case("unused", AT_unused)
+    .Case("aligned", AT_aligned)
+    .Case("cleanup", AT_cleanup)
+    .Case("nodebug", AT_nodebug)
+    .Case("nonnull", AT_nonnull)
+    .Case("nothrow", AT_nothrow)
+    .Case("objc_gc", AT_objc_gc)
+    .Case("regparm", AT_regparm)
+    .Case("section", AT_section)
+    .Case("stdcall", AT_stdcall)
+    .Case("annotate", AT_annotate)
+    .Case("fastcall", AT_fastcall)
+    .Case("iboutlet", AT_IBOutlet)
+    .Case("noreturn", AT_noreturn)
+    .Case("noinline", AT_noinline)
+    .Case("override", AT_override)
+    .Case("sentinel", AT_sentinel)
+    .Case("NSObject", AT_nsobject)
+    .Case("dllimport", AT_dllimport)
+    .Case("dllexport", AT_dllexport)
+    .Case("may_alias", IgnoredAttribute) // FIXME: TBAA
+    .Case("base_check", AT_base_check)
+    .Case("deprecated", AT_deprecated)
+    .Case("visibility", AT_visibility)
+    .Case("destructor", AT_destructor)
+    .Case("format_arg", AT_format_arg)
+    .Case("gnu_inline", AT_gnu_inline)
+    .Case("weak_import", AT_weak_import)
+    .Case("vector_size", AT_vector_size)
+    .Case("constructor", AT_constructor)
+    .Case("unavailable", AT_unavailable)
+    .Case("overloadable", AT_overloadable)
+    .Case("address_space", AT_address_space)
+    .Case("always_inline", AT_always_inline)
+    .Case("vec_type_hint", IgnoredAttribute)
+    .Case("objc_exception", AT_objc_exception)
+    .Case("ext_vector_type", AT_ext_vector_type)
+    .Case("transparent_union", AT_transparent_union)
+    .Case("analyzer_noreturn", AT_analyzer_noreturn)
+    .Case("warn_unused_result", AT_warn_unused_result)
+    .Case("carries_dependency", AT_carries_dependency)
+    .Case("ns_returns_retained", AT_ns_returns_retained)
+    .Case("cf_returns_retained", AT_cf_returns_retained)
+    .Case("reqd_work_group_size", AT_reqd_wg_size)
+    .Case("no_instrument_function", AT_no_instrument_function)
+    .Default(UnknownAttribute);
+}
diff --git a/lib/Parse/CMakeLists.txt b/lib/Parse/CMakeLists.txt
new file mode 100644
index 0000000..bec1c6e
--- /dev/null
+++ b/lib/Parse/CMakeLists.txt
@@ -0,0 +1,21 @@
+set(LLVM_NO_RTTI 1)
+
+add_clang_library(clangParse
+  AttributeList.cpp
+  DeclSpec.cpp
+  MinimalAction.cpp
+  ParseCXXInlineMethods.cpp
+  ParseDecl.cpp
+  ParseDeclCXX.cpp
+  ParseExpr.cpp
+  ParseExprCXX.cpp
+  ParseInit.cpp
+  ParseObjc.cpp
+  ParsePragma.cpp
+  ParseStmt.cpp
+  ParseTemplate.cpp
+  ParseTentative.cpp
+  Parser.cpp
+  )
+
+add_dependencies(clangParse ClangDiagnosticParse)
diff --git a/lib/Parse/DeclSpec.cpp b/lib/Parse/DeclSpec.cpp
new file mode 100644
index 0000000..4a699e7
--- /dev/null
+++ b/lib/Parse/DeclSpec.cpp
@@ -0,0 +1,555 @@
+//===--- SemaDeclSpec.cpp - Declaration Specifier Semantic Analysis -------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+//  This file implements semantic analysis for declaration specifiers.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Parse/DeclSpec.h"
+#include "clang/Parse/ParseDiagnostic.h"
+#include "clang/Parse/Template.h"
+#include "clang/Lex/Preprocessor.h"
+#include "clang/Basic/LangOptions.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/Support/ErrorHandling.h"
+#include <cstring>
+using namespace clang;
+
+
+static DiagnosticBuilder Diag(Diagnostic &D, SourceLocation Loc,
+                              SourceManager &SrcMgr, unsigned DiagID) {
+  return D.Report(FullSourceLoc(Loc, SrcMgr), DiagID);
+}
+
+
+void UnqualifiedId::setTemplateId(TemplateIdAnnotation *TemplateId) {
+  assert(TemplateId && "NULL template-id annotation?");
+  Kind = IK_TemplateId;
+  this->TemplateId = TemplateId;
+  StartLocation = TemplateId->TemplateNameLoc;
+  EndLocation = TemplateId->RAngleLoc;
+}
+
+void UnqualifiedId::setConstructorTemplateId(TemplateIdAnnotation *TemplateId) {
+  assert(TemplateId && "NULL template-id annotation?");
+  Kind = IK_ConstructorTemplateId;
+  this->TemplateId = TemplateId;
+  StartLocation = TemplateId->TemplateNameLoc;
+  EndLocation = TemplateId->RAngleLoc;
+}
+
+/// DeclaratorChunk::getFunction - Return a DeclaratorChunk for a function.
+/// "TheDeclarator" is the declarator that this will be added to.
+DeclaratorChunk DeclaratorChunk::getFunction(bool hasProto, bool isVariadic,
+                                             SourceLocation EllipsisLoc,
+                                             ParamInfo *ArgInfo,
+                                             unsigned NumArgs,
+                                             unsigned TypeQuals,
+                                             bool hasExceptionSpec,
+                                             SourceLocation ThrowLoc,
+                                             bool hasAnyExceptionSpec,
+                                             ActionBase::TypeTy **Exceptions,
+                                             SourceRange *ExceptionRanges,
+                                             unsigned NumExceptions,
+                                             SourceLocation LPLoc,
+                                             SourceLocation RPLoc,
+                                             Declarator &TheDeclarator) {
+  DeclaratorChunk I;
+  I.Kind                 = Function;
+  I.Loc                  = LPLoc;
+  I.EndLoc               = RPLoc;
+  I.Fun.hasPrototype     = hasProto;
+  I.Fun.isVariadic       = isVariadic;
+  I.Fun.EllipsisLoc      = EllipsisLoc.getRawEncoding();
+  I.Fun.DeleteArgInfo    = false;
+  I.Fun.TypeQuals        = TypeQuals;
+  I.Fun.NumArgs          = NumArgs;
+  I.Fun.ArgInfo          = 0;
+  I.Fun.hasExceptionSpec = hasExceptionSpec;
+  I.Fun.ThrowLoc         = ThrowLoc.getRawEncoding();
+  I.Fun.hasAnyExceptionSpec = hasAnyExceptionSpec;
+  I.Fun.NumExceptions    = NumExceptions;
+  I.Fun.Exceptions       = 0;
+
+  // new[] an argument array if needed.
+  if (NumArgs) {
+    // If the 'InlineParams' in Declarator is unused and big enough, put our
+    // parameter list there (in an effort to avoid new/delete traffic).  If it
+    // is already used (consider a function returning a function pointer) or too
+    // small (function taking too many arguments), go to the heap.
+    if (!TheDeclarator.InlineParamsUsed &&
+        NumArgs <= llvm::array_lengthof(TheDeclarator.InlineParams)) {
+      I.Fun.ArgInfo = TheDeclarator.InlineParams;
+      I.Fun.DeleteArgInfo = false;
+      TheDeclarator.InlineParamsUsed = true;
+    } else {
+      I.Fun.ArgInfo = new DeclaratorChunk::ParamInfo[NumArgs];
+      I.Fun.DeleteArgInfo = true;
+    }
+    memcpy(I.Fun.ArgInfo, ArgInfo, sizeof(ArgInfo[0])*NumArgs);
+  }
+  // new[] an exception array if needed
+  if (NumExceptions) {
+    I.Fun.Exceptions = new DeclaratorChunk::TypeAndRange[NumExceptions];
+    for (unsigned i = 0; i != NumExceptions; ++i) {
+      I.Fun.Exceptions[i].Ty = Exceptions[i];
+      I.Fun.Exceptions[i].Range = ExceptionRanges[i];
+    }
+  }
+  return I;
+}
+
+/// getParsedSpecifiers - Return a bitmask of which flavors of specifiers this
+/// declaration specifier includes.
+///
+unsigned DeclSpec::getParsedSpecifiers() const {
+  unsigned Res = 0;
+  if (StorageClassSpec != SCS_unspecified ||
+      SCS_thread_specified)
+    Res |= PQ_StorageClassSpecifier;
+
+  if (TypeQualifiers != TQ_unspecified)
+    Res |= PQ_TypeQualifier;
+
+  if (hasTypeSpecifier())
+    Res |= PQ_TypeSpecifier;
+
+  if (FS_inline_specified || FS_virtual_specified || FS_explicit_specified)
+    Res |= PQ_FunctionSpecifier;
+  return Res;
+}
+
+template <class T> static bool BadSpecifier(T TNew, T TPrev,
+                                            const char *&PrevSpec,
+                                            unsigned &DiagID) {
+  PrevSpec = DeclSpec::getSpecifierName(TPrev);
+  DiagID = (TNew == TPrev ? diag::ext_duplicate_declspec
+            : diag::err_invalid_decl_spec_combination);
+  return true;
+}
+
+const char *DeclSpec::getSpecifierName(DeclSpec::SCS S) {
+  switch (S) {
+  case DeclSpec::SCS_unspecified: return "unspecified";
+  case DeclSpec::SCS_typedef:     return "typedef";
+  case DeclSpec::SCS_extern:      return "extern";
+  case DeclSpec::SCS_static:      return "static";
+  case DeclSpec::SCS_auto:        return "auto";
+  case DeclSpec::SCS_register:    return "register";
+  case DeclSpec::SCS_private_extern: return "__private_extern__";
+  case DeclSpec::SCS_mutable:     return "mutable";
+  }
+  llvm_unreachable("Unknown typespec!");
+}
+
+const char *DeclSpec::getSpecifierName(TSW W) {
+  switch (W) {
+  case TSW_unspecified: return "unspecified";
+  case TSW_short:       return "short";
+  case TSW_long:        return "long";
+  case TSW_longlong:    return "long long";
+  }
+  llvm_unreachable("Unknown typespec!");
+}
+
+const char *DeclSpec::getSpecifierName(TSC C) {
+  switch (C) {
+  case TSC_unspecified: return "unspecified";
+  case TSC_imaginary:   return "imaginary";
+  case TSC_complex:     return "complex";
+  }
+  llvm_unreachable("Unknown typespec!");
+}
+
+
+const char *DeclSpec::getSpecifierName(TSS S) {
+  switch (S) {
+  case TSS_unspecified: return "unspecified";
+  case TSS_signed:      return "signed";
+  case TSS_unsigned:    return "unsigned";
+  }
+  llvm_unreachable("Unknown typespec!");
+}
+
+const char *DeclSpec::getSpecifierName(DeclSpec::TST T) {
+  switch (T) {
+  case DeclSpec::TST_unspecified: return "unspecified";
+  case DeclSpec::TST_void:        return "void";
+  case DeclSpec::TST_char:        return "char";
+  case DeclSpec::TST_wchar:       return "wchar_t";
+  case DeclSpec::TST_char16:      return "char16_t";
+  case DeclSpec::TST_char32:      return "char32_t";
+  case DeclSpec::TST_int:         return "int";
+  case DeclSpec::TST_float:       return "float";
+  case DeclSpec::TST_double:      return "double";
+  case DeclSpec::TST_bool:        return "_Bool";
+  case DeclSpec::TST_decimal32:   return "_Decimal32";
+  case DeclSpec::TST_decimal64:   return "_Decimal64";
+  case DeclSpec::TST_decimal128:  return "_Decimal128";
+  case DeclSpec::TST_enum:        return "enum";
+  case DeclSpec::TST_class:       return "class";
+  case DeclSpec::TST_union:       return "union";
+  case DeclSpec::TST_struct:      return "struct";
+  case DeclSpec::TST_typename:    return "type-name";
+  case DeclSpec::TST_typeofType:
+  case DeclSpec::TST_typeofExpr:  return "typeof";
+  case DeclSpec::TST_auto:        return "auto";
+  case DeclSpec::TST_decltype:    return "(decltype)";
+  case DeclSpec::TST_error:       return "(error)";
+  }
+  llvm_unreachable("Unknown typespec!");
+}
+
+const char *DeclSpec::getSpecifierName(TQ T) {
+  switch (T) {
+  case DeclSpec::TQ_unspecified: return "unspecified";
+  case DeclSpec::TQ_const:       return "const";
+  case DeclSpec::TQ_restrict:    return "restrict";
+  case DeclSpec::TQ_volatile:    return "volatile";
+  }
+  llvm_unreachable("Unknown typespec!");
+}
+
+bool DeclSpec::SetStorageClassSpec(SCS S, SourceLocation Loc,
+                                   const char *&PrevSpec,
+                                   unsigned &DiagID) {
+  if (StorageClassSpec != SCS_unspecified)
+    return BadSpecifier(S, (SCS)StorageClassSpec, PrevSpec, DiagID);
+  StorageClassSpec = S;
+  StorageClassSpecLoc = Loc;
+  assert((unsigned)S == StorageClassSpec && "SCS constants overflow bitfield");
+  return false;
+}
+
+bool DeclSpec::SetStorageClassSpecThread(SourceLocation Loc,
+                                         const char *&PrevSpec,
+                                         unsigned &DiagID) {
+  if (SCS_thread_specified) {
+    PrevSpec = "__thread";
+    DiagID = diag::ext_duplicate_declspec;
+    return true;
+  }
+  SCS_thread_specified = true;
+  SCS_threadLoc = Loc;
+  return false;
+}
+
+
+/// These methods set the specified attribute of the DeclSpec, but return true
+/// and ignore the request if invalid (e.g. "extern" then "auto" is
+/// specified).
+bool DeclSpec::SetTypeSpecWidth(TSW W, SourceLocation Loc,
+                                const char *&PrevSpec,
+                                unsigned &DiagID) {
+  if (TypeSpecWidth != TSW_unspecified &&
+      // Allow turning long -> long long.
+      (W != TSW_longlong || TypeSpecWidth != TSW_long))
+    return BadSpecifier(W, (TSW)TypeSpecWidth, PrevSpec, DiagID);
+  TypeSpecWidth = W;
+  TSWLoc = Loc;
+  if (TypeAltiVecVector && ((TypeSpecWidth == TSW_long) || (TypeSpecWidth == TSW_longlong))) {
+    PrevSpec = DeclSpec::getSpecifierName((TST) TypeSpecType);
+    DiagID = diag::warn_vector_long_decl_spec_combination;
+    return true;
+  }
+  return false;
+}
+
+bool DeclSpec::SetTypeSpecComplex(TSC C, SourceLocation Loc,
+                                  const char *&PrevSpec,
+                                  unsigned &DiagID) {
+  if (TypeSpecComplex != TSC_unspecified)
+    return BadSpecifier(C, (TSC)TypeSpecComplex, PrevSpec, DiagID);
+  TypeSpecComplex = C;
+  TSCLoc = Loc;
+  return false;
+}
+
+bool DeclSpec::SetTypeSpecSign(TSS S, SourceLocation Loc,
+                               const char *&PrevSpec,
+                               unsigned &DiagID) {
+  if (TypeSpecSign != TSS_unspecified)
+    return BadSpecifier(S, (TSS)TypeSpecSign, PrevSpec, DiagID);
+  TypeSpecSign = S;
+  TSSLoc = Loc;
+  return false;
+}
+
+bool DeclSpec::SetTypeSpecType(TST T, SourceLocation Loc,
+                               const char *&PrevSpec,
+                               unsigned &DiagID,
+                               void *Rep, bool Owned) {
+  if (TypeSpecType != TST_unspecified) {
+    PrevSpec = DeclSpec::getSpecifierName((TST) TypeSpecType);
+    DiagID = diag::err_invalid_decl_spec_combination;
+    return true;
+  }
+  TypeSpecType = T;
+  TypeRep = Rep;
+  TSTLoc = Loc;
+  TypeSpecOwned = Owned;
+  if (TypeAltiVecVector && (TypeSpecType == TST_double)) {
+    PrevSpec = DeclSpec::getSpecifierName((TST) TypeSpecType);
+    DiagID = diag::err_invalid_vector_double_decl_spec_combination;
+    return true;
+  }
+  return false;
+}
+
+bool DeclSpec::SetTypeAltiVecVector(bool isAltiVecVector, SourceLocation Loc,
+                          const char *&PrevSpec, unsigned &DiagID) {
+  if (TypeSpecType != TST_unspecified) {
+    PrevSpec = DeclSpec::getSpecifierName((TST) TypeSpecType);
+    DiagID = diag::err_invalid_vector_decl_spec_combination;
+    return true;
+  }
+  TypeAltiVecVector = isAltiVecVector;
+  AltiVecLoc = Loc;
+  return false;
+}
+
+bool DeclSpec::SetTypeAltiVecPixel(bool isAltiVecPixel, SourceLocation Loc,
+                          const char *&PrevSpec, unsigned &DiagID) {
+  if (!TypeAltiVecVector || (TypeSpecType != TST_unspecified)) {
+    PrevSpec = DeclSpec::getSpecifierName((TST) TypeSpecType);
+    DiagID = diag::err_invalid_pixel_decl_spec_combination;
+    return true;
+  }
+  TypeSpecType = TST_int;
+  TypeSpecSign = TSS_unsigned;
+  TypeSpecWidth = TSW_short;
+  TypeAltiVecPixel = isAltiVecPixel;
+  TSTLoc = Loc;
+  return false;
+}
+
+bool DeclSpec::SetTypeSpecError() {
+  TypeSpecType = TST_error;
+  TypeRep = 0;
+  TSTLoc = SourceLocation();
+  return false;
+}
+
+bool DeclSpec::SetTypeQual(TQ T, SourceLocation Loc, const char *&PrevSpec,
+                           unsigned &DiagID, const LangOptions &Lang) {
+  // Duplicates turn into warnings pre-C99.
+  if ((TypeQualifiers & T) && !Lang.C99)
+    return BadSpecifier(T, T, PrevSpec, DiagID);
+  TypeQualifiers |= T;
+
+  switch (T) {
+  default: assert(0 && "Unknown type qualifier!");
+  case TQ_const:    TQ_constLoc = Loc; break;
+  case TQ_restrict: TQ_restrictLoc = Loc; break;
+  case TQ_volatile: TQ_volatileLoc = Loc; break;
+  }
+  return false;
+}
+
+bool DeclSpec::SetFunctionSpecInline(SourceLocation Loc, const char *&PrevSpec,
+                                     unsigned &DiagID) {
+  // 'inline inline' is ok.
+  FS_inline_specified = true;
+  FS_inlineLoc = Loc;
+  return false;
+}
+
+bool DeclSpec::SetFunctionSpecVirtual(SourceLocation Loc, const char *&PrevSpec,
+                                      unsigned &DiagID) {
+  // 'virtual virtual' is ok.
+  FS_virtual_specified = true;
+  FS_virtualLoc = Loc;
+  return false;
+}
+
+bool DeclSpec::SetFunctionSpecExplicit(SourceLocation Loc, const char *&PrevSpec,
+                                       unsigned &DiagID) {
+  // 'explicit explicit' is ok.
+  FS_explicit_specified = true;
+  FS_explicitLoc = Loc;
+  return false;
+}
+
+bool DeclSpec::SetFriendSpec(SourceLocation Loc, const char *&PrevSpec,
+                             unsigned &DiagID) {
+  if (Friend_specified) {
+    PrevSpec = "friend";
+    DiagID = diag::ext_duplicate_declspec;
+    return true;
+  }
+
+  Friend_specified = true;
+  FriendLoc = Loc;
+  return false;
+}
+
+bool DeclSpec::SetConstexprSpec(SourceLocation Loc, const char *&PrevSpec,
+                                unsigned &DiagID) {
+  // 'constexpr constexpr' is ok.
+  Constexpr_specified = true;
+  ConstexprLoc = Loc;
+  return false;
+}
+
+void DeclSpec::setProtocolQualifiers(const ActionBase::DeclPtrTy *Protos,
+                                     unsigned NP,
+                                     SourceLocation *ProtoLocs,
+                                     SourceLocation LAngleLoc) {
+  if (NP == 0) return;
+  ProtocolQualifiers = new ActionBase::DeclPtrTy[NP];
+  ProtocolLocs = new SourceLocation[NP];
+  memcpy((void*)ProtocolQualifiers, Protos, sizeof(ActionBase::DeclPtrTy)*NP);
+  memcpy(ProtocolLocs, ProtoLocs, sizeof(SourceLocation)*NP);
+  NumProtocolQualifiers = NP;
+  ProtocolLAngleLoc = LAngleLoc;
+}
+
+void DeclSpec::SaveWrittenBuiltinSpecs() {
+  writtenBS.Sign = getTypeSpecSign();
+  writtenBS.Width = getTypeSpecWidth();
+  writtenBS.Type = getTypeSpecType();
+  // Search the list of attributes for the presence of a mode attribute.
+  writtenBS.ModeAttr = false;
+  AttributeList* attrs = getAttributes();
+  while (attrs) {
+    if (attrs->getKind() == AttributeList::AT_mode) {
+      writtenBS.ModeAttr = true;
+      break;
+    }
+    attrs = attrs->getNext();
+  }
+}
+
+/// Finish - This does final analysis of the declspec, rejecting things like
+/// "_Imaginary" (lacking an FP type).  This returns a diagnostic to issue or
+/// diag::NUM_DIAGNOSTICS if there is no error.  After calling this method,
+/// DeclSpec is guaranteed self-consistent, even if an error occurred.
+void DeclSpec::Finish(Diagnostic &D, Preprocessor &PP) {
+  // Before possibly changing their values, save specs as written.
+  SaveWrittenBuiltinSpecs();
+
+  // Check the type specifier components first.
+  SourceManager &SrcMgr = PP.getSourceManager();
+
+  // signed/unsigned are only valid with int/char/wchar_t.
+  if (TypeSpecSign != TSS_unspecified) {
+    if (TypeSpecType == TST_unspecified)
+      TypeSpecType = TST_int; // unsigned -> unsigned int, signed -> signed int.
+    else if (TypeSpecType != TST_int  &&
+             TypeSpecType != TST_char && TypeSpecType != TST_wchar) {
+      Diag(D, TSSLoc, SrcMgr, diag::err_invalid_sign_spec)
+        << getSpecifierName((TST)TypeSpecType);
+      // signed double -> double.
+      TypeSpecSign = TSS_unspecified;
+    }
+  }
+
+  // Validate the width of the type.
+  switch (TypeSpecWidth) {
+  case TSW_unspecified: break;
+  case TSW_short:    // short int
+  case TSW_longlong: // long long int
+    if (TypeSpecType == TST_unspecified)
+      TypeSpecType = TST_int; // short -> short int, long long -> long long int.
+    else if (TypeSpecType != TST_int) {
+      Diag(D, TSWLoc, SrcMgr,
+           TypeSpecWidth == TSW_short ? diag::err_invalid_short_spec
+                                      : diag::err_invalid_longlong_spec)
+        <<  getSpecifierName((TST)TypeSpecType);
+      TypeSpecType = TST_int;
+    }
+    break;
+  case TSW_long:  // long double, long int
+    if (TypeSpecType == TST_unspecified)
+      TypeSpecType = TST_int;  // long -> long int.
+    else if (TypeSpecType != TST_int && TypeSpecType != TST_double) {
+      Diag(D, TSWLoc, SrcMgr, diag::err_invalid_long_spec)
+        << getSpecifierName((TST)TypeSpecType);
+      TypeSpecType = TST_int;
+    }
+    break;
+  }
+
+  // TODO: if the implementation does not implement _Complex or _Imaginary,
+  // disallow their use.  Need information about the backend.
+  if (TypeSpecComplex != TSC_unspecified) {
+    if (TypeSpecType == TST_unspecified) {
+      Diag(D, TSCLoc, SrcMgr, diag::ext_plain_complex)
+        << CodeModificationHint::CreateInsertion(
+                              PP.getLocForEndOfToken(getTypeSpecComplexLoc()),
+                                                 " double");
+      TypeSpecType = TST_double;   // _Complex -> _Complex double.
+    } else if (TypeSpecType == TST_int || TypeSpecType == TST_char) {
+      // Note that this intentionally doesn't include _Complex _Bool.
+      Diag(D, TSTLoc, SrcMgr, diag::ext_integer_complex);
+    } else if (TypeSpecType != TST_float && TypeSpecType != TST_double) {
+      Diag(D, TSCLoc, SrcMgr, diag::err_invalid_complex_spec)
+        << getSpecifierName((TST)TypeSpecType);
+      TypeSpecComplex = TSC_unspecified;
+    }
+  }
+
+  // C++ [class.friend]p6:
+  //   No storage-class-specifier shall appear in the decl-specifier-seq
+  //   of a friend declaration.
+  if (isFriendSpecified() && getStorageClassSpec()) {
+    DeclSpec::SCS SC = getStorageClassSpec();
+    const char *SpecName = getSpecifierName(SC);
+
+    SourceLocation SCLoc = getStorageClassSpecLoc();
+    SourceLocation SCEndLoc = SCLoc.getFileLocWithOffset(strlen(SpecName));
+
+    Diag(D, SCLoc, SrcMgr, diag::err_friend_storage_spec)
+      << SpecName
+      << CodeModificationHint::CreateRemoval(SourceRange(SCLoc, SCEndLoc));
+
+    ClearStorageClassSpecs();
+  }
+
+
+  // Okay, now we can infer the real type.
+
+  // TODO: return "auto function" and other bad things based on the real type.
+
+  // 'data definition has no type or storage class'?
+}
+
+bool DeclSpec::isMissingDeclaratorOk() {
+  TST tst = getTypeSpecType();
+  return (tst == TST_union
+       || tst == TST_struct
+       || tst == TST_class
+       || tst == TST_enum
+          ) && getTypeRep() != 0 && StorageClassSpec != DeclSpec::SCS_typedef;
+}
+
+void UnqualifiedId::clear() {
+  if (Kind == IK_TemplateId)
+    TemplateId->Destroy();
+  
+  Kind = IK_Identifier;
+  Identifier = 0;
+  StartLocation = SourceLocation();
+  EndLocation = SourceLocation();
+}
+
+void UnqualifiedId::setOperatorFunctionId(SourceLocation OperatorLoc, 
+                                          OverloadedOperatorKind Op,
+                                          SourceLocation SymbolLocations[3]) {
+  Kind = IK_OperatorFunctionId;
+  StartLocation = OperatorLoc;
+  EndLocation = OperatorLoc;
+  OperatorFunctionId.Operator = Op;
+  for (unsigned I = 0; I != 3; ++I) {
+    OperatorFunctionId.SymbolLocations[I] = SymbolLocations[I].getRawEncoding();
+    
+    if (SymbolLocations[I].isValid())
+      EndLocation = SymbolLocations[I];
+  }
+}
diff --git a/lib/Parse/Makefile b/lib/Parse/Makefile
new file mode 100644
index 0000000..de16e3e
--- /dev/null
+++ b/lib/Parse/Makefile
@@ -0,0 +1,21 @@
+##===- clang/lib/Parse/Makefile ----------------------------*- Makefile -*-===##
+# 
+#                     The LLVM Compiler Infrastructure
+#
+# This file is distributed under the University of Illinois Open Source
+# License. See LICENSE.TXT for details.
+# 
+##===----------------------------------------------------------------------===##
+#
+#  This implements the Parser library for the C-Language front-end.
+#
+##===----------------------------------------------------------------------===##
+
+LEVEL = ../../../..
+LIBRARYNAME := clangParse
+BUILD_ARCHIVE = 1
+
+CPPFLAGS += -I$(PROJ_SRC_DIR)/../../include -I$(PROJ_OBJ_DIR)/../../include
+
+include $(LEVEL)/Makefile.common
+
diff --git a/lib/Parse/MinimalAction.cpp b/lib/Parse/MinimalAction.cpp
new file mode 100644
index 0000000..5f48897
--- /dev/null
+++ b/lib/Parse/MinimalAction.cpp
@@ -0,0 +1,250 @@
+//===--- MinimalAction.cpp - Implement the MinimalAction class ------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+//  This file implements the MinimalAction interface.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Parse/Parser.h"
+#include "clang/Parse/DeclSpec.h"
+#include "clang/Parse/Scope.h"
+#include "clang/Basic/TargetInfo.h"
+#include "llvm/Support/Allocator.h"
+#include "llvm/Support/RecyclingAllocator.h"
+#include "llvm/Support/raw_ostream.h"
+using namespace clang;
+
+///  Out-of-line virtual destructor to provide home for ActionBase class.
+ActionBase::~ActionBase() {}
+
+///  Out-of-line virtual destructor to provide home for Action class.
+Action::~Action() {}
+
+// Defined out-of-line here because of dependecy on AttributeList
+Action::DeclPtrTy Action::ActOnUsingDirective(Scope *CurScope,
+                                              SourceLocation UsingLoc,
+                                              SourceLocation NamespcLoc,
+                                              const CXXScopeSpec &SS,
+                                              SourceLocation IdentLoc,
+                                              IdentifierInfo *NamespcName,
+                                              AttributeList *AttrList) {
+
+  // FIXME: Parser seems to assume that Action::ActOn* takes ownership over
+  // passed AttributeList, however other actions don't free it, is it
+  // temporary state or bug?
+  delete AttrList;
+  return DeclPtrTy();
+}
+
+// Defined out-of-line here because of dependency on AttributeList
+Action::DeclPtrTy Action::ActOnUsingDeclaration(Scope *CurScope,
+                                                AccessSpecifier AS,
+                                                bool HasUsingKeyword,
+                                                SourceLocation UsingLoc,
+                                                const CXXScopeSpec &SS,
+                                                UnqualifiedId &Name,
+                                                AttributeList *AttrList,
+                                                bool IsTypeName,
+                                                SourceLocation TypenameLoc) {
+
+  // FIXME: Parser seems to assume that Action::ActOn* takes ownership over
+  // passed AttributeList, however other actions don't free it, is it
+  // temporary state or bug?
+  delete AttrList;
+  return DeclPtrTy();
+}
+
+
+void PrettyStackTraceActionsDecl::print(llvm::raw_ostream &OS) const {
+  if (Loc.isValid()) {
+    Loc.print(OS, SM);
+    OS << ": ";
+  }
+  OS << Message;
+
+  std::string Name = Actions.getDeclName(TheDecl);
+  if (!Name.empty())
+    OS << " '" << Name << '\'';
+
+  OS << '\n';
+}
+
+/// TypeNameInfo - A link exists here for each scope that an identifier is
+/// defined.
+namespace {
+  struct TypeNameInfo {
+    TypeNameInfo *Prev;
+    bool isTypeName;
+
+    TypeNameInfo(bool istypename, TypeNameInfo *prev) {
+      isTypeName = istypename;
+      Prev = prev;
+    }
+  };
+
+  struct TypeNameInfoTable {
+    llvm::RecyclingAllocator<llvm::BumpPtrAllocator, TypeNameInfo> Allocator;
+
+    void AddEntry(bool isTypename, IdentifierInfo *II) {
+      TypeNameInfo *TI = Allocator.Allocate<TypeNameInfo>();
+      new (TI) TypeNameInfo(isTypename, II->getFETokenInfo<TypeNameInfo>());
+      II->setFETokenInfo(TI);
+    }
+
+    void DeleteEntry(TypeNameInfo *Entry) {
+      Entry->~TypeNameInfo();
+      Allocator.Deallocate(Entry);
+    }
+  };
+}
+
+static TypeNameInfoTable *getTable(void *TP) {
+  return static_cast<TypeNameInfoTable*>(TP);
+}
+
+MinimalAction::MinimalAction(Preprocessor &pp)
+  : Idents(pp.getIdentifierTable()), PP(pp) {
+  TypeNameInfoTablePtr = new TypeNameInfoTable();
+}
+
+MinimalAction::~MinimalAction() {
+  delete getTable(TypeNameInfoTablePtr);
+}
+
+void MinimalAction::ActOnTranslationUnitScope(SourceLocation Loc, Scope *S) {
+  TUScope = S;
+
+  TypeNameInfoTable &TNIT = *getTable(TypeNameInfoTablePtr);
+
+  if (PP.getTargetInfo().getPointerWidth(0) >= 64) {
+    // Install [u]int128_t for 64-bit targets.
+    TNIT.AddEntry(true, &Idents.get("__int128_t"));
+    TNIT.AddEntry(true, &Idents.get("__uint128_t"));
+  }
+
+  if (PP.getLangOptions().ObjC1) {
+    // Recognize the ObjC built-in type identifiers as types.
+    TNIT.AddEntry(true, &Idents.get("id"));
+    TNIT.AddEntry(true, &Idents.get("SEL"));
+    TNIT.AddEntry(true, &Idents.get("Class"));
+    TNIT.AddEntry(true, &Idents.get("Protocol"));
+  }
+}
+
+/// isTypeName - This looks at the IdentifierInfo::FETokenInfo field to
+/// determine whether the name is a type name (objc class name or typedef) or
+/// not in this scope.
+///
+/// FIXME: Use the passed CXXScopeSpec for accurate C++ type checking.
+Action::TypeTy *
+MinimalAction::getTypeName(IdentifierInfo &II, SourceLocation Loc,
+                           Scope *S, const CXXScopeSpec *SS,
+                           bool isClassName, TypeTy *ObjectType) {
+  if (TypeNameInfo *TI = II.getFETokenInfo<TypeNameInfo>())
+    if (TI->isTypeName)
+      return TI;
+  return 0;
+}
+
+/// isCurrentClassName - Always returns false, because MinimalAction
+/// does not support C++ classes with constructors.
+bool MinimalAction::isCurrentClassName(const IdentifierInfo &, Scope *,
+                                       const CXXScopeSpec *) {
+  return false;
+}
+
+TemplateNameKind
+MinimalAction::isTemplateName(Scope *S,
+                              const CXXScopeSpec &SS,
+                              UnqualifiedId &Name,
+                              TypeTy *ObjectType,
+                              bool EnteringScope,
+                              TemplateTy &TemplateDecl) {
+  return TNK_Non_template;
+}
+
+/// ActOnDeclarator - If this is a typedef declarator, we modify the
+/// IdentifierInfo::FETokenInfo field to keep track of this fact, until S is
+/// popped.
+Action::DeclPtrTy
+MinimalAction::ActOnDeclarator(Scope *S, Declarator &D) {
+  IdentifierInfo *II = D.getIdentifier();
+
+  // If there is no identifier associated with this declarator, bail out.
+  if (II == 0) return DeclPtrTy();
+
+  TypeNameInfo *weCurrentlyHaveTypeInfo = II->getFETokenInfo<TypeNameInfo>();
+  bool isTypeName =
+    D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_typedef;
+
+  // this check avoids creating TypeNameInfo objects for the common case.
+  // It does need to handle the uncommon case of shadowing a typedef name with a
+  // non-typedef name. e.g. { typedef int a; a xx; { int a; } }
+  if (weCurrentlyHaveTypeInfo || isTypeName) {
+    // Allocate and add the 'TypeNameInfo' "decl".
+    getTable(TypeNameInfoTablePtr)->AddEntry(isTypeName, II);
+
+    // Remember that this needs to be removed when the scope is popped.
+    S->AddDecl(DeclPtrTy::make(II));
+  }
+  return DeclPtrTy();
+}
+
+Action::DeclPtrTy
+MinimalAction::ActOnStartClassInterface(SourceLocation AtInterfaceLoc,
+                                        IdentifierInfo *ClassName,
+                                        SourceLocation ClassLoc,
+                                        IdentifierInfo *SuperName,
+                                        SourceLocation SuperLoc,
+                                        const DeclPtrTy *ProtoRefs,
+                                        unsigned NumProtocols,
+                                        const SourceLocation *ProtoLocs,
+                                        SourceLocation EndProtoLoc,
+                                        AttributeList *AttrList) {
+  // Allocate and add the 'TypeNameInfo' "decl".
+  getTable(TypeNameInfoTablePtr)->AddEntry(true, ClassName);
+  return DeclPtrTy();
+}
+
+/// ActOnForwardClassDeclaration -
+/// Scope will always be top level file scope.
+Action::DeclPtrTy
+MinimalAction::ActOnForwardClassDeclaration(SourceLocation AtClassLoc,
+                                            IdentifierInfo **IdentList,
+                                            SourceLocation *IdentLocs,
+                                            unsigned NumElts) {
+  for (unsigned i = 0; i != NumElts; ++i) {
+    // Allocate and add the 'TypeNameInfo' "decl".
+    getTable(TypeNameInfoTablePtr)->AddEntry(true, IdentList[i]);
+
+    // Remember that this needs to be removed when the scope is popped.
+    TUScope->AddDecl(DeclPtrTy::make(IdentList[i]));
+  }
+  return DeclPtrTy();
+}
+
+/// ActOnPopScope - When a scope is popped, if any typedefs are now
+/// out-of-scope, they are removed from the IdentifierInfo::FETokenInfo field.
+void MinimalAction::ActOnPopScope(SourceLocation Loc, Scope *S) {
+  TypeNameInfoTable &Table = *getTable(TypeNameInfoTablePtr);
+
+  for (Scope::decl_iterator I = S->decl_begin(), E = S->decl_end();
+       I != E; ++I) {
+    IdentifierInfo &II = *(*I).getAs<IdentifierInfo>();
+    TypeNameInfo *TI = II.getFETokenInfo<TypeNameInfo>();
+    assert(TI && "This decl didn't get pushed??");
+
+    if (TI) {
+      TypeNameInfo *Next = TI->Prev;
+      Table.DeleteEntry(TI);
+
+      II.setFETokenInfo(Next);
+    }
+  }
+}
diff --git a/lib/Parse/ParseCXXInlineMethods.cpp b/lib/Parse/ParseCXXInlineMethods.cpp
new file mode 100644
index 0000000..f1e639c
--- /dev/null
+++ b/lib/Parse/ParseCXXInlineMethods.cpp
@@ -0,0 +1,302 @@
+//===--- ParseCXXInlineMethods.cpp - C++ class inline methods parsing------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+//  This file implements parsing for C++ class inline methods.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Parse/ParseDiagnostic.h"
+#include "clang/Parse/Parser.h"
+#include "clang/Parse/DeclSpec.h"
+#include "clang/Parse/Scope.h"
+using namespace clang;
+
+/// ParseCXXInlineMethodDef - We parsed and verified that the specified
+/// Declarator is a well formed C++ inline method definition. Now lex its body
+/// and store its tokens for parsing after the C++ class is complete.
+Parser::DeclPtrTy
+Parser::ParseCXXInlineMethodDef(AccessSpecifier AS, Declarator &D,
+                                const ParsedTemplateInfo &TemplateInfo) {
+  assert(D.getTypeObject(0).Kind == DeclaratorChunk::Function &&
+         "This isn't a function declarator!");
+  assert((Tok.is(tok::l_brace) || Tok.is(tok::colon) || Tok.is(tok::kw_try)) &&
+         "Current token not a '{', ':' or 'try'!");
+
+  Action::MultiTemplateParamsArg TemplateParams(Actions,
+                                                TemplateInfo.TemplateParams? TemplateInfo.TemplateParams->data() : 0,
+                                                TemplateInfo.TemplateParams? TemplateInfo.TemplateParams->size() : 0);
+  DeclPtrTy FnD;
+  if (D.getDeclSpec().isFriendSpecified())
+    // FIXME: Friend templates
+    FnD = Actions.ActOnFriendFunctionDecl(CurScope, D, true, move(TemplateParams));
+  else // FIXME: pass template information through
+    FnD = Actions.ActOnCXXMemberDeclarator(CurScope, AS, D,
+                                           move(TemplateParams), 0, 0,
+                                           /*IsDefinition*/true);
+
+  HandleMemberFunctionDefaultArgs(D, FnD);
+
+  // Consume the tokens and store them for later parsing.
+
+  getCurrentClass().MethodDefs.push_back(LexedMethod(FnD));
+  getCurrentClass().MethodDefs.back().TemplateScope
+    = CurScope->isTemplateParamScope();
+  CachedTokens &Toks = getCurrentClass().MethodDefs.back().Toks;
+
+  tok::TokenKind kind = Tok.getKind();
+  // We may have a constructor initializer or function-try-block here.
+  if (kind == tok::colon || kind == tok::kw_try) {
+    // Consume everything up to (and including) the left brace.
+    if (!ConsumeAndStoreUntil(tok::l_brace, tok::unknown, Toks, tok::semi)) {
+      // We didn't find the left-brace we expected after the
+      // constructor initializer.
+      if (Tok.is(tok::semi)) {
+        // We found a semicolon; complain, consume the semicolon, and
+        // don't try to parse this method later.
+        Diag(Tok.getLocation(), diag::err_expected_lbrace);
+        ConsumeAnyToken();
+        getCurrentClass().MethodDefs.pop_back();
+        return FnD;
+      }
+    }
+
+  } else {
+    // Begin by storing the '{' token.
+    Toks.push_back(Tok);
+    ConsumeBrace();
+  }
+  // Consume everything up to (and including) the matching right brace.
+  ConsumeAndStoreUntil(tok::r_brace, tok::unknown, Toks);
+
+  // If we're in a function-try-block, we need to store all the catch blocks.
+  if (kind == tok::kw_try) {
+    while (Tok.is(tok::kw_catch)) {
+      ConsumeAndStoreUntil(tok::l_brace, tok::unknown, Toks);
+      ConsumeAndStoreUntil(tok::r_brace, tok::unknown, Toks);
+    }
+  }
+
+  return FnD;
+}
+
+/// ParseLexedMethodDeclarations - We finished parsing the member
+/// specification of a top (non-nested) C++ class. Now go over the
+/// stack of method declarations with some parts for which parsing was
+/// delayed (such as default arguments) and parse them.
+void Parser::ParseLexedMethodDeclarations(ParsingClass &Class) {
+  bool HasTemplateScope = !Class.TopLevelClass && Class.TemplateScope;
+  ParseScope TemplateScope(this, Scope::TemplateParamScope, HasTemplateScope);
+  if (HasTemplateScope)
+    Actions.ActOnReenterTemplateScope(CurScope, Class.TagOrTemplate);
+
+  // The current scope is still active if we're the top-level class.
+  // Otherwise we'll need to push and enter a new scope.
+  bool HasClassScope = !Class.TopLevelClass;
+  ParseScope ClassScope(this, Scope::ClassScope|Scope::DeclScope, HasClassScope);
+  if (HasClassScope)
+    Actions.ActOnStartDelayedMemberDeclarations(CurScope, Class.TagOrTemplate);
+
+  for (; !Class.MethodDecls.empty(); Class.MethodDecls.pop_front()) {
+    LateParsedMethodDeclaration &LM = Class.MethodDecls.front();
+
+    // If this is a member template, introduce the template parameter scope.
+    ParseScope TemplateScope(this, Scope::TemplateParamScope, LM.TemplateScope);
+    if (LM.TemplateScope)
+      Actions.ActOnReenterTemplateScope(CurScope, LM.Method);
+
+    // Start the delayed C++ method declaration
+    Actions.ActOnStartDelayedCXXMethodDeclaration(CurScope, LM.Method);
+
+    // Introduce the parameters into scope and parse their default
+    // arguments.
+    ParseScope PrototypeScope(this,
+                              Scope::FunctionPrototypeScope|Scope::DeclScope);
+    for (unsigned I = 0, N = LM.DefaultArgs.size(); I != N; ++I) {
+      // Introduce the parameter into scope.
+      Actions.ActOnDelayedCXXMethodParameter(CurScope, LM.DefaultArgs[I].Param);
+
+      if (CachedTokens *Toks = LM.DefaultArgs[I].Toks) {
+        // Parse the default argument from its saved token stream.
+        Toks->push_back(Tok); // So that the current token doesn't get lost
+        PP.EnterTokenStream(&Toks->front(), Toks->size(), true, false);
+
+        // Consume the previously-pushed token.
+        ConsumeAnyToken();
+
+        // Consume the '='.
+        assert(Tok.is(tok::equal) && "Default argument not starting with '='");
+        SourceLocation EqualLoc = ConsumeToken();
+
+        OwningExprResult DefArgResult(ParseAssignmentExpression());
+        if (DefArgResult.isInvalid())
+          Actions.ActOnParamDefaultArgumentError(LM.DefaultArgs[I].Param);
+        else
+          Actions.ActOnParamDefaultArgument(LM.DefaultArgs[I].Param, EqualLoc,
+                                            move(DefArgResult));
+        delete Toks;
+        LM.DefaultArgs[I].Toks = 0;
+      }
+    }
+    PrototypeScope.Exit();
+
+    // Finish the delayed C++ method declaration.
+    Actions.ActOnFinishDelayedCXXMethodDeclaration(CurScope, LM.Method);
+  }
+
+  for (unsigned I = 0, N = Class.NestedClasses.size(); I != N; ++I)
+    ParseLexedMethodDeclarations(*Class.NestedClasses[I]);
+
+  if (HasClassScope)
+    Actions.ActOnFinishDelayedMemberDeclarations(CurScope, Class.TagOrTemplate);
+}
+
+/// ParseLexedMethodDefs - We finished parsing the member specification of a top
+/// (non-nested) C++ class. Now go over the stack of lexed methods that were
+/// collected during its parsing and parse them all.
+void Parser::ParseLexedMethodDefs(ParsingClass &Class) {
+  bool HasTemplateScope = !Class.TopLevelClass && Class.TemplateScope;
+  ParseScope TemplateScope(this, Scope::TemplateParamScope, HasTemplateScope);
+  if (HasTemplateScope)
+    Actions.ActOnReenterTemplateScope(CurScope, Class.TagOrTemplate);
+
+  bool HasClassScope = !Class.TopLevelClass;
+  ParseScope ClassScope(this, Scope::ClassScope|Scope::DeclScope,
+                        HasClassScope);
+
+  for (; !Class.MethodDefs.empty(); Class.MethodDefs.pop_front()) {
+    LexedMethod &LM = Class.MethodDefs.front();
+
+    // If this is a member template, introduce the template parameter scope.
+    ParseScope TemplateScope(this, Scope::TemplateParamScope, LM.TemplateScope);
+    if (LM.TemplateScope)
+      Actions.ActOnReenterTemplateScope(CurScope, LM.D);
+
+    assert(!LM.Toks.empty() && "Empty body!");
+    // Append the current token at the end of the new token stream so that it
+    // doesn't get lost.
+    LM.Toks.push_back(Tok);
+    PP.EnterTokenStream(LM.Toks.data(), LM.Toks.size(), true, false);
+
+    // Consume the previously pushed token.
+    ConsumeAnyToken();
+    assert((Tok.is(tok::l_brace) || Tok.is(tok::colon) || Tok.is(tok::kw_try))
+           && "Inline method not starting with '{', ':' or 'try'");
+
+    // Parse the method body. Function body parsing code is similar enough
+    // to be re-used for method bodies as well.
+    ParseScope FnScope(this, Scope::FnScope|Scope::DeclScope);
+    Actions.ActOnStartOfFunctionDef(CurScope, LM.D);
+
+    if (Tok.is(tok::kw_try)) {
+      ParseFunctionTryBlock(LM.D);
+      continue;
+    }
+    if (Tok.is(tok::colon))
+      ParseConstructorInitializer(LM.D);
+    else
+      Actions.ActOnDefaultCtorInitializers(LM.D);
+
+    // FIXME: What if ParseConstructorInitializer doesn't leave us with a '{'??
+    ParseFunctionStatementBody(LM.D);
+  }
+
+  for (unsigned I = 0, N = Class.NestedClasses.size(); I != N; ++I)
+    ParseLexedMethodDefs(*Class.NestedClasses[I]);
+}
+
+/// ConsumeAndStoreUntil - Consume and store the token at the passed token
+/// container until the token 'T' is reached (which gets
+/// consumed/stored too, if ConsumeFinalToken).
+/// If EarlyAbortIf is specified, then we will stop early if we find that
+/// token at the top level.
+/// Returns true if token 'T1' or 'T2' was found.
+/// NOTE: This is a specialized version of Parser::SkipUntil.
+bool Parser::ConsumeAndStoreUntil(tok::TokenKind T1, tok::TokenKind T2,
+                                  CachedTokens &Toks,
+                                  tok::TokenKind EarlyAbortIf,
+                                  bool ConsumeFinalToken) {
+  // We always want this function to consume at least one token if the first
+  // token isn't T and if not at EOF.
+  bool isFirstTokenConsumed = true;
+  while (1) {
+    // If we found one of the tokens, stop and return true.
+    if (Tok.is(T1) || Tok.is(T2)) {
+      if (ConsumeFinalToken) {
+        Toks.push_back(Tok);
+        ConsumeAnyToken();
+      }
+      return true;
+    }
+
+    // If we found the early-abort token, return.
+    if (Tok.is(EarlyAbortIf))
+      return false;
+
+    switch (Tok.getKind()) {
+    case tok::eof:
+      // Ran out of tokens.
+      return false;
+
+    case tok::l_paren:
+      // Recursively consume properly-nested parens.
+      Toks.push_back(Tok);
+      ConsumeParen();
+      ConsumeAndStoreUntil(tok::r_paren, tok::unknown, Toks);
+      break;
+    case tok::l_square:
+      // Recursively consume properly-nested square brackets.
+      Toks.push_back(Tok);
+      ConsumeBracket();
+      ConsumeAndStoreUntil(tok::r_square, tok::unknown, Toks);
+      break;
+    case tok::l_brace:
+      // Recursively consume properly-nested braces.
+      Toks.push_back(Tok);
+      ConsumeBrace();
+      ConsumeAndStoreUntil(tok::r_brace, tok::unknown, Toks);
+      break;
+
+    // Okay, we found a ']' or '}' or ')', which we think should be balanced.
+    // Since the user wasn't looking for this token (if they were, it would
+    // already be handled), this isn't balanced.  If there is a LHS token at a
+    // higher level, we will assume that this matches the unbalanced token
+    // and return it.  Otherwise, this is a spurious RHS token, which we skip.
+    case tok::r_paren:
+      if (ParenCount && !isFirstTokenConsumed)
+        return false;  // Matches something.
+      Toks.push_back(Tok);
+      ConsumeParen();
+      break;
+    case tok::r_square:
+      if (BracketCount && !isFirstTokenConsumed)
+        return false;  // Matches something.
+      Toks.push_back(Tok);
+      ConsumeBracket();
+      break;
+    case tok::r_brace:
+      if (BraceCount && !isFirstTokenConsumed)
+        return false;  // Matches something.
+      Toks.push_back(Tok);
+      ConsumeBrace();
+      break;
+
+    case tok::string_literal:
+    case tok::wide_string_literal:
+      Toks.push_back(Tok);
+      ConsumeStringToken();
+      break;
+    default:
+      // consume this token.
+      Toks.push_back(Tok);
+      ConsumeToken();
+      break;
+    }
+    isFirstTokenConsumed = false;
+  }
+}
diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp
new file mode 100644
index 0000000..7856e62
--- /dev/null
+++ b/lib/Parse/ParseDecl.cpp
@@ -0,0 +1,3239 @@
+//===--- ParseDecl.cpp - Declaration Parsing ------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+//  This file implements the Declaration portions of the Parser interfaces.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Parse/Parser.h"
+#include "clang/Parse/ParseDiagnostic.h"
+#include "clang/Parse/Scope.h"
+#include "clang/Parse/Template.h"
+#include "RAIIObjectsForParser.h"
+#include "llvm/ADT/SmallSet.h"
+using namespace clang;
+
+//===----------------------------------------------------------------------===//
+// C99 6.7: Declarations.
+//===----------------------------------------------------------------------===//
+
+/// ParseTypeName
+///       type-name: [C99 6.7.6]
+///         specifier-qualifier-list abstract-declarator[opt]
+///
+/// Called type-id in C++.
+Action::TypeResult Parser::ParseTypeName(SourceRange *Range) {
+  // Parse the common declaration-specifiers piece.
+  DeclSpec DS;
+  ParseSpecifierQualifierList(DS);
+
+  // Parse the abstract-declarator, if present.
+  Declarator DeclaratorInfo(DS, Declarator::TypeNameContext);
+  ParseDeclarator(DeclaratorInfo);
+  if (Range)
+    *Range = DeclaratorInfo.getSourceRange();
+
+  if (DeclaratorInfo.isInvalidType())
+    return true;
+
+  return Actions.ActOnTypeName(CurScope, DeclaratorInfo);
+}
+
+/// ParseGNUAttributes - Parse a non-empty attributes list.
+///
+/// [GNU] attributes:
+///         attribute
+///         attributes attribute
+///
+/// [GNU]  attribute:
+///          '__attribute__' '(' '(' attribute-list ')' ')'
+///
+/// [GNU]  attribute-list:
+///          attrib
+///          attribute_list ',' attrib
+///
+/// [GNU]  attrib:
+///          empty
+///          attrib-name
+///          attrib-name '(' identifier ')'
+///          attrib-name '(' identifier ',' nonempty-expr-list ')'
+///          attrib-name '(' argument-expression-list [C99 6.5.2] ')'
+///
+/// [GNU]  attrib-name:
+///          identifier
+///          typespec
+///          typequal
+///          storageclass
+///
+/// FIXME: The GCC grammar/code for this construct implies we need two
+/// token lookahead. Comment from gcc: "If they start with an identifier
+/// which is followed by a comma or close parenthesis, then the arguments
+/// start with that identifier; otherwise they are an expression list."
+///
+/// At the moment, I am not doing 2 token lookahead. I am also unaware of
+/// any attributes that don't work (based on my limited testing). Most
+/// attributes are very simple in practice. Until we find a bug, I don't see
+/// a pressing need to implement the 2 token lookahead.
+
+AttributeList *Parser::ParseGNUAttributes(SourceLocation *EndLoc) {
+  assert(Tok.is(tok::kw___attribute) && "Not a GNU attribute list!");
+
+  AttributeList *CurrAttr = 0;
+
+  while (Tok.is(tok::kw___attribute)) {
+    ConsumeToken();
+    if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen_after,
+                         "attribute")) {
+      SkipUntil(tok::r_paren, true); // skip until ) or ;
+      return CurrAttr;
+    }
+    if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen_after, "(")) {
+      SkipUntil(tok::r_paren, true); // skip until ) or ;
+      return CurrAttr;
+    }
+    // Parse the attribute-list. e.g. __attribute__(( weak, alias("__f") ))
+    while (Tok.is(tok::identifier) || isDeclarationSpecifier() ||
+           Tok.is(tok::comma)) {
+
+      if (Tok.is(tok::comma)) {
+        // allows for empty/non-empty attributes. ((__vector_size__(16),,,,))
+        ConsumeToken();
+        continue;
+      }
+      // we have an identifier or declaration specifier (const, int, etc.)
+      IdentifierInfo *AttrName = Tok.getIdentifierInfo();
+      SourceLocation AttrNameLoc = ConsumeToken();
+
+      // check if we have a "paramterized" attribute
+      if (Tok.is(tok::l_paren)) {
+        ConsumeParen(); // ignore the left paren loc for now
+
+        if (Tok.is(tok::identifier)) {
+          IdentifierInfo *ParmName = Tok.getIdentifierInfo();
+          SourceLocation ParmLoc = ConsumeToken();
+
+          if (Tok.is(tok::r_paren)) {
+            // __attribute__(( mode(byte) ))
+            ConsumeParen(); // ignore the right paren loc for now
+            CurrAttr = new AttributeList(AttrName, AttrNameLoc, 0, AttrNameLoc,
+                                         ParmName, ParmLoc, 0, 0, CurrAttr);
+          } else if (Tok.is(tok::comma)) {
+            ConsumeToken();
+            // __attribute__(( format(printf, 1, 2) ))
+            ExprVector ArgExprs(Actions);
+            bool ArgExprsOk = true;
+
+            // now parse the non-empty comma separated list of expressions
+            while (1) {
+              OwningExprResult ArgExpr(ParseAssignmentExpression());
+              if (ArgExpr.isInvalid()) {
+                ArgExprsOk = false;
+                SkipUntil(tok::r_paren);
+                break;
+              } else {
+                ArgExprs.push_back(ArgExpr.release());
+              }
+              if (Tok.isNot(tok::comma))
+                break;
+              ConsumeToken(); // Eat the comma, move to the next argument
+            }
+            if (ArgExprsOk && Tok.is(tok::r_paren)) {
+              ConsumeParen(); // ignore the right paren loc for now
+              CurrAttr = new AttributeList(AttrName, AttrNameLoc, 0,
+                                           AttrNameLoc, ParmName, ParmLoc,
+                                           ArgExprs.take(), ArgExprs.size(),
+                                           CurrAttr);
+            }
+          }
+        } else { // not an identifier
+          switch (Tok.getKind()) {
+          case tok::r_paren:
+          // parse a possibly empty comma separated list of expressions
+            // __attribute__(( nonnull() ))
+            ConsumeParen(); // ignore the right paren loc for now
+            CurrAttr = new AttributeList(AttrName, AttrNameLoc, 0, AttrNameLoc,
+                                         0, SourceLocation(), 0, 0, CurrAttr);
+            break;
+          case tok::kw_char:
+          case tok::kw_wchar_t:
+          case tok::kw_char16_t:
+          case tok::kw_char32_t:
+          case tok::kw_bool:
+          case tok::kw_short:
+          case tok::kw_int:
+          case tok::kw_long:
+          case tok::kw_signed:
+          case tok::kw_unsigned:
+          case tok::kw_float:
+          case tok::kw_double:
+          case tok::kw_void:
+          case tok::kw_typeof:
+            // If it's a builtin type name, eat it and expect a rparen
+            // __attribute__(( vec_type_hint(char) ))
+            ConsumeToken();
+            CurrAttr = new AttributeList(AttrName, AttrNameLoc, 0, AttrNameLoc,
+                                         0, SourceLocation(), 0, 0, CurrAttr);
+            if (Tok.is(tok::r_paren))
+              ConsumeParen();
+            break;
+          default:
+            // __attribute__(( aligned(16) ))
+            ExprVector ArgExprs(Actions);
+            bool ArgExprsOk = true;
+
+            // now parse the list of expressions
+            while (1) {
+              OwningExprResult ArgExpr(ParseAssignmentExpression());
+              if (ArgExpr.isInvalid()) {
+                ArgExprsOk = false;
+                SkipUntil(tok::r_paren);
+                break;
+              } else {
+                ArgExprs.push_back(ArgExpr.release());
+              }
+              if (Tok.isNot(tok::comma))
+                break;
+              ConsumeToken(); // Eat the comma, move to the next argument
+            }
+            // Match the ')'.
+            if (ArgExprsOk && Tok.is(tok::r_paren)) {
+              ConsumeParen(); // ignore the right paren loc for now
+              CurrAttr = new AttributeList(AttrName, AttrNameLoc, 0,
+                           AttrNameLoc, 0, SourceLocation(), ArgExprs.take(),
+                           ArgExprs.size(),
+                           CurrAttr);
+            }
+            break;
+          }
+        }
+      } else {
+        CurrAttr = new AttributeList(AttrName, AttrNameLoc, 0, AttrNameLoc,
+                                     0, SourceLocation(), 0, 0, CurrAttr);
+      }
+    }
+    if (ExpectAndConsume(tok::r_paren, diag::err_expected_rparen))
+      SkipUntil(tok::r_paren, false);
+    SourceLocation Loc = Tok.getLocation();
+    if (ExpectAndConsume(tok::r_paren, diag::err_expected_rparen)) {
+      SkipUntil(tok::r_paren, false);
+    }
+    if (EndLoc)
+      *EndLoc = Loc;
+  }
+  return CurrAttr;
+}
+
+/// ParseMicrosoftDeclSpec - Parse an __declspec construct
+///
+/// [MS] decl-specifier:
+///             __declspec ( extended-decl-modifier-seq )
+///
+/// [MS] extended-decl-modifier-seq:
+///             extended-decl-modifier[opt]
+///             extended-decl-modifier extended-decl-modifier-seq
+
+AttributeList* Parser::ParseMicrosoftDeclSpec(AttributeList *CurrAttr) {
+  assert(Tok.is(tok::kw___declspec) && "Not a declspec!");
+
+  ConsumeToken();
+  if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen_after,
+                       "declspec")) {
+    SkipUntil(tok::r_paren, true); // skip until ) or ;
+    return CurrAttr;
+  }
+  while (Tok.getIdentifierInfo()) {
+    IdentifierInfo *AttrName = Tok.getIdentifierInfo();
+    SourceLocation AttrNameLoc = ConsumeToken();
+    if (Tok.is(tok::l_paren)) {
+      ConsumeParen();
+      // FIXME: This doesn't parse __declspec(property(get=get_func_name))
+      // correctly.
+      OwningExprResult ArgExpr(ParseAssignmentExpression());
+      if (!ArgExpr.isInvalid()) {
+        ExprTy* ExprList = ArgExpr.take();
+        CurrAttr = new AttributeList(AttrName, AttrNameLoc, 0, AttrNameLoc, 0,
+                                     SourceLocation(), &ExprList, 1,
+                                     CurrAttr, true);
+      }
+      if (ExpectAndConsume(tok::r_paren, diag::err_expected_rparen))
+        SkipUntil(tok::r_paren, false);
+    } else {
+      CurrAttr = new AttributeList(AttrName, AttrNameLoc, 0, AttrNameLoc,
+                                   0, SourceLocation(), 0, 0, CurrAttr, true);
+    }
+  }
+  if (ExpectAndConsume(tok::r_paren, diag::err_expected_rparen))
+    SkipUntil(tok::r_paren, false);
+  return CurrAttr;
+}
+
+AttributeList* Parser::ParseMicrosoftTypeAttributes(AttributeList *CurrAttr) {
+  // Treat these like attributes
+  // FIXME: Allow Sema to distinguish between these and real attributes!
+  while (Tok.is(tok::kw___fastcall) || Tok.is(tok::kw___stdcall) ||
+         Tok.is(tok::kw___cdecl)    || Tok.is(tok::kw___ptr64) ||
+         Tok.is(tok::kw___w64)) {
+    IdentifierInfo *AttrName = Tok.getIdentifierInfo();
+    SourceLocation AttrNameLoc = ConsumeToken();
+    if (Tok.is(tok::kw___ptr64) || Tok.is(tok::kw___w64))
+      // FIXME: Support these properly!
+      continue;
+    CurrAttr = new AttributeList(AttrName, AttrNameLoc, 0, AttrNameLoc, 0,
+                                 SourceLocation(), 0, 0, CurrAttr, true);
+  }
+  return CurrAttr;
+}
+
+/// ParseDeclaration - Parse a full 'declaration', which consists of
+/// declaration-specifiers, some number of declarators, and a semicolon.
+/// 'Context' should be a Declarator::TheContext value.  This returns the
+/// location of the semicolon in DeclEnd.
+///
+///       declaration: [C99 6.7]
+///         block-declaration ->
+///           simple-declaration
+///           others                   [FIXME]
+/// [C++]   template-declaration
+/// [C++]   namespace-definition
+/// [C++]   using-directive
+/// [C++]   using-declaration
+/// [C++0x] static_assert-declaration
+///         others... [FIXME]
+///
+Parser::DeclGroupPtrTy Parser::ParseDeclaration(unsigned Context,
+                                                SourceLocation &DeclEnd,
+                                                CXX0XAttributeList Attr) {
+  DeclPtrTy SingleDecl;
+  switch (Tok.getKind()) {
+  case tok::kw_template:
+  case tok::kw_export:
+    if (Attr.HasAttr)
+      Diag(Attr.Range.getBegin(), diag::err_attributes_not_allowed)
+        << Attr.Range;
+    SingleDecl = ParseDeclarationStartingWithTemplate(Context, DeclEnd);
+    break;
+  case tok::kw_namespace:
+    if (Attr.HasAttr)
+      Diag(Attr.Range.getBegin(), diag::err_attributes_not_allowed)
+        << Attr.Range;
+    SingleDecl = ParseNamespace(Context, DeclEnd);
+    break;
+  case tok::kw_using:
+    SingleDecl = ParseUsingDirectiveOrDeclaration(Context, DeclEnd, Attr);
+    break;
+  case tok::kw_static_assert:
+    if (Attr.HasAttr)
+      Diag(Attr.Range.getBegin(), diag::err_attributes_not_allowed)
+        << Attr.Range;
+    SingleDecl = ParseStaticAssertDeclaration(DeclEnd);
+    break;
+  default:
+    return ParseSimpleDeclaration(Context, DeclEnd, Attr.AttrList);
+  }
+  
+  // This routine returns a DeclGroup, if the thing we parsed only contains a
+  // single decl, convert it now.
+  return Actions.ConvertDeclToDeclGroup(SingleDecl);
+}
+
+///       simple-declaration: [C99 6.7: declaration] [C++ 7p1: dcl.dcl]
+///         declaration-specifiers init-declarator-list[opt] ';'
+///[C90/C++]init-declarator-list ';'                             [TODO]
+/// [OMP]   threadprivate-directive                              [TODO]
+///
+/// If RequireSemi is false, this does not check for a ';' at the end of the
+/// declaration.
+Parser::DeclGroupPtrTy Parser::ParseSimpleDeclaration(unsigned Context,
+                                                      SourceLocation &DeclEnd,
+                                                      AttributeList *Attr) {
+  // Parse the common declaration-specifiers piece.
+  ParsingDeclSpec DS(*this);
+  if (Attr)
+    DS.AddAttributes(Attr);
+  ParseDeclarationSpecifiers(DS, ParsedTemplateInfo(), AS_none,
+                            getDeclSpecContextFromDeclaratorContext(Context));
+
+  // C99 6.7.2.3p6: Handle "struct-or-union identifier;", "enum { X };"
+  // declaration-specifiers init-declarator-list[opt] ';'
+  if (Tok.is(tok::semi)) {
+    ConsumeToken();
+    DeclPtrTy TheDecl = Actions.ParsedFreeStandingDeclSpec(CurScope, DS);
+    DS.complete(TheDecl);
+    return Actions.ConvertDeclToDeclGroup(TheDecl);
+  }
+
+  DeclGroupPtrTy DG = ParseDeclGroup(DS, Context, /*FunctionDefs=*/ false,
+                                     &DeclEnd);
+  return DG;
+}
+
+/// ParseDeclGroup - Having concluded that this is either a function
+/// definition or a group of object declarations, actually parse the
+/// result.
+Parser::DeclGroupPtrTy Parser::ParseDeclGroup(ParsingDeclSpec &DS,
+                                              unsigned Context,
+                                              bool AllowFunctionDefinitions,
+                                              SourceLocation *DeclEnd) {
+  // Parse the first declarator.
+  ParsingDeclarator D(*this, DS, static_cast<Declarator::TheContext>(Context));
+  ParseDeclarator(D);
+
+  // Bail out if the first declarator didn't seem well-formed.
+  if (!D.hasName() && !D.mayOmitIdentifier()) {
+    // Skip until ; or }.
+    SkipUntil(tok::r_brace, true, true);
+    if (Tok.is(tok::semi))
+      ConsumeToken();
+    return DeclGroupPtrTy();
+  }
+
+  if (AllowFunctionDefinitions && D.isFunctionDeclarator()) {
+    if (isDeclarationAfterDeclarator()) {
+      // Fall though.  We have to check this first, though, because
+      // __attribute__ might be the start of a function definition in
+      // (extended) K&R C.
+    } else if (isStartOfFunctionDefinition()) {
+      if (DS.getStorageClassSpec() == DeclSpec::SCS_typedef) {
+        Diag(Tok, diag::err_function_declared_typedef);
+
+        // Recover by treating the 'typedef' as spurious.
+        DS.ClearStorageClassSpecs();
+      }
+
+      DeclPtrTy TheDecl = ParseFunctionDefinition(D);
+      return Actions.ConvertDeclToDeclGroup(TheDecl);
+    } else {
+      Diag(Tok, diag::err_expected_fn_body);
+      SkipUntil(tok::semi);
+      return DeclGroupPtrTy();
+    }
+  }
+
+  llvm::SmallVector<DeclPtrTy, 8> DeclsInGroup;
+  DeclPtrTy FirstDecl = ParseDeclarationAfterDeclarator(D);
+  D.complete(FirstDecl);
+  if (FirstDecl.get())
+    DeclsInGroup.push_back(FirstDecl);
+
+  // If we don't have a comma, it is either the end of the list (a ';') or an
+  // error, bail out.
+  while (Tok.is(tok::comma)) {
+    // Consume the comma.
+    ConsumeToken();
+
+    // Parse the next declarator.
+    D.clear();
+
+    // Accept attributes in an init-declarator.  In the first declarator in a
+    // declaration, these would be part of the declspec.  In subsequent
+    // declarators, they become part of the declarator itself, so that they
+    // don't apply to declarators after *this* one.  Examples:
+    //    short __attribute__((common)) var;    -> declspec
+    //    short var __attribute__((common));    -> declarator
+    //    short x, __attribute__((common)) var;    -> declarator
+    if (Tok.is(tok::kw___attribute)) {
+      SourceLocation Loc;
+      AttributeList *AttrList = ParseGNUAttributes(&Loc);
+      D.AddAttributes(AttrList, Loc);
+    }
+
+    ParseDeclarator(D);
+
+    DeclPtrTy ThisDecl = ParseDeclarationAfterDeclarator(D);
+    D.complete(ThisDecl);
+    if (ThisDecl.get())
+      DeclsInGroup.push_back(ThisDecl);    
+  }
+
+  if (DeclEnd)
+    *DeclEnd = Tok.getLocation();
+
+  if (Context != Declarator::ForContext &&
+      ExpectAndConsume(tok::semi,
+                       Context == Declarator::FileContext
+                         ? diag::err_invalid_token_after_toplevel_declarator
+                         : diag::err_expected_semi_declaration)) {
+    SkipUntil(tok::r_brace, true, true);
+    if (Tok.is(tok::semi))
+      ConsumeToken();
+  }
+
+  return Actions.FinalizeDeclaratorGroup(CurScope, DS,
+                                         DeclsInGroup.data(),
+                                         DeclsInGroup.size());
+}
+
+/// \brief Parse 'declaration' after parsing 'declaration-specifiers
+/// declarator'. This method parses the remainder of the declaration
+/// (including any attributes or initializer, among other things) and
+/// finalizes the declaration.
+///
+///       init-declarator: [C99 6.7]
+///         declarator
+///         declarator '=' initializer
+/// [GNU]   declarator simple-asm-expr[opt] attributes[opt]
+/// [GNU]   declarator simple-asm-expr[opt] attributes[opt] '=' initializer
+/// [C++]   declarator initializer[opt]
+///
+/// [C++] initializer:
+/// [C++]   '=' initializer-clause
+/// [C++]   '(' expression-list ')'
+/// [C++0x] '=' 'default'                                                [TODO]
+/// [C++0x] '=' 'delete'
+///
+/// According to the standard grammar, =default and =delete are function
+/// definitions, but that definitely doesn't fit with the parser here.
+///
+Parser::DeclPtrTy Parser::ParseDeclarationAfterDeclarator(Declarator &D,
+                                     const ParsedTemplateInfo &TemplateInfo) {
+  // If a simple-asm-expr is present, parse it.
+  if (Tok.is(tok::kw_asm)) {
+    SourceLocation Loc;
+    OwningExprResult AsmLabel(ParseSimpleAsm(&Loc));
+    if (AsmLabel.isInvalid()) {
+      SkipUntil(tok::semi, true, true);
+      return DeclPtrTy();
+    }
+
+    D.setAsmLabel(AsmLabel.release());
+    D.SetRangeEnd(Loc);
+  }
+
+  // If attributes are present, parse them.
+  if (Tok.is(tok::kw___attribute)) {
+    SourceLocation Loc;
+    AttributeList *AttrList = ParseGNUAttributes(&Loc);
+    D.AddAttributes(AttrList, Loc);
+  }
+
+  // Inform the current actions module that we just parsed this declarator.
+  DeclPtrTy ThisDecl;
+  switch (TemplateInfo.Kind) {
+  case ParsedTemplateInfo::NonTemplate:
+    ThisDecl = Actions.ActOnDeclarator(CurScope, D);
+    break;
+      
+  case ParsedTemplateInfo::Template:
+  case ParsedTemplateInfo::ExplicitSpecialization:
+    ThisDecl = Actions.ActOnTemplateDeclarator(CurScope,
+                             Action::MultiTemplateParamsArg(Actions,
+                                          TemplateInfo.TemplateParams->data(),
+                                          TemplateInfo.TemplateParams->size()),
+                                               D);
+    break;
+      
+  case ParsedTemplateInfo::ExplicitInstantiation: {
+    Action::DeclResult ThisRes 
+      = Actions.ActOnExplicitInstantiation(CurScope,
+                                           TemplateInfo.ExternLoc,
+                                           TemplateInfo.TemplateLoc,
+                                           D);
+    if (ThisRes.isInvalid()) {
+      SkipUntil(tok::semi, true, true);
+      return DeclPtrTy();
+    }
+    
+    ThisDecl = ThisRes.get();
+    break;
+    }
+  }
+
+  // Parse declarator '=' initializer.
+  if (Tok.is(tok::equal)) {
+    ConsumeToken();
+    if (getLang().CPlusPlus0x && Tok.is(tok::kw_delete)) {
+      SourceLocation DelLoc = ConsumeToken();
+      Actions.SetDeclDeleted(ThisDecl, DelLoc);
+    } else {
+      if (getLang().CPlusPlus && D.getCXXScopeSpec().isSet()) {
+        EnterScope(0);
+        Actions.ActOnCXXEnterDeclInitializer(CurScope, ThisDecl);
+      }
+
+      OwningExprResult Init(ParseInitializer());
+
+      if (getLang().CPlusPlus && D.getCXXScopeSpec().isSet()) {
+        Actions.ActOnCXXExitDeclInitializer(CurScope, ThisDecl);
+        ExitScope();
+      }
+
+      if (Init.isInvalid()) {
+        SkipUntil(tok::semi, true, true);
+        return DeclPtrTy();
+      }
+      Actions.AddInitializerToDecl(ThisDecl, move(Init));
+    }
+  } else if (Tok.is(tok::l_paren)) {
+    // Parse C++ direct initializer: '(' expression-list ')'
+    SourceLocation LParenLoc = ConsumeParen();
+    ExprVector Exprs(Actions);
+    CommaLocsTy CommaLocs;
+
+    if (getLang().CPlusPlus && D.getCXXScopeSpec().isSet()) {
+      EnterScope(0);
+      Actions.ActOnCXXEnterDeclInitializer(CurScope, ThisDecl);
+    }
+
+    if (ParseExpressionList(Exprs, CommaLocs)) {
+      SkipUntil(tok::r_paren);
+
+      if (getLang().CPlusPlus && D.getCXXScopeSpec().isSet()) {
+        Actions.ActOnCXXExitDeclInitializer(CurScope, ThisDecl);
+        ExitScope();
+      }
+    } else {
+      // Match the ')'.
+      SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc);
+
+      assert(!Exprs.empty() && Exprs.size()-1 == CommaLocs.size() &&
+             "Unexpected number of commas!");
+
+      if (getLang().CPlusPlus && D.getCXXScopeSpec().isSet()) {
+        Actions.ActOnCXXExitDeclInitializer(CurScope, ThisDecl);
+        ExitScope();
+      }
+
+      Actions.AddCXXDirectInitializerToDecl(ThisDecl, LParenLoc,
+                                            move_arg(Exprs),
+                                            CommaLocs.data(), RParenLoc);
+    }
+  } else {
+    bool TypeContainsUndeducedAuto =
+      D.getDeclSpec().getTypeSpecType() == DeclSpec::TST_auto;
+    Actions.ActOnUninitializedDecl(ThisDecl, TypeContainsUndeducedAuto);
+  }
+
+  return ThisDecl;
+}
+
+/// ParseSpecifierQualifierList
+///        specifier-qualifier-list:
+///          type-specifier specifier-qualifier-list[opt]
+///          type-qualifier specifier-qualifier-list[opt]
+/// [GNU]    attributes     specifier-qualifier-list[opt]
+///
+void Parser::ParseSpecifierQualifierList(DeclSpec &DS) {
+  /// specifier-qualifier-list is a subset of declaration-specifiers.  Just
+  /// parse declaration-specifiers and complain about extra stuff.
+  ParseDeclarationSpecifiers(DS);
+
+  // Validate declspec for type-name.
+  unsigned Specs = DS.getParsedSpecifiers();
+  if (Specs == DeclSpec::PQ_None && !DS.getNumProtocolQualifiers() &&
+      !DS.getAttributes())
+    Diag(Tok, diag::err_typename_requires_specqual);
+
+  // Issue diagnostic and remove storage class if present.
+  if (Specs & DeclSpec::PQ_StorageClassSpecifier) {
+    if (DS.getStorageClassSpecLoc().isValid())
+      Diag(DS.getStorageClassSpecLoc(),diag::err_typename_invalid_storageclass);
+    else
+      Diag(DS.getThreadSpecLoc(), diag::err_typename_invalid_storageclass);
+    DS.ClearStorageClassSpecs();
+  }
+
+  // Issue diagnostic and remove function specfier if present.
+  if (Specs & DeclSpec::PQ_FunctionSpecifier) {
+    if (DS.isInlineSpecified())
+      Diag(DS.getInlineSpecLoc(), diag::err_typename_invalid_functionspec);
+    if (DS.isVirtualSpecified())
+      Diag(DS.getVirtualSpecLoc(), diag::err_typename_invalid_functionspec);
+    if (DS.isExplicitSpecified())
+      Diag(DS.getExplicitSpecLoc(), diag::err_typename_invalid_functionspec);
+    DS.ClearFunctionSpecs();
+  }
+}
+
+/// isValidAfterIdentifierInDeclaratorAfterDeclSpec - Return true if the
+/// specified token is valid after the identifier in a declarator which
+/// immediately follows the declspec.  For example, these things are valid:
+///
+///      int x   [             4];         // direct-declarator
+///      int x   (             int y);     // direct-declarator
+///  int(int x   )                         // direct-declarator
+///      int x   ;                         // simple-declaration
+///      int x   =             17;         // init-declarator-list
+///      int x   ,             y;          // init-declarator-list
+///      int x   __asm__       ("foo");    // init-declarator-list
+///      int x   :             4;          // struct-declarator
+///      int x   {             5};         // C++'0x unified initializers
+///
+/// This is not, because 'x' does not immediately follow the declspec (though
+/// ')' happens to be valid anyway).
+///    int (x)
+///
+static bool isValidAfterIdentifierInDeclarator(const Token &T) {
+  return T.is(tok::l_square) || T.is(tok::l_paren) || T.is(tok::r_paren) ||
+         T.is(tok::semi) || T.is(tok::comma) || T.is(tok::equal) ||
+         T.is(tok::kw_asm) || T.is(tok::l_brace) || T.is(tok::colon);
+}
+
+
+/// ParseImplicitInt - This method is called when we have an non-typename
+/// identifier in a declspec (which normally terminates the decl spec) when
+/// the declspec has no type specifier.  In this case, the declspec is either
+/// malformed or is "implicit int" (in K&R and C89).
+///
+/// This method handles diagnosing this prettily and returns false if the
+/// declspec is done being processed.  If it recovers and thinks there may be
+/// other pieces of declspec after it, it returns true.
+///
+bool Parser::ParseImplicitInt(DeclSpec &DS, CXXScopeSpec *SS,
+                              const ParsedTemplateInfo &TemplateInfo,
+                              AccessSpecifier AS) {
+  assert(Tok.is(tok::identifier) && "should have identifier");
+
+  SourceLocation Loc = Tok.getLocation();
+  // If we see an identifier that is not a type name, we normally would
+  // parse it as the identifer being declared.  However, when a typename
+  // is typo'd or the definition is not included, this will incorrectly
+  // parse the typename as the identifier name and fall over misparsing
+  // later parts of the diagnostic.
+  //
+  // As such, we try to do some look-ahead in cases where this would
+  // otherwise be an "implicit-int" case to see if this is invalid.  For
+  // example: "static foo_t x = 4;"  In this case, if we parsed foo_t as
+  // an identifier with implicit int, we'd get a parse error because the
+  // next token is obviously invalid for a type.  Parse these as a case
+  // with an invalid type specifier.
+  assert(!DS.hasTypeSpecifier() && "Type specifier checked above");
+
+  // Since we know that this either implicit int (which is rare) or an
+  // error, we'd do lookahead to try to do better recovery.
+  if (isValidAfterIdentifierInDeclarator(NextToken())) {
+    // If this token is valid for implicit int, e.g. "static x = 4", then
+    // we just avoid eating the identifier, so it will be parsed as the
+    // identifier in the declarator.
+    return false;
+  }
+
+  // Otherwise, if we don't consume this token, we are going to emit an
+  // error anyway.  Try to recover from various common problems.  Check
+  // to see if this was a reference to a tag name without a tag specified.
+  // This is a common problem in C (saying 'foo' instead of 'struct foo').
+  //
+  // C++ doesn't need this, and isTagName doesn't take SS.
+  if (SS == 0) {
+    const char *TagName = 0;
+    tok::TokenKind TagKind = tok::unknown;
+
+    switch (Actions.isTagName(*Tok.getIdentifierInfo(), CurScope)) {
+      default: break;
+      case DeclSpec::TST_enum:  TagName="enum"  ;TagKind=tok::kw_enum  ;break;
+      case DeclSpec::TST_union: TagName="union" ;TagKind=tok::kw_union ;break;
+      case DeclSpec::TST_struct:TagName="struct";TagKind=tok::kw_struct;break;
+      case DeclSpec::TST_class: TagName="class" ;TagKind=tok::kw_class ;break;
+    }
+
+    if (TagName) {
+      Diag(Loc, diag::err_use_of_tag_name_without_tag)
+        << Tok.getIdentifierInfo() << TagName
+        << CodeModificationHint::CreateInsertion(Tok.getLocation(),TagName);
+
+      // Parse this as a tag as if the missing tag were present.
+      if (TagKind == tok::kw_enum)
+        ParseEnumSpecifier(Loc, DS, AS);
+      else
+        ParseClassSpecifier(TagKind, Loc, DS, TemplateInfo, AS);
+      return true;
+    }
+  }
+
+  // This is almost certainly an invalid type name. Let the action emit a 
+  // diagnostic and attempt to recover.
+  Action::TypeTy *T = 0;
+  if (Actions.DiagnoseUnknownTypeName(*Tok.getIdentifierInfo(), Loc,
+                                      CurScope, SS, T)) {
+    // The action emitted a diagnostic, so we don't have to.
+    if (T) {
+      // The action has suggested that the type T could be used. Set that as
+      // the type in the declaration specifiers, consume the would-be type
+      // name token, and we're done.
+      const char *PrevSpec;
+      unsigned DiagID;
+      DS.SetTypeSpecType(DeclSpec::TST_typename, Loc, PrevSpec, DiagID, T, 
+                         false);
+      DS.SetRangeEnd(Tok.getLocation());
+      ConsumeToken();
+      
+      // There may be other declaration specifiers after this.
+      return true;
+    }
+    
+    // Fall through; the action had no suggestion for us.
+  } else {
+    // The action did not emit a diagnostic, so emit one now.
+    SourceRange R;
+    if (SS) R = SS->getRange();
+    Diag(Loc, diag::err_unknown_typename) << Tok.getIdentifierInfo() << R;
+  }
+
+  // Mark this as an error.
+  const char *PrevSpec;
+  unsigned DiagID;
+  DS.SetTypeSpecType(DeclSpec::TST_error, Loc, PrevSpec, DiagID);
+  DS.SetRangeEnd(Tok.getLocation());
+  ConsumeToken();
+
+  // TODO: Could inject an invalid typedef decl in an enclosing scope to
+  // avoid rippling error messages on subsequent uses of the same type,
+  // could be useful if #include was forgotten.
+  return false;
+}
+
+/// \brief Determine the declaration specifier context from the declarator
+/// context.
+///
+/// \param Context the declarator context, which is one of the
+/// Declarator::TheContext enumerator values.
+Parser::DeclSpecContext 
+Parser::getDeclSpecContextFromDeclaratorContext(unsigned Context) {
+  if (Context == Declarator::MemberContext)
+    return DSC_class;
+  if (Context == Declarator::FileContext)
+    return DSC_top_level;
+  return DSC_normal;
+}
+
+/// ParseDeclarationSpecifiers
+///       declaration-specifiers: [C99 6.7]
+///         storage-class-specifier declaration-specifiers[opt]
+///         type-specifier declaration-specifiers[opt]
+/// [C99]   function-specifier declaration-specifiers[opt]
+/// [GNU]   attributes declaration-specifiers[opt]
+///
+///       storage-class-specifier: [C99 6.7.1]
+///         'typedef'
+///         'extern'
+///         'static'
+///         'auto'
+///         'register'
+/// [C++]   'mutable'
+/// [GNU]   '__thread'
+///       function-specifier: [C99 6.7.4]
+/// [C99]   'inline'
+/// [C++]   'virtual'
+/// [C++]   'explicit'
+///       'friend': [C++ dcl.friend]
+///       'constexpr': [C++0x dcl.constexpr]
+
+///
+void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
+                                        const ParsedTemplateInfo &TemplateInfo,
+                                        AccessSpecifier AS,
+                                        DeclSpecContext DSContext) {
+  if (Tok.is(tok::code_completion)) {
+    Action::CodeCompletionContext CCC = Action::CCC_Namespace;
+    if (TemplateInfo.Kind != ParsedTemplateInfo::NonTemplate)
+      CCC = DSContext == DSC_class? Action::CCC_MemberTemplate 
+                                  : Action::CCC_Template;
+    else if (DSContext == DSC_class)
+      CCC = Action::CCC_Class;
+    else if (ObjCImpDecl)
+      CCC = Action::CCC_ObjCImplementation;
+    
+    Actions.CodeCompleteOrdinaryName(CurScope, CCC);
+    ConsumeToken();
+  }
+  
+  DS.SetRangeStart(Tok.getLocation());
+  while (1) {
+    bool isInvalid = false;
+    const char *PrevSpec = 0;
+    unsigned DiagID = 0;
+
+    SourceLocation Loc = Tok.getLocation();
+
+    switch (Tok.getKind()) {
+    default:
+    DoneWithDeclSpec:
+      // If this is not a declaration specifier token, we're done reading decl
+      // specifiers.  First verify that DeclSpec's are consistent.
+      DS.Finish(Diags, PP);
+      return;
+
+    case tok::coloncolon: // ::foo::bar
+      // Annotate C++ scope specifiers.  If we get one, loop.
+      if (TryAnnotateCXXScopeToken(true))
+        continue;
+      goto DoneWithDeclSpec;
+
+    case tok::annot_cxxscope: {
+      if (DS.hasTypeSpecifier())
+        goto DoneWithDeclSpec;
+
+      CXXScopeSpec SS;
+      SS.setScopeRep(Tok.getAnnotationValue());
+      SS.setRange(Tok.getAnnotationRange());
+
+      // We are looking for a qualified typename.
+      Token Next = NextToken();
+      if (Next.is(tok::annot_template_id) &&
+          static_cast<TemplateIdAnnotation *>(Next.getAnnotationValue())
+            ->Kind == TNK_Type_template) {
+        // We have a qualified template-id, e.g., N::A<int>
+
+        // C++ [class.qual]p2:
+        //   In a lookup in which the constructor is an acceptable lookup
+        //   result and the nested-name-specifier nominates a class C:
+        //
+        //     - if the name specified after the
+        //       nested-name-specifier, when looked up in C, is the
+        //       injected-class-name of C (Clause 9), or
+        //
+        //     - if the name specified after the nested-name-specifier
+        //       is the same as the identifier or the
+        //       simple-template-id's template-name in the last
+        //       component of the nested-name-specifier,
+        //
+        //   the name is instead considered to name the constructor of
+        //   class C.
+        // 
+        // Thus, if the template-name is actually the constructor
+        // name, then the code is ill-formed; this interpretation is
+        // reinforced by the NAD status of core issue 635. 
+        TemplateIdAnnotation *TemplateId
+          = static_cast<TemplateIdAnnotation *>(Next.getAnnotationValue());
+        if (DSContext == DSC_top_level && TemplateId->Name &&
+            Actions.isCurrentClassName(*TemplateId->Name, CurScope, &SS)) {
+          if (isConstructorDeclarator()) {
+            // The user meant this to be an out-of-line constructor
+            // definition, but template arguments are not allowed
+            // there.  Just allow this as a constructor; we'll
+            // complain about it later.
+            goto DoneWithDeclSpec;
+          }
+
+          // The user meant this to name a type, but it actually names
+          // a constructor with some extraneous template
+          // arguments. Complain, then parse it as a type as the user
+          // intended.
+          Diag(TemplateId->TemplateNameLoc,
+               diag::err_out_of_line_template_id_names_constructor)
+            << TemplateId->Name;
+        }
+
+        DS.getTypeSpecScope() = SS;
+        ConsumeToken(); // The C++ scope.
+        assert(Tok.is(tok::annot_template_id) &&
+               "ParseOptionalCXXScopeSpecifier not working");
+        AnnotateTemplateIdTokenAsType(&SS);
+        continue;
+      }
+
+      if (Next.is(tok::annot_typename)) {
+        DS.getTypeSpecScope() = SS;
+        ConsumeToken(); // The C++ scope.
+        if (Tok.getAnnotationValue())
+          isInvalid = DS.SetTypeSpecType(DeclSpec::TST_typename, Loc, 
+                                         PrevSpec, DiagID, 
+                                         Tok.getAnnotationValue());
+        else
+          DS.SetTypeSpecError();
+        DS.SetRangeEnd(Tok.getAnnotationEndLoc());
+        ConsumeToken(); // The typename
+      }
+
+      if (Next.isNot(tok::identifier))
+        goto DoneWithDeclSpec;
+
+      // If we're in a context where the identifier could be a class name,
+      // check whether this is a constructor declaration.
+      if (DSContext == DSC_top_level &&
+          Actions.isCurrentClassName(*Next.getIdentifierInfo(), CurScope, 
+                                     &SS)) {
+        if (isConstructorDeclarator())
+          goto DoneWithDeclSpec;
+
+        // As noted in C++ [class.qual]p2 (cited above), when the name
+        // of the class is qualified in a context where it could name
+        // a constructor, its a constructor name. However, we've
+        // looked at the declarator, and the user probably meant this
+        // to be a type. Complain that it isn't supposed to be treated
+        // as a type, then proceed to parse it as a type.
+        Diag(Next.getLocation(), diag::err_out_of_line_type_names_constructor)
+          << Next.getIdentifierInfo();
+      }
+
+      TypeTy *TypeRep = Actions.getTypeName(*Next.getIdentifierInfo(),
+                                            Next.getLocation(), CurScope, &SS);
+
+      // If the referenced identifier is not a type, then this declspec is
+      // erroneous: We already checked about that it has no type specifier, and
+      // C++ doesn't have implicit int.  Diagnose it as a typo w.r.t. to the
+      // typename.
+      if (TypeRep == 0) {
+        ConsumeToken();   // Eat the scope spec so the identifier is current.
+        if (ParseImplicitInt(DS, &SS, TemplateInfo, AS)) continue;
+        goto DoneWithDeclSpec;
+      }
+
+      DS.getTypeSpecScope() = SS;
+      ConsumeToken(); // The C++ scope.
+
+      isInvalid = DS.SetTypeSpecType(DeclSpec::TST_typename, Loc, PrevSpec,
+                                     DiagID, TypeRep);
+      if (isInvalid)
+        break;
+
+      DS.SetRangeEnd(Tok.getLocation());
+      ConsumeToken(); // The typename.
+
+      continue;
+    }
+
+    case tok::annot_typename: {
+      if (Tok.getAnnotationValue())
+        isInvalid = DS.SetTypeSpecType(DeclSpec::TST_typename, Loc, PrevSpec,
+                                       DiagID, Tok.getAnnotationValue());
+      else
+        DS.SetTypeSpecError();
+      DS.SetRangeEnd(Tok.getAnnotationEndLoc());
+      ConsumeToken(); // The typename
+
+      // Objective-C supports syntax of the form 'id<proto1,proto2>' where 'id'
+      // is a specific typedef and 'itf<proto1,proto2>' where 'itf' is an
+      // Objective-C interface.  If we don't have Objective-C or a '<', this is
+      // just a normal reference to a typedef name.
+      if (!Tok.is(tok::less) || !getLang().ObjC1)
+        continue;
+
+      SourceLocation LAngleLoc, EndProtoLoc;
+      llvm::SmallVector<DeclPtrTy, 8> ProtocolDecl;
+      llvm::SmallVector<SourceLocation, 8> ProtocolLocs;
+      ParseObjCProtocolReferences(ProtocolDecl, ProtocolLocs, false,
+                                  LAngleLoc, EndProtoLoc);
+      DS.setProtocolQualifiers(ProtocolDecl.data(), ProtocolDecl.size(),
+                               ProtocolLocs.data(), LAngleLoc);
+
+      DS.SetRangeEnd(EndProtoLoc);
+      continue;
+    }
+
+      // typedef-name
+    case tok::identifier: {
+      // In C++, check to see if this is a scope specifier like foo::bar::, if
+      // so handle it as such.  This is important for ctor parsing.
+      if (getLang().CPlusPlus && TryAnnotateCXXScopeToken(true))
+        continue;
+
+      // This identifier can only be a typedef name if we haven't already seen
+      // a type-specifier.  Without this check we misparse:
+      //  typedef int X; struct Y { short X; };  as 'short int'.
+      if (DS.hasTypeSpecifier())
+        goto DoneWithDeclSpec;
+
+      // Check for need to substitute AltiVec keyword tokens.
+      if (TryAltiVecToken(DS, Loc, PrevSpec, DiagID, isInvalid))
+        break;
+
+      // It has to be available as a typedef too!
+      TypeTy *TypeRep = Actions.getTypeName(*Tok.getIdentifierInfo(),
+                                            Tok.getLocation(), CurScope);
+
+      // If this is not a typedef name, don't parse it as part of the declspec,
+      // it must be an implicit int or an error.
+      if (TypeRep == 0) {
+        if (ParseImplicitInt(DS, 0, TemplateInfo, AS)) continue;
+        goto DoneWithDeclSpec;
+      }
+
+      // If we're in a context where the identifier could be a class name,
+      // check whether this is a constructor declaration.
+      if (getLang().CPlusPlus && DSContext == DSC_class &&
+          Actions.isCurrentClassName(*Tok.getIdentifierInfo(), CurScope) &&
+          isConstructorDeclarator())
+        goto DoneWithDeclSpec;
+
+      isInvalid = DS.SetTypeSpecType(DeclSpec::TST_typename, Loc, PrevSpec,
+                                     DiagID, TypeRep);
+      if (isInvalid)
+        break;
+
+      DS.SetRangeEnd(Tok.getLocation());
+      ConsumeToken(); // The identifier
+
+      // Objective-C supports syntax of the form 'id<proto1,proto2>' where 'id'
+      // is a specific typedef and 'itf<proto1,proto2>' where 'itf' is an
+      // Objective-C interface.  If we don't have Objective-C or a '<', this is
+      // just a normal reference to a typedef name.
+      if (!Tok.is(tok::less) || !getLang().ObjC1)
+        continue;
+
+      SourceLocation LAngleLoc, EndProtoLoc;
+      llvm::SmallVector<DeclPtrTy, 8> ProtocolDecl;
+      llvm::SmallVector<SourceLocation, 8> ProtocolLocs;
+      ParseObjCProtocolReferences(ProtocolDecl, ProtocolLocs, false,
+                                  LAngleLoc, EndProtoLoc);
+      DS.setProtocolQualifiers(ProtocolDecl.data(), ProtocolDecl.size(),
+                               ProtocolLocs.data(), LAngleLoc);
+
+      DS.SetRangeEnd(EndProtoLoc);
+
+      // Need to support trailing type qualifiers (e.g. "id<p> const").
+      // If a type specifier follows, it will be diagnosed elsewhere.
+      continue;
+    }
+
+      // type-name
+    case tok::annot_template_id: {
+      TemplateIdAnnotation *TemplateId
+        = static_cast<TemplateIdAnnotation *>(Tok.getAnnotationValue());
+      if (TemplateId->Kind != TNK_Type_template) {
+        // This template-id does not refer to a type name, so we're
+        // done with the type-specifiers.
+        goto DoneWithDeclSpec;
+      }
+
+      // If we're in a context where the template-id could be a
+      // constructor name or specialization, check whether this is a
+      // constructor declaration.
+      if (getLang().CPlusPlus && DSContext == DSC_class &&
+          Actions.isCurrentClassName(*TemplateId->Name, CurScope) &&
+          isConstructorDeclarator())
+        goto DoneWithDeclSpec;
+
+      // Turn the template-id annotation token into a type annotation
+      // token, then try again to parse it as a type-specifier.
+      AnnotateTemplateIdTokenAsType();
+      continue;
+    }
+
+    // GNU attributes support.
+    case tok::kw___attribute:
+      DS.AddAttributes(ParseGNUAttributes());
+      continue;
+
+    // Microsoft declspec support.
+    case tok::kw___declspec:
+      DS.AddAttributes(ParseMicrosoftDeclSpec());
+      continue;
+
+    // Microsoft single token adornments.
+    case tok::kw___forceinline:
+      // FIXME: Add handling here!
+      break;
+
+    case tok::kw___ptr64:
+    case tok::kw___w64:
+    case tok::kw___cdecl:
+    case tok::kw___stdcall:
+    case tok::kw___fastcall:
+      DS.AddAttributes(ParseMicrosoftTypeAttributes());
+      continue;
+
+    // storage-class-specifier
+    case tok::kw_typedef:
+      isInvalid = DS.SetStorageClassSpec(DeclSpec::SCS_typedef, Loc, PrevSpec,
+                                         DiagID);
+      break;
+    case tok::kw_extern:
+      if (DS.isThreadSpecified())
+        Diag(Tok, diag::ext_thread_before) << "extern";
+      isInvalid = DS.SetStorageClassSpec(DeclSpec::SCS_extern, Loc, PrevSpec,
+                                         DiagID);
+      break;
+    case tok::kw___private_extern__:
+      isInvalid = DS.SetStorageClassSpec(DeclSpec::SCS_private_extern, Loc,
+                                         PrevSpec, DiagID);
+      break;
+    case tok::kw_static:
+      if (DS.isThreadSpecified())
+        Diag(Tok, diag::ext_thread_before) << "static";
+      isInvalid = DS.SetStorageClassSpec(DeclSpec::SCS_static, Loc, PrevSpec,
+                                         DiagID);
+      break;
+    case tok::kw_auto:
+      if (getLang().CPlusPlus0x)
+        isInvalid = DS.SetTypeSpecType(DeclSpec::TST_auto, Loc, PrevSpec,
+                                       DiagID);
+      else
+        isInvalid = DS.SetStorageClassSpec(DeclSpec::SCS_auto, Loc, PrevSpec,
+                                           DiagID);
+      break;
+    case tok::kw_register:
+      isInvalid = DS.SetStorageClassSpec(DeclSpec::SCS_register, Loc, PrevSpec,
+                                         DiagID);
+      break;
+    case tok::kw_mutable:
+      isInvalid = DS.SetStorageClassSpec(DeclSpec::SCS_mutable, Loc, PrevSpec,
+                                         DiagID);
+      break;
+    case tok::kw___thread:
+      isInvalid = DS.SetStorageClassSpecThread(Loc, PrevSpec, DiagID);
+      break;
+
+    // function-specifier
+    case tok::kw_inline:
+      isInvalid = DS.SetFunctionSpecInline(Loc, PrevSpec, DiagID);
+      break;
+    case tok::kw_virtual:
+      isInvalid = DS.SetFunctionSpecVirtual(Loc, PrevSpec, DiagID);
+      break;
+    case tok::kw_explicit:
+      isInvalid = DS.SetFunctionSpecExplicit(Loc, PrevSpec, DiagID);
+      break;
+
+    // friend
+    case tok::kw_friend:
+      if (DSContext == DSC_class)
+        isInvalid = DS.SetFriendSpec(Loc, PrevSpec, DiagID);
+      else {
+        PrevSpec = ""; // not actually used by the diagnostic
+        DiagID = diag::err_friend_invalid_in_context;
+        isInvalid = true;
+      }
+      break;
+
+    // constexpr
+    case tok::kw_constexpr:
+      isInvalid = DS.SetConstexprSpec(Loc, PrevSpec, DiagID);
+      break;
+
+    // type-specifier
+    case tok::kw_short:
+      isInvalid = DS.SetTypeSpecWidth(DeclSpec::TSW_short, Loc, PrevSpec,
+                                      DiagID);
+      break;
+    case tok::kw_long:
+      if (DS.getTypeSpecWidth() != DeclSpec::TSW_long)
+        isInvalid = DS.SetTypeSpecWidth(DeclSpec::TSW_long, Loc, PrevSpec,
+                                        DiagID);
+      else
+        isInvalid = DS.SetTypeSpecWidth(DeclSpec::TSW_longlong, Loc, PrevSpec,
+                                        DiagID);
+      break;
+    case tok::kw_signed:
+      isInvalid = DS.SetTypeSpecSign(DeclSpec::TSS_signed, Loc, PrevSpec,
+                                     DiagID);
+      break;
+    case tok::kw_unsigned:
+      isInvalid = DS.SetTypeSpecSign(DeclSpec::TSS_unsigned, Loc, PrevSpec,
+                                     DiagID);
+      break;
+    case tok::kw__Complex:
+      isInvalid = DS.SetTypeSpecComplex(DeclSpec::TSC_complex, Loc, PrevSpec,
+                                        DiagID);
+      break;
+    case tok::kw__Imaginary:
+      isInvalid = DS.SetTypeSpecComplex(DeclSpec::TSC_imaginary, Loc, PrevSpec,
+                                        DiagID);
+      break;
+    case tok::kw_void:
+      isInvalid = DS.SetTypeSpecType(DeclSpec::TST_void, Loc, PrevSpec,
+                                     DiagID);
+      break;
+    case tok::kw_char:
+      isInvalid = DS.SetTypeSpecType(DeclSpec::TST_char, Loc, PrevSpec,
+                                     DiagID);
+      break;
+    case tok::kw_int:
+      isInvalid = DS.SetTypeSpecType(DeclSpec::TST_int, Loc, PrevSpec,
+                                     DiagID);
+      break;
+    case tok::kw_float:
+      isInvalid = DS.SetTypeSpecType(DeclSpec::TST_float, Loc, PrevSpec,
+                                     DiagID);
+      break;
+    case tok::kw_double:
+      isInvalid = DS.SetTypeSpecType(DeclSpec::TST_double, Loc, PrevSpec,
+                                     DiagID);
+      break;
+    case tok::kw_wchar_t:
+      isInvalid = DS.SetTypeSpecType(DeclSpec::TST_wchar, Loc, PrevSpec,
+                                     DiagID);
+      break;
+    case tok::kw_char16_t:
+      isInvalid = DS.SetTypeSpecType(DeclSpec::TST_char16, Loc, PrevSpec,
+                                     DiagID);
+      break;
+    case tok::kw_char32_t:
+      isInvalid = DS.SetTypeSpecType(DeclSpec::TST_char32, Loc, PrevSpec,
+                                     DiagID);
+      break;
+    case tok::kw_bool:
+    case tok::kw__Bool:
+      isInvalid = DS.SetTypeSpecType(DeclSpec::TST_bool, Loc, PrevSpec,
+                                     DiagID);
+      break;
+    case tok::kw__Decimal32:
+      isInvalid = DS.SetTypeSpecType(DeclSpec::TST_decimal32, Loc, PrevSpec,
+                                     DiagID);
+      break;
+    case tok::kw__Decimal64:
+      isInvalid = DS.SetTypeSpecType(DeclSpec::TST_decimal64, Loc, PrevSpec,
+                                     DiagID);
+      break;
+    case tok::kw__Decimal128:
+      isInvalid = DS.SetTypeSpecType(DeclSpec::TST_decimal128, Loc, PrevSpec,
+                                     DiagID);
+      break;
+    case tok::kw___vector:
+      isInvalid = DS.SetTypeAltiVecVector(true, Loc, PrevSpec, DiagID);
+      break;
+    case tok::kw___pixel:
+      isInvalid = DS.SetTypeAltiVecPixel(true, Loc, PrevSpec, DiagID);
+      break;
+
+    // class-specifier:
+    case tok::kw_class:
+    case tok::kw_struct:
+    case tok::kw_union: {
+      tok::TokenKind Kind = Tok.getKind();
+      ConsumeToken();
+      ParseClassSpecifier(Kind, Loc, DS, TemplateInfo, AS);
+      continue;
+    }
+
+    // enum-specifier:
+    case tok::kw_enum:
+      ConsumeToken();
+      ParseEnumSpecifier(Loc, DS, AS);
+      continue;
+
+    // cv-qualifier:
+    case tok::kw_const:
+      isInvalid = DS.SetTypeQual(DeclSpec::TQ_const, Loc, PrevSpec, DiagID,
+                                 getLang());
+      break;
+    case tok::kw_volatile:
+      isInvalid = DS.SetTypeQual(DeclSpec::TQ_volatile, Loc, PrevSpec, DiagID,
+                                 getLang());
+      break;
+    case tok::kw_restrict:
+      isInvalid = DS.SetTypeQual(DeclSpec::TQ_restrict, Loc, PrevSpec, DiagID,
+                                 getLang());
+      break;
+
+    // C++ typename-specifier:
+    case tok::kw_typename:
+      if (TryAnnotateTypeOrScopeToken())
+        continue;
+      break;
+
+    // GNU typeof support.
+    case tok::kw_typeof:
+      ParseTypeofSpecifier(DS);
+      continue;
+
+    case tok::kw_decltype:
+      ParseDecltypeSpecifier(DS);
+      continue;
+
+    case tok::less:
+      // GCC ObjC supports types like "<SomeProtocol>" as a synonym for
+      // "id<SomeProtocol>".  This is hopelessly old fashioned and dangerous,
+      // but we support it.
+      if (DS.hasTypeSpecifier() || !getLang().ObjC1)
+        goto DoneWithDeclSpec;
+
+      {
+        SourceLocation LAngleLoc, EndProtoLoc;
+        llvm::SmallVector<DeclPtrTy, 8> ProtocolDecl;
+        llvm::SmallVector<SourceLocation, 8> ProtocolLocs;
+        ParseObjCProtocolReferences(ProtocolDecl, ProtocolLocs, false,
+                                    LAngleLoc, EndProtoLoc);
+        DS.setProtocolQualifiers(ProtocolDecl.data(), ProtocolDecl.size(),
+                                 ProtocolLocs.data(), LAngleLoc);
+        DS.SetRangeEnd(EndProtoLoc);
+
+        Diag(Loc, diag::warn_objc_protocol_qualifier_missing_id)
+          << CodeModificationHint::CreateInsertion(Loc, "id")
+          << SourceRange(Loc, EndProtoLoc);
+        // Need to support trailing type qualifiers (e.g. "id<p> const").
+        // If a type specifier follows, it will be diagnosed elsewhere.
+        continue;
+      }
+    }
+    // If the specifier wasn't legal, issue a diagnostic.
+    if (isInvalid) {
+      assert(PrevSpec && "Method did not return previous specifier!");
+      assert(DiagID);
+      Diag(Tok, DiagID) << PrevSpec;
+    }
+    DS.SetRangeEnd(Tok.getLocation());
+    ConsumeToken();
+  }
+}
+
+/// ParseOptionalTypeSpecifier - Try to parse a single type-specifier. We
+/// primarily follow the C++ grammar with additions for C99 and GNU,
+/// which together subsume the C grammar. Note that the C++
+/// type-specifier also includes the C type-qualifier (for const,
+/// volatile, and C99 restrict). Returns true if a type-specifier was
+/// found (and parsed), false otherwise.
+///
+///       type-specifier: [C++ 7.1.5]
+///         simple-type-specifier
+///         class-specifier
+///         enum-specifier
+///         elaborated-type-specifier  [TODO]
+///         cv-qualifier
+///
+///       cv-qualifier: [C++ 7.1.5.1]
+///         'const'
+///         'volatile'
+/// [C99]   'restrict'
+///
+///       simple-type-specifier: [ C++ 7.1.5.2]
+///         '::'[opt] nested-name-specifier[opt] type-name [TODO]
+///         '::'[opt] nested-name-specifier 'template' template-id [TODO]
+///         'char'
+///         'wchar_t'
+///         'bool'
+///         'short'
+///         'int'
+///         'long'
+///         'signed'
+///         'unsigned'
+///         'float'
+///         'double'
+///         'void'
+/// [C99]   '_Bool'
+/// [C99]   '_Complex'
+/// [C99]   '_Imaginary'  // Removed in TC2?
+/// [GNU]   '_Decimal32'
+/// [GNU]   '_Decimal64'
+/// [GNU]   '_Decimal128'
+/// [GNU]   typeof-specifier
+/// [OBJC]  class-name objc-protocol-refs[opt]    [TODO]
+/// [OBJC]  typedef-name objc-protocol-refs[opt]  [TODO]
+/// [C++0x] 'decltype' ( expression )
+/// [AltiVec] '__vector'
+bool Parser::ParseOptionalTypeSpecifier(DeclSpec &DS, bool& isInvalid,
+                                        const char *&PrevSpec,
+                                        unsigned &DiagID,
+                                        const ParsedTemplateInfo &TemplateInfo,
+                                        bool SuppressDeclarations) {
+  SourceLocation Loc = Tok.getLocation();
+
+  switch (Tok.getKind()) {
+  case tok::identifier:   // foo::bar
+    // Check for need to substitute AltiVec keyword tokens.
+    if (TryAltiVecToken(DS, Loc, PrevSpec, DiagID, isInvalid))
+      break;
+    // Fall through.
+  case tok::kw_typename:  // typename foo::bar
+    // Annotate typenames and C++ scope specifiers.  If we get one, just
+    // recurse to handle whatever we get.
+    if (TryAnnotateTypeOrScopeToken())
+      return ParseOptionalTypeSpecifier(DS, isInvalid, PrevSpec, DiagID,
+                                        TemplateInfo, SuppressDeclarations);
+    // Otherwise, not a type specifier.
+    return false;
+  case tok::coloncolon:   // ::foo::bar
+    if (NextToken().is(tok::kw_new) ||    // ::new
+        NextToken().is(tok::kw_delete))   // ::delete
+      return false;
+
+    // Annotate typenames and C++ scope specifiers.  If we get one, just
+    // recurse to handle whatever we get.
+    if (TryAnnotateTypeOrScopeToken())
+      return ParseOptionalTypeSpecifier(DS, isInvalid, PrevSpec, DiagID,
+                                        TemplateInfo, SuppressDeclarations);
+    // Otherwise, not a type specifier.
+    return false;
+
+  // simple-type-specifier:
+  case tok::annot_typename: {
+    if (Tok.getAnnotationValue())
+      isInvalid = DS.SetTypeSpecType(DeclSpec::TST_typename, Loc, PrevSpec,
+                                     DiagID, Tok.getAnnotationValue());
+    else
+      DS.SetTypeSpecError();
+    DS.SetRangeEnd(Tok.getAnnotationEndLoc());
+    ConsumeToken(); // The typename
+
+    // Objective-C supports syntax of the form 'id<proto1,proto2>' where 'id'
+    // is a specific typedef and 'itf<proto1,proto2>' where 'itf' is an
+    // Objective-C interface.  If we don't have Objective-C or a '<', this is
+    // just a normal reference to a typedef name.
+    if (!Tok.is(tok::less) || !getLang().ObjC1)
+      return true;
+
+    SourceLocation LAngleLoc, EndProtoLoc;
+    llvm::SmallVector<DeclPtrTy, 8> ProtocolDecl;
+    llvm::SmallVector<SourceLocation, 8> ProtocolLocs;
+    ParseObjCProtocolReferences(ProtocolDecl, ProtocolLocs, false,
+                                LAngleLoc, EndProtoLoc);
+    DS.setProtocolQualifiers(ProtocolDecl.data(), ProtocolDecl.size(),
+                             ProtocolLocs.data(), LAngleLoc);
+
+    DS.SetRangeEnd(EndProtoLoc);
+    return true;
+  }
+
+  case tok::kw_short:
+    isInvalid = DS.SetTypeSpecWidth(DeclSpec::TSW_short, Loc, PrevSpec, DiagID);
+    break;
+  case tok::kw_long:
+    if (DS.getTypeSpecWidth() != DeclSpec::TSW_long)
+      isInvalid = DS.SetTypeSpecWidth(DeclSpec::TSW_long, Loc, PrevSpec,
+                                      DiagID);
+    else
+      isInvalid = DS.SetTypeSpecWidth(DeclSpec::TSW_longlong, Loc, PrevSpec,
+                                      DiagID);
+    break;
+  case tok::kw_signed:
+    isInvalid = DS.SetTypeSpecSign(DeclSpec::TSS_signed, Loc, PrevSpec, DiagID);
+    break;
+  case tok::kw_unsigned:
+    isInvalid = DS.SetTypeSpecSign(DeclSpec::TSS_unsigned, Loc, PrevSpec,
+                                   DiagID);
+    break;
+  case tok::kw__Complex:
+    isInvalid = DS.SetTypeSpecComplex(DeclSpec::TSC_complex, Loc, PrevSpec,
+                                      DiagID);
+    break;
+  case tok::kw__Imaginary:
+    isInvalid = DS.SetTypeSpecComplex(DeclSpec::TSC_imaginary, Loc, PrevSpec,
+                                      DiagID);
+    break;
+  case tok::kw_void:
+    isInvalid = DS.SetTypeSpecType(DeclSpec::TST_void, Loc, PrevSpec, DiagID);
+    break;
+  case tok::kw_char:
+    isInvalid = DS.SetTypeSpecType(DeclSpec::TST_char, Loc, PrevSpec, DiagID);
+    break;
+  case tok::kw_int:
+    isInvalid = DS.SetTypeSpecType(DeclSpec::TST_int, Loc, PrevSpec, DiagID);
+    break;
+  case tok::kw_float:
+    isInvalid = DS.SetTypeSpecType(DeclSpec::TST_float, Loc, PrevSpec, DiagID);
+    break;
+  case tok::kw_double:
+    isInvalid = DS.SetTypeSpecType(DeclSpec::TST_double, Loc, PrevSpec, DiagID);
+    break;
+  case tok::kw_wchar_t:
+    isInvalid = DS.SetTypeSpecType(DeclSpec::TST_wchar, Loc, PrevSpec, DiagID);
+    break;
+  case tok::kw_char16_t:
+    isInvalid = DS.SetTypeSpecType(DeclSpec::TST_char16, Loc, PrevSpec, DiagID);
+    break;
+  case tok::kw_char32_t:
+    isInvalid = DS.SetTypeSpecType(DeclSpec::TST_char32, Loc, PrevSpec, DiagID);
+    break;
+  case tok::kw_bool:
+  case tok::kw__Bool:
+    isInvalid = DS.SetTypeSpecType(DeclSpec::TST_bool, Loc, PrevSpec, DiagID);
+    break;
+  case tok::kw__Decimal32:
+    isInvalid = DS.SetTypeSpecType(DeclSpec::TST_decimal32, Loc, PrevSpec,
+                                   DiagID);
+    break;
+  case tok::kw__Decimal64:
+    isInvalid = DS.SetTypeSpecType(DeclSpec::TST_decimal64, Loc, PrevSpec,
+                                   DiagID);
+    break;
+  case tok::kw__Decimal128:
+    isInvalid = DS.SetTypeSpecType(DeclSpec::TST_decimal128, Loc, PrevSpec,
+                                   DiagID);
+    break;
+  case tok::kw___vector:
+    isInvalid = DS.SetTypeAltiVecVector(true, Loc, PrevSpec, DiagID);
+    break;
+  case tok::kw___pixel:
+    isInvalid = DS.SetTypeAltiVecPixel(true, Loc, PrevSpec, DiagID);
+    break;
+  
+  // class-specifier:
+  case tok::kw_class:
+  case tok::kw_struct:
+  case tok::kw_union: {
+    tok::TokenKind Kind = Tok.getKind();
+    ConsumeToken();
+    ParseClassSpecifier(Kind, Loc, DS, TemplateInfo, AS_none,
+                        SuppressDeclarations);
+    return true;
+  }
+
+  // enum-specifier:
+  case tok::kw_enum:
+    ConsumeToken();
+    ParseEnumSpecifier(Loc, DS);
+    return true;
+
+  // cv-qualifier:
+  case tok::kw_const:
+    isInvalid = DS.SetTypeQual(DeclSpec::TQ_const   , Loc, PrevSpec,
+                               DiagID, getLang());
+    break;
+  case tok::kw_volatile:
+    isInvalid = DS.SetTypeQual(DeclSpec::TQ_volatile, Loc, PrevSpec,
+                               DiagID, getLang());
+    break;
+  case tok::kw_restrict:
+    isInvalid = DS.SetTypeQual(DeclSpec::TQ_restrict, Loc, PrevSpec,
+                               DiagID, getLang());
+    break;
+
+  // GNU typeof support.
+  case tok::kw_typeof:
+    ParseTypeofSpecifier(DS);
+    return true;
+
+  // C++0x decltype support.
+  case tok::kw_decltype:
+    ParseDecltypeSpecifier(DS);
+    return true;
+
+  // C++0x auto support.
+  case tok::kw_auto:
+    if (!getLang().CPlusPlus0x)
+      return false;
+
+    isInvalid = DS.SetTypeSpecType(DeclSpec::TST_auto, Loc, PrevSpec, DiagID);
+    break;
+  case tok::kw___ptr64:
+  case tok::kw___w64:
+  case tok::kw___cdecl:
+  case tok::kw___stdcall:
+  case tok::kw___fastcall:
+    DS.AddAttributes(ParseMicrosoftTypeAttributes());
+    return true;
+
+  default:
+    // Not a type-specifier; do nothing.
+    return false;
+  }
+
+  // If the specifier combination wasn't legal, issue a diagnostic.
+  if (isInvalid) {
+    assert(PrevSpec && "Method did not return previous specifier!");
+    // Pick between error or extwarn.
+    Diag(Tok, DiagID) << PrevSpec;
+  }
+  DS.SetRangeEnd(Tok.getLocation());
+  ConsumeToken(); // whatever we parsed above.
+  return true;
+}
+
+/// ParseStructDeclaration - Parse a struct declaration without the terminating
+/// semicolon.
+///
+///       struct-declaration:
+///         specifier-qualifier-list struct-declarator-list
+/// [GNU]   __extension__ struct-declaration
+/// [GNU]   specifier-qualifier-list
+///       struct-declarator-list:
+///         struct-declarator
+///         struct-declarator-list ',' struct-declarator
+/// [GNU]   struct-declarator-list ',' attributes[opt] struct-declarator
+///       struct-declarator:
+///         declarator
+/// [GNU]   declarator attributes[opt]
+///         declarator[opt] ':' constant-expression
+/// [GNU]   declarator[opt] ':' constant-expression attributes[opt]
+///
+void Parser::
+ParseStructDeclaration(DeclSpec &DS, FieldCallback &Fields) {
+  if (Tok.is(tok::kw___extension__)) {
+    // __extension__ silences extension warnings in the subexpression.
+    ExtensionRAIIObject O(Diags);  // Use RAII to do this.
+    ConsumeToken();
+    return ParseStructDeclaration(DS, Fields);
+  }
+
+  // Parse the common specifier-qualifiers-list piece.
+  SourceLocation DSStart = Tok.getLocation();
+  ParseSpecifierQualifierList(DS);
+
+  // If there are no declarators, this is a free-standing declaration
+  // specifier. Let the actions module cope with it.
+  if (Tok.is(tok::semi)) {
+    Actions.ParsedFreeStandingDeclSpec(CurScope, DS);
+    return;
+  }
+
+  // Read struct-declarators until we find the semicolon.
+  bool FirstDeclarator = true;
+  while (1) {
+    ParsingDeclRAIIObject PD(*this);
+    FieldDeclarator DeclaratorInfo(DS);
+
+    // Attributes are only allowed here on successive declarators.
+    if (!FirstDeclarator && Tok.is(tok::kw___attribute)) {
+      SourceLocation Loc;
+      AttributeList *AttrList = ParseGNUAttributes(&Loc);
+      DeclaratorInfo.D.AddAttributes(AttrList, Loc);
+    }
+
+    /// struct-declarator: declarator
+    /// struct-declarator: declarator[opt] ':' constant-expression
+    if (Tok.isNot(tok::colon)) {
+      // Don't parse FOO:BAR as if it were a typo for FOO::BAR.
+      ColonProtectionRAIIObject X(*this);
+      ParseDeclarator(DeclaratorInfo.D);
+    }
+
+    if (Tok.is(tok::colon)) {
+      ConsumeToken();
+      OwningExprResult Res(ParseConstantExpression());
+      if (Res.isInvalid())
+        SkipUntil(tok::semi, true, true);
+      else
+        DeclaratorInfo.BitfieldSize = Res.release();
+    }
+
+    // If attributes exist after the declarator, parse them.
+    if (Tok.is(tok::kw___attribute)) {
+      SourceLocation Loc;
+      AttributeList *AttrList = ParseGNUAttributes(&Loc);
+      DeclaratorInfo.D.AddAttributes(AttrList, Loc);
+    }
+
+    // We're done with this declarator;  invoke the callback.
+    DeclPtrTy D = Fields.invoke(DeclaratorInfo);
+    PD.complete(D);
+
+    // If we don't have a comma, it is either the end of the list (a ';')
+    // or an error, bail out.
+    if (Tok.isNot(tok::comma))
+      return;
+
+    // Consume the comma.
+    ConsumeToken();
+
+    FirstDeclarator = false;
+  }
+}
+
+/// ParseStructUnionBody
+///       struct-contents:
+///         struct-declaration-list
+/// [EXT]   empty
+/// [GNU]   "struct-declaration-list" without terminatoring ';'
+///       struct-declaration-list:
+///         struct-declaration
+///         struct-declaration-list struct-declaration
+/// [OBC]   '@' 'defs' '(' class-name ')'
+///
+void Parser::ParseStructUnionBody(SourceLocation RecordLoc,
+                                  unsigned TagType, DeclPtrTy TagDecl) {
+  PrettyStackTraceActionsDecl CrashInfo(TagDecl, RecordLoc, Actions,
+                                        PP.getSourceManager(),
+                                        "parsing struct/union body");
+
+  SourceLocation LBraceLoc = ConsumeBrace();
+
+  ParseScope StructScope(this, Scope::ClassScope|Scope::DeclScope);
+  Actions.ActOnTagStartDefinition(CurScope, TagDecl);
+
+  // Empty structs are an extension in C (C99 6.7.2.1p7), but are allowed in
+  // C++.
+  if (Tok.is(tok::r_brace) && !getLang().CPlusPlus)
+    Diag(Tok, diag::ext_empty_struct_union_enum)
+      << DeclSpec::getSpecifierName((DeclSpec::TST)TagType);
+
+  llvm::SmallVector<DeclPtrTy, 32> FieldDecls;
+
+  // While we still have something to read, read the declarations in the struct.
+  while (Tok.isNot(tok::r_brace) && Tok.isNot(tok::eof)) {
+    // Each iteration of this loop reads one struct-declaration.
+
+    // Check for extraneous top-level semicolon.
+    if (Tok.is(tok::semi)) {
+      Diag(Tok, diag::ext_extra_struct_semi)
+        << CodeModificationHint::CreateRemoval(Tok.getLocation());
+      ConsumeToken();
+      continue;
+    }
+
+    // Parse all the comma separated declarators.
+    DeclSpec DS;
+
+    if (!Tok.is(tok::at)) {
+      struct CFieldCallback : FieldCallback {
+        Parser &P;
+        DeclPtrTy TagDecl;
+        llvm::SmallVectorImpl<DeclPtrTy> &FieldDecls;
+
+        CFieldCallback(Parser &P, DeclPtrTy TagDecl,
+                       llvm::SmallVectorImpl<DeclPtrTy> &FieldDecls) :
+          P(P), TagDecl(TagDecl), FieldDecls(FieldDecls) {}
+
+        virtual DeclPtrTy invoke(FieldDeclarator &FD) {
+          // Install the declarator into the current TagDecl.
+          DeclPtrTy Field = P.Actions.ActOnField(P.CurScope, TagDecl,
+                              FD.D.getDeclSpec().getSourceRange().getBegin(),
+                                                 FD.D, FD.BitfieldSize);
+          FieldDecls.push_back(Field);
+          return Field;
+        }
+      } Callback(*this, TagDecl, FieldDecls);
+
+      ParseStructDeclaration(DS, Callback);
+    } else { // Handle @defs
+      ConsumeToken();
+      if (!Tok.isObjCAtKeyword(tok::objc_defs)) {
+        Diag(Tok, diag::err_unexpected_at);
+        SkipUntil(tok::semi, true);
+        continue;
+      }
+      ConsumeToken();
+      ExpectAndConsume(tok::l_paren, diag::err_expected_lparen);
+      if (!Tok.is(tok::identifier)) {
+        Diag(Tok, diag::err_expected_ident);
+        SkipUntil(tok::semi, true);
+        continue;
+      }
+      llvm::SmallVector<DeclPtrTy, 16> Fields;
+      Actions.ActOnDefs(CurScope, TagDecl, Tok.getLocation(),
+                        Tok.getIdentifierInfo(), Fields);
+      FieldDecls.insert(FieldDecls.end(), Fields.begin(), Fields.end());
+      ConsumeToken();
+      ExpectAndConsume(tok::r_paren, diag::err_expected_rparen);
+    }
+
+    if (Tok.is(tok::semi)) {
+      ConsumeToken();
+    } else if (Tok.is(tok::r_brace)) {
+      ExpectAndConsume(tok::semi, diag::ext_expected_semi_decl_list);
+      break;
+    } else {
+      ExpectAndConsume(tok::semi, diag::err_expected_semi_decl_list);
+      // Skip to end of block or statement to avoid ext-warning on extra ';'.
+      SkipUntil(tok::r_brace, true, true);
+      // If we stopped at a ';', eat it.
+      if (Tok.is(tok::semi)) ConsumeToken();
+    }
+  }
+
+  SourceLocation RBraceLoc = MatchRHSPunctuation(tok::r_brace, LBraceLoc);
+
+  AttributeList *AttrList = 0;
+  // If attributes exist after struct contents, parse them.
+  if (Tok.is(tok::kw___attribute))
+    AttrList = ParseGNUAttributes();
+
+  Actions.ActOnFields(CurScope,
+                      RecordLoc, TagDecl, FieldDecls.data(), FieldDecls.size(),
+                      LBraceLoc, RBraceLoc,
+                      AttrList);
+  StructScope.Exit();
+  Actions.ActOnTagFinishDefinition(CurScope, TagDecl, RBraceLoc);
+}
+
+
+/// ParseEnumSpecifier
+///       enum-specifier: [C99 6.7.2.2]
+///         'enum' identifier[opt] '{' enumerator-list '}'
+///[C99/C++]'enum' identifier[opt] '{' enumerator-list ',' '}'
+/// [GNU]   'enum' attributes[opt] identifier[opt] '{' enumerator-list ',' [opt]
+///                                                 '}' attributes[opt]
+///         'enum' identifier
+/// [GNU]   'enum' attributes[opt] identifier
+///
+/// [C++] elaborated-type-specifier:
+/// [C++]   'enum' '::'[opt] nested-name-specifier[opt] identifier
+///
+void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS,
+                                AccessSpecifier AS) {
+  // Parse the tag portion of this.
+  if (Tok.is(tok::code_completion)) {
+    // Code completion for an enum name.
+    Actions.CodeCompleteTag(CurScope, DeclSpec::TST_enum);
+    ConsumeToken();
+  }
+  
+  AttributeList *Attr = 0;
+  // If attributes exist after tag, parse them.
+  if (Tok.is(tok::kw___attribute))
+    Attr = ParseGNUAttributes();
+
+  CXXScopeSpec SS;
+  if (getLang().CPlusPlus && ParseOptionalCXXScopeSpecifier(SS, 0, false)) {
+    if (Tok.isNot(tok::identifier)) {
+      Diag(Tok, diag::err_expected_ident);
+      if (Tok.isNot(tok::l_brace)) {
+        // Has no name and is not a definition.
+        // Skip the rest of this declarator, up until the comma or semicolon.
+        SkipUntil(tok::comma, true);
+        return;
+      }
+    }
+  }
+
+  // Must have either 'enum name' or 'enum {...}'.
+  if (Tok.isNot(tok::identifier) && Tok.isNot(tok::l_brace)) {
+    Diag(Tok, diag::err_expected_ident_lbrace);
+
+    // Skip the rest of this declarator, up until the comma or semicolon.
+    SkipUntil(tok::comma, true);
+    return;
+  }
+
+  // If an identifier is present, consume and remember it.
+  IdentifierInfo *Name = 0;
+  SourceLocation NameLoc;
+  if (Tok.is(tok::identifier)) {
+    Name = Tok.getIdentifierInfo();
+    NameLoc = ConsumeToken();
+  }
+
+  // There are three options here.  If we have 'enum foo;', then this is a
+  // forward declaration.  If we have 'enum foo {...' then this is a
+  // definition. Otherwise we have something like 'enum foo xyz', a reference.
+  //
+  // This is needed to handle stuff like this right (C99 6.7.2.3p11):
+  // enum foo {..};  void bar() { enum foo; }    <- new foo in bar.
+  // enum foo {..};  void bar() { enum foo x; }  <- use of old foo.
+  //
+  Action::TagUseKind TUK;
+  if (Tok.is(tok::l_brace))
+    TUK = Action::TUK_Definition;
+  else if (Tok.is(tok::semi))
+    TUK = Action::TUK_Declaration;
+  else
+    TUK = Action::TUK_Reference;
+  bool Owned = false;
+  bool IsDependent = false;
+  DeclPtrTy TagDecl = Actions.ActOnTag(CurScope, DeclSpec::TST_enum, TUK,
+                                       StartLoc, SS, Name, NameLoc, Attr, AS,
+                                       Action::MultiTemplateParamsArg(Actions),
+                                       Owned, IsDependent);
+  assert(!IsDependent && "didn't expect dependent enum");
+
+  if (Tok.is(tok::l_brace))
+    ParseEnumBody(StartLoc, TagDecl);
+
+  // FIXME: The DeclSpec should keep the locations of both the keyword and the
+  // name (if there is one).
+  SourceLocation TSTLoc = NameLoc.isValid()? NameLoc : StartLoc;
+  const char *PrevSpec = 0;
+  unsigned DiagID;
+  if (DS.SetTypeSpecType(DeclSpec::TST_enum, TSTLoc, PrevSpec, DiagID,
+                         TagDecl.getAs<void>(), Owned))
+    Diag(StartLoc, DiagID) << PrevSpec;
+}
+
+/// ParseEnumBody - Parse a {} enclosed enumerator-list.
+///       enumerator-list:
+///         enumerator
+///         enumerator-list ',' enumerator
+///       enumerator:
+///         enumeration-constant
+///         enumeration-constant '=' constant-expression
+///       enumeration-constant:
+///         identifier
+///
+void Parser::ParseEnumBody(SourceLocation StartLoc, DeclPtrTy EnumDecl) {
+  // Enter the scope of the enum body and start the definition.
+  ParseScope EnumScope(this, Scope::DeclScope);
+  Actions.ActOnTagStartDefinition(CurScope, EnumDecl);
+
+  SourceLocation LBraceLoc = ConsumeBrace();
+
+  // C does not allow an empty enumerator-list, C++ does [dcl.enum].
+  if (Tok.is(tok::r_brace) && !getLang().CPlusPlus)
+    Diag(Tok, diag::ext_empty_struct_union_enum) << "enum";
+
+  llvm::SmallVector<DeclPtrTy, 32> EnumConstantDecls;
+
+  DeclPtrTy LastEnumConstDecl;
+
+  // Parse the enumerator-list.
+  while (Tok.is(tok::identifier)) {
+    IdentifierInfo *Ident = Tok.getIdentifierInfo();
+    SourceLocation IdentLoc = ConsumeToken();
+
+    SourceLocation EqualLoc;
+    OwningExprResult AssignedVal(Actions);
+    if (Tok.is(tok::equal)) {
+      EqualLoc = ConsumeToken();
+      AssignedVal = ParseConstantExpression();
+      if (AssignedVal.isInvalid())
+        SkipUntil(tok::comma, tok::r_brace, true, true);
+    }
+
+    // Install the enumerator constant into EnumDecl.
+    DeclPtrTy EnumConstDecl = Actions.ActOnEnumConstant(CurScope, EnumDecl,
+                                                        LastEnumConstDecl,
+                                                        IdentLoc, Ident,
+                                                        EqualLoc,
+                                                        AssignedVal.release());
+    EnumConstantDecls.push_back(EnumConstDecl);
+    LastEnumConstDecl = EnumConstDecl;
+
+    if (Tok.isNot(tok::comma))
+      break;
+    SourceLocation CommaLoc = ConsumeToken();
+
+    if (Tok.isNot(tok::identifier) &&
+        !(getLang().C99 || getLang().CPlusPlus0x))
+      Diag(CommaLoc, diag::ext_enumerator_list_comma)
+        << getLang().CPlusPlus
+        << CodeModificationHint::CreateRemoval(CommaLoc);
+  }
+
+  // Eat the }.
+  SourceLocation RBraceLoc = MatchRHSPunctuation(tok::r_brace, LBraceLoc);
+
+  AttributeList *Attr = 0;
+  // If attributes exist after the identifier list, parse them.
+  if (Tok.is(tok::kw___attribute))
+    Attr = ParseGNUAttributes(); // FIXME: where do they do?
+
+  Actions.ActOnEnumBody(StartLoc, LBraceLoc, RBraceLoc, EnumDecl,
+                        EnumConstantDecls.data(), EnumConstantDecls.size(),
+                        CurScope, Attr);
+
+  EnumScope.Exit();
+  Actions.ActOnTagFinishDefinition(CurScope, EnumDecl, RBraceLoc);
+}
+
+/// isTypeSpecifierQualifier - Return true if the current token could be the
+/// start of a type-qualifier-list.
+bool Parser::isTypeQualifier() const {
+  switch (Tok.getKind()) {
+  default: return false;
+    // type-qualifier
+  case tok::kw_const:
+  case tok::kw_volatile:
+  case tok::kw_restrict:
+    return true;
+  }
+}
+
+/// isTypeSpecifierQualifier - Return true if the current token could be the
+/// start of a specifier-qualifier-list.
+bool Parser::isTypeSpecifierQualifier() {
+  switch (Tok.getKind()) {
+  default: return false;
+
+  case tok::identifier:   // foo::bar
+    if (TryAltiVecVectorToken())
+      return true;
+    // Fall through.
+  case tok::kw_typename:  // typename T::type
+    // Annotate typenames and C++ scope specifiers.  If we get one, just
+    // recurse to handle whatever we get.
+    if (TryAnnotateTypeOrScopeToken())
+      return isTypeSpecifierQualifier();
+    // Otherwise, not a type specifier.
+    return false;
+
+  case tok::coloncolon:   // ::foo::bar
+    if (NextToken().is(tok::kw_new) ||    // ::new
+        NextToken().is(tok::kw_delete))   // ::delete
+      return false;
+
+    // Annotate typenames and C++ scope specifiers.  If we get one, just
+    // recurse to handle whatever we get.
+    if (TryAnnotateTypeOrScopeToken())
+      return isTypeSpecifierQualifier();
+    // Otherwise, not a type specifier.
+    return false;
+
+    // GNU attributes support.
+  case tok::kw___attribute:
+    // GNU typeof support.
+  case tok::kw_typeof:
+
+    // type-specifiers
+  case tok::kw_short:
+  case tok::kw_long:
+  case tok::kw_signed:
+  case tok::kw_unsigned:
+  case tok::kw__Complex:
+  case tok::kw__Imaginary:
+  case tok::kw_void:
+  case tok::kw_char:
+  case tok::kw_wchar_t:
+  case tok::kw_char16_t:
+  case tok::kw_char32_t:
+  case tok::kw_int:
+  case tok::kw_float:
+  case tok::kw_double:
+  case tok::kw_bool:
+  case tok::kw__Bool:
+  case tok::kw__Decimal32:
+  case tok::kw__Decimal64:
+  case tok::kw__Decimal128:
+  case tok::kw___vector:
+
+    // struct-or-union-specifier (C99) or class-specifier (C++)
+  case tok::kw_class:
+  case tok::kw_struct:
+  case tok::kw_union:
+    // enum-specifier
+  case tok::kw_enum:
+
+    // type-qualifier
+  case tok::kw_const:
+  case tok::kw_volatile:
+  case tok::kw_restrict:
+
+    // typedef-name
+  case tok::annot_typename:
+    return true;
+
+    // GNU ObjC bizarre protocol extension: <proto1,proto2> with implicit 'id'.
+  case tok::less:
+    return getLang().ObjC1;
+
+  case tok::kw___cdecl:
+  case tok::kw___stdcall:
+  case tok::kw___fastcall:
+  case tok::kw___w64:
+  case tok::kw___ptr64:
+    return true;
+  }
+}
+
+/// isDeclarationSpecifier() - Return true if the current token is part of a
+/// declaration specifier.
+bool Parser::isDeclarationSpecifier() {
+  switch (Tok.getKind()) {
+  default: return false;
+
+  case tok::identifier:   // foo::bar
+    // Unfortunate hack to support "Class.factoryMethod" notation.
+    if (getLang().ObjC1 && NextToken().is(tok::period))
+      return false;
+    if (TryAltiVecVectorToken())
+      return true;
+    // Fall through.
+
+  case tok::kw_typename: // typename T::type
+    // Annotate typenames and C++ scope specifiers.  If we get one, just
+    // recurse to handle whatever we get.
+    if (TryAnnotateTypeOrScopeToken())
+      return isDeclarationSpecifier();
+    // Otherwise, not a declaration specifier.
+    return false;
+  case tok::coloncolon:   // ::foo::bar
+    if (NextToken().is(tok::kw_new) ||    // ::new
+        NextToken().is(tok::kw_delete))   // ::delete
+      return false;
+
+    // Annotate typenames and C++ scope specifiers.  If we get one, just
+    // recurse to handle whatever we get.
+    if (TryAnnotateTypeOrScopeToken())
+      return isDeclarationSpecifier();
+    // Otherwise, not a declaration specifier.
+    return false;
+
+    // storage-class-specifier
+  case tok::kw_typedef:
+  case tok::kw_extern:
+  case tok::kw___private_extern__:
+  case tok::kw_static:
+  case tok::kw_auto:
+  case tok::kw_register:
+  case tok::kw___thread:
+
+    // type-specifiers
+  case tok::kw_short:
+  case tok::kw_long:
+  case tok::kw_signed:
+  case tok::kw_unsigned:
+  case tok::kw__Complex:
+  case tok::kw__Imaginary:
+  case tok::kw_void:
+  case tok::kw_char:
+  case tok::kw_wchar_t:
+  case tok::kw_char16_t:
+  case tok::kw_char32_t:
+
+  case tok::kw_int:
+  case tok::kw_float:
+  case tok::kw_double:
+  case tok::kw_bool:
+  case tok::kw__Bool:
+  case tok::kw__Decimal32:
+  case tok::kw__Decimal64:
+  case tok::kw__Decimal128:
+  case tok::kw___vector:
+
+    // struct-or-union-specifier (C99) or class-specifier (C++)
+  case tok::kw_class:
+  case tok::kw_struct:
+  case tok::kw_union:
+    // enum-specifier
+  case tok::kw_enum:
+
+    // type-qualifier
+  case tok::kw_const:
+  case tok::kw_volatile:
+  case tok::kw_restrict:
+
+    // function-specifier
+  case tok::kw_inline:
+  case tok::kw_virtual:
+  case tok::kw_explicit:
+
+    // typedef-name
+  case tok::annot_typename:
+
+    // GNU typeof support.
+  case tok::kw_typeof:
+
+    // GNU attributes.
+  case tok::kw___attribute:
+    return true;
+
+    // GNU ObjC bizarre protocol extension: <proto1,proto2> with implicit 'id'.
+  case tok::less:
+    return getLang().ObjC1;
+
+  case tok::kw___declspec:
+  case tok::kw___cdecl:
+  case tok::kw___stdcall:
+  case tok::kw___fastcall:
+  case tok::kw___w64:
+  case tok::kw___ptr64:
+  case tok::kw___forceinline:
+    return true;
+  }
+}
+
+bool Parser::isConstructorDeclarator() {
+  TentativeParsingAction TPA(*this);
+
+  // Parse the C++ scope specifier.
+  CXXScopeSpec SS;
+  ParseOptionalCXXScopeSpecifier(SS, 0, true);
+
+  // Parse the constructor name.
+  if (Tok.is(tok::identifier) || Tok.is(tok::annot_template_id)) {
+    // We already know that we have a constructor name; just consume
+    // the token.
+    ConsumeToken();
+  } else {
+    TPA.Revert();
+    return false;
+  }
+
+  // Current class name must be followed by a left parentheses.
+  if (Tok.isNot(tok::l_paren)) {
+    TPA.Revert();
+    return false;
+  }
+  ConsumeParen();
+
+  // A right parentheses or ellipsis signals that we have a constructor.
+  if (Tok.is(tok::r_paren) || Tok.is(tok::ellipsis)) {
+    TPA.Revert();
+    return true;
+  }
+
+  // If we need to, enter the specified scope.
+  DeclaratorScopeObj DeclScopeObj(*this, SS);
+  if (SS.isSet() && Actions.ShouldEnterDeclaratorScope(CurScope, SS))
+    DeclScopeObj.EnterDeclaratorScope();
+
+  // Check whether the next token(s) are part of a declaration
+  // specifier, in which case we have the start of a parameter and,
+  // therefore, we know that this is a constructor.
+  bool IsConstructor = isDeclarationSpecifier();
+  TPA.Revert();
+  return IsConstructor;
+}
+
+/// ParseTypeQualifierListOpt
+///       type-qualifier-list: [C99 6.7.5]
+///         type-qualifier
+/// [GNU]   attributes                        [ only if AttributesAllowed=true ]
+///         type-qualifier-list type-qualifier
+/// [GNU]   type-qualifier-list attributes    [ only if AttributesAllowed=true ]
+/// [C++0x] attribute-specifier[opt] is allowed before cv-qualifier-seq
+///           if CXX0XAttributesAllowed = true
+///
+void Parser::ParseTypeQualifierListOpt(DeclSpec &DS, bool GNUAttributesAllowed,
+                                       bool CXX0XAttributesAllowed) {
+  if (getLang().CPlusPlus0x && isCXX0XAttributeSpecifier()) {
+    SourceLocation Loc = Tok.getLocation();
+    CXX0XAttributeList Attr = ParseCXX0XAttributes();
+    if (CXX0XAttributesAllowed)
+      DS.AddAttributes(Attr.AttrList);
+    else
+      Diag(Loc, diag::err_attributes_not_allowed);
+  }
+  
+  while (1) {
+    bool isInvalid = false;
+    const char *PrevSpec = 0;
+    unsigned DiagID = 0;
+    SourceLocation Loc = Tok.getLocation();
+
+    switch (Tok.getKind()) {
+    case tok::kw_const:
+      isInvalid = DS.SetTypeQual(DeclSpec::TQ_const   , Loc, PrevSpec, DiagID,
+                                 getLang());
+      break;
+    case tok::kw_volatile:
+      isInvalid = DS.SetTypeQual(DeclSpec::TQ_volatile, Loc, PrevSpec, DiagID,
+                                 getLang());
+      break;
+    case tok::kw_restrict:
+      isInvalid = DS.SetTypeQual(DeclSpec::TQ_restrict, Loc, PrevSpec, DiagID,
+                                 getLang());
+      break;
+    case tok::kw___w64:
+    case tok::kw___ptr64:
+    case tok::kw___cdecl:
+    case tok::kw___stdcall:
+    case tok::kw___fastcall:
+      if (GNUAttributesAllowed) {
+        DS.AddAttributes(ParseMicrosoftTypeAttributes());
+        continue;
+      }
+      goto DoneWithTypeQuals;
+    case tok::kw___attribute:
+      if (GNUAttributesAllowed) {
+        DS.AddAttributes(ParseGNUAttributes());
+        continue; // do *not* consume the next token!
+      }
+      // otherwise, FALL THROUGH!
+    default:
+      DoneWithTypeQuals:
+      // If this is not a type-qualifier token, we're done reading type
+      // qualifiers.  First verify that DeclSpec's are consistent.
+      DS.Finish(Diags, PP);
+      return;
+    }
+
+    // If the specifier combination wasn't legal, issue a diagnostic.
+    if (isInvalid) {
+      assert(PrevSpec && "Method did not return previous specifier!");
+      Diag(Tok, DiagID) << PrevSpec;
+    }
+    ConsumeToken();
+  }
+}
+
+
+/// ParseDeclarator - Parse and verify a newly-initialized declarator.
+///
+void Parser::ParseDeclarator(Declarator &D) {
+  /// This implements the 'declarator' production in the C grammar, then checks
+  /// for well-formedness and issues diagnostics.
+  ParseDeclaratorInternal(D, &Parser::ParseDirectDeclarator);
+}
+
+/// ParseDeclaratorInternal - Parse a C or C++ declarator. The direct-declarator
+/// is parsed by the function passed to it. Pass null, and the direct-declarator
+/// isn't parsed at all, making this function effectively parse the C++
+/// ptr-operator production.
+///
+///       declarator: [C99 6.7.5] [C++ 8p4, dcl.decl]
+/// [C]     pointer[opt] direct-declarator
+/// [C++]   direct-declarator
+/// [C++]   ptr-operator declarator
+///
+///       pointer: [C99 6.7.5]
+///         '*' type-qualifier-list[opt]
+///         '*' type-qualifier-list[opt] pointer
+///
+///       ptr-operator:
+///         '*' cv-qualifier-seq[opt]
+///         '&'
+/// [C++0x] '&&'
+/// [GNU]   '&' restrict[opt] attributes[opt]
+/// [GNU?]  '&&' restrict[opt] attributes[opt]
+///         '::'[opt] nested-name-specifier '*' cv-qualifier-seq[opt]
+void Parser::ParseDeclaratorInternal(Declarator &D,
+                                     DirectDeclParseFunction DirectDeclParser) {
+  if (Diags.hasAllExtensionsSilenced())
+    D.setExtension();
+  // C++ member pointers start with a '::' or a nested-name.
+  // Member pointers get special handling, since there's no place for the
+  // scope spec in the generic path below.
+  if (getLang().CPlusPlus &&
+      (Tok.is(tok::coloncolon) || Tok.is(tok::identifier) ||
+       Tok.is(tok::annot_cxxscope))) {
+    CXXScopeSpec SS;
+    if (ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/0, true)) {
+      if (Tok.isNot(tok::star)) {
+        // The scope spec really belongs to the direct-declarator.
+        D.getCXXScopeSpec() = SS;
+        if (DirectDeclParser)
+          (this->*DirectDeclParser)(D);
+        return;
+      }
+
+      SourceLocation Loc = ConsumeToken();
+      D.SetRangeEnd(Loc);
+      DeclSpec DS;
+      ParseTypeQualifierListOpt(DS);
+      D.ExtendWithDeclSpec(DS);
+
+      // Recurse to parse whatever is left.
+      ParseDeclaratorInternal(D, DirectDeclParser);
+
+      // Sema will have to catch (syntactically invalid) pointers into global
+      // scope. It has to catch pointers into namespace scope anyway.
+      D.AddTypeInfo(DeclaratorChunk::getMemberPointer(SS,DS.getTypeQualifiers(),
+                                                      Loc, DS.TakeAttributes()),
+                    /* Don't replace range end. */SourceLocation());
+      return;
+    }
+  }
+
+  tok::TokenKind Kind = Tok.getKind();
+  // Not a pointer, C++ reference, or block.
+  if (Kind != tok::star && Kind != tok::caret &&
+      (Kind != tok::amp || !getLang().CPlusPlus) &&
+      // We parse rvalue refs in C++03, because otherwise the errors are scary.
+      (Kind != tok::ampamp || !getLang().CPlusPlus)) {
+    if (DirectDeclParser)
+      (this->*DirectDeclParser)(D);
+    return;
+  }
+
+  // Otherwise, '*' -> pointer, '^' -> block, '&' -> lvalue reference,
+  // '&&' -> rvalue reference
+  SourceLocation Loc = ConsumeToken();  // Eat the *, ^, & or &&.
+  D.SetRangeEnd(Loc);
+
+  if (Kind == tok::star || Kind == tok::caret) {
+    // Is a pointer.
+    DeclSpec DS;
+
+    ParseTypeQualifierListOpt(DS);
+    D.ExtendWithDeclSpec(DS);
+
+    // Recursively parse the declarator.
+    ParseDeclaratorInternal(D, DirectDeclParser);
+    if (Kind == tok::star)
+      // Remember that we parsed a pointer type, and remember the type-quals.
+      D.AddTypeInfo(DeclaratorChunk::getPointer(DS.getTypeQualifiers(), Loc,
+                                                DS.TakeAttributes()),
+                    SourceLocation());
+    else
+      // Remember that we parsed a Block type, and remember the type-quals.
+      D.AddTypeInfo(DeclaratorChunk::getBlockPointer(DS.getTypeQualifiers(),
+                                                     Loc, DS.TakeAttributes()),
+                    SourceLocation());
+  } else {
+    // Is a reference
+    DeclSpec DS;
+
+    // Complain about rvalue references in C++03, but then go on and build
+    // the declarator.
+    if (Kind == tok::ampamp && !getLang().CPlusPlus0x)
+      Diag(Loc, diag::err_rvalue_reference);
+
+    // C++ 8.3.2p1: cv-qualified references are ill-formed except when the
+    // cv-qualifiers are introduced through the use of a typedef or of a
+    // template type argument, in which case the cv-qualifiers are ignored.
+    //
+    // [GNU] Retricted references are allowed.
+    // [GNU] Attributes on references are allowed.
+    // [C++0x] Attributes on references are not allowed.
+    ParseTypeQualifierListOpt(DS, true, false);
+    D.ExtendWithDeclSpec(DS);
+
+    if (DS.getTypeQualifiers() != DeclSpec::TQ_unspecified) {
+      if (DS.getTypeQualifiers() & DeclSpec::TQ_const)
+        Diag(DS.getConstSpecLoc(),
+             diag::err_invalid_reference_qualifier_application) << "const";
+      if (DS.getTypeQualifiers() & DeclSpec::TQ_volatile)
+        Diag(DS.getVolatileSpecLoc(),
+             diag::err_invalid_reference_qualifier_application) << "volatile";
+    }
+
+    // Recursively parse the declarator.
+    ParseDeclaratorInternal(D, DirectDeclParser);
+
+    if (D.getNumTypeObjects() > 0) {
+      // C++ [dcl.ref]p4: There shall be no references to references.
+      DeclaratorChunk& InnerChunk = D.getTypeObject(D.getNumTypeObjects() - 1);
+      if (InnerChunk.Kind == DeclaratorChunk::Reference) {
+        if (const IdentifierInfo *II = D.getIdentifier())
+          Diag(InnerChunk.Loc, diag::err_illegal_decl_reference_to_reference)
+           << II;
+        else
+          Diag(InnerChunk.Loc, diag::err_illegal_decl_reference_to_reference)
+            << "type name";
+
+        // Once we've complained about the reference-to-reference, we
+        // can go ahead and build the (technically ill-formed)
+        // declarator: reference collapsing will take care of it.
+      }
+    }
+
+    // Remember that we parsed a reference type. It doesn't have type-quals.
+    D.AddTypeInfo(DeclaratorChunk::getReference(DS.getTypeQualifiers(), Loc,
+                                                DS.TakeAttributes(),
+                                                Kind == tok::amp),
+                  SourceLocation());
+  }
+}
+
+/// ParseDirectDeclarator
+///       direct-declarator: [C99 6.7.5]
+/// [C99]   identifier
+///         '(' declarator ')'
+/// [GNU]   '(' attributes declarator ')'
+/// [C90]   direct-declarator '[' constant-expression[opt] ']'
+/// [C99]   direct-declarator '[' type-qual-list[opt] assignment-expr[opt] ']'
+/// [C99]   direct-declarator '[' 'static' type-qual-list[opt] assign-expr ']'
+/// [C99]   direct-declarator '[' type-qual-list 'static' assignment-expr ']'
+/// [C99]   direct-declarator '[' type-qual-list[opt] '*' ']'
+///         direct-declarator '(' parameter-type-list ')'
+///         direct-declarator '(' identifier-list[opt] ')'
+/// [GNU]   direct-declarator '(' parameter-forward-declarations
+///                    parameter-type-list[opt] ')'
+/// [C++]   direct-declarator '(' parameter-declaration-clause ')'
+///                    cv-qualifier-seq[opt] exception-specification[opt]
+/// [C++]   declarator-id
+///
+///       declarator-id: [C++ 8]
+///         id-expression
+///         '::'[opt] nested-name-specifier[opt] type-name
+///
+///       id-expression: [C++ 5.1]
+///         unqualified-id
+///         qualified-id
+///
+///       unqualified-id: [C++ 5.1]
+///         identifier
+///         operator-function-id
+///         conversion-function-id
+///          '~' class-name
+///         template-id
+///
+void Parser::ParseDirectDeclarator(Declarator &D) {
+  DeclaratorScopeObj DeclScopeObj(*this, D.getCXXScopeSpec());
+
+  if (getLang().CPlusPlus && D.mayHaveIdentifier()) {
+    // ParseDeclaratorInternal might already have parsed the scope.
+    bool afterCXXScope = D.getCXXScopeSpec().isSet() ||
+      ParseOptionalCXXScopeSpecifier(D.getCXXScopeSpec(), /*ObjectType=*/0,
+                                     true);
+    if (afterCXXScope) {
+      if (Actions.ShouldEnterDeclaratorScope(CurScope, D.getCXXScopeSpec()))
+        // Change the declaration context for name lookup, until this function
+        // is exited (and the declarator has been parsed).
+        DeclScopeObj.EnterDeclaratorScope();
+    } 
+    
+    if (Tok.is(tok::identifier) || Tok.is(tok::kw_operator) ||
+        Tok.is(tok::annot_template_id) || Tok.is(tok::tilde)) {
+      // We found something that indicates the start of an unqualified-id.
+      // Parse that unqualified-id.
+      bool AllowConstructorName
+        = ((D.getCXXScopeSpec().isSet() && 
+            D.getContext() == Declarator::FileContext) ||
+           (!D.getCXXScopeSpec().isSet() &&
+            D.getContext() == Declarator::MemberContext)) &&
+        !D.getDeclSpec().hasTypeSpecifier();
+      if (ParseUnqualifiedId(D.getCXXScopeSpec(), 
+                             /*EnteringContext=*/true, 
+                             /*AllowDestructorName=*/true, 
+                             AllowConstructorName,
+                             /*ObjectType=*/0,
+                             D.getName())) {
+        D.SetIdentifier(0, Tok.getLocation());
+        D.setInvalidType(true);
+      } else {
+        // Parsed the unqualified-id; update range information and move along.
+        if (D.getSourceRange().getBegin().isInvalid())
+          D.SetRangeBegin(D.getName().getSourceRange().getBegin());
+        D.SetRangeEnd(D.getName().getSourceRange().getEnd());
+      }
+      goto PastIdentifier;
+    }
+  } else if (Tok.is(tok::identifier) && D.mayHaveIdentifier()) {
+    assert(!getLang().CPlusPlus &&
+           "There's a C++-specific check for tok::identifier above");
+    assert(Tok.getIdentifierInfo() && "Not an identifier?");
+    D.SetIdentifier(Tok.getIdentifierInfo(), Tok.getLocation());
+    ConsumeToken();
+    goto PastIdentifier;
+  }
+    
+  if (Tok.is(tok::l_paren)) {
+    // direct-declarator: '(' declarator ')'
+    // direct-declarator: '(' attributes declarator ')'
+    // Example: 'char (*X)'   or 'int (*XX)(void)'
+    ParseParenDeclarator(D);
+
+    // If the declarator was parenthesized, we entered the declarator
+    // scope when parsing the parenthesized declarator, then exited
+    // the scope already. Re-enter the scope, if we need to.
+    if (D.getCXXScopeSpec().isSet()) {
+      if (Actions.ShouldEnterDeclaratorScope(CurScope, D.getCXXScopeSpec()))
+        // Change the declaration context for name lookup, until this function
+        // is exited (and the declarator has been parsed).
+        DeclScopeObj.EnterDeclaratorScope();
+    }
+  } else if (D.mayOmitIdentifier()) {
+    // This could be something simple like "int" (in which case the declarator
+    // portion is empty), if an abstract-declarator is allowed.
+    D.SetIdentifier(0, Tok.getLocation());
+  } else {
+    if (D.getContext() == Declarator::MemberContext)
+      Diag(Tok, diag::err_expected_member_name_or_semi)
+        << D.getDeclSpec().getSourceRange();
+    else if (getLang().CPlusPlus)
+      Diag(Tok, diag::err_expected_unqualified_id) << getLang().CPlusPlus;
+    else
+      Diag(Tok, diag::err_expected_ident_lparen);
+    D.SetIdentifier(0, Tok.getLocation());
+    D.setInvalidType(true);
+  }
+
+ PastIdentifier:
+  assert(D.isPastIdentifier() &&
+         "Haven't past the location of the identifier yet?");
+
+  // Don't parse attributes unless we have an identifier.
+  if (D.getIdentifier() && getLang().CPlusPlus
+   && isCXX0XAttributeSpecifier(true)) {
+    SourceLocation AttrEndLoc;
+    CXX0XAttributeList Attr = ParseCXX0XAttributes();
+    D.AddAttributes(Attr.AttrList, AttrEndLoc);
+  }
+
+  while (1) {
+    if (Tok.is(tok::l_paren)) {
+      // The paren may be part of a C++ direct initializer, eg. "int x(1);".
+      // In such a case, check if we actually have a function declarator; if it
+      // is not, the declarator has been fully parsed.
+      if (getLang().CPlusPlus && D.mayBeFollowedByCXXDirectInit()) {
+        // When not in file scope, warn for ambiguous function declarators, just
+        // in case the author intended it as a variable definition.
+        bool warnIfAmbiguous = D.getContext() != Declarator::FileContext;
+        if (!isCXXFunctionDeclarator(warnIfAmbiguous))
+          break;
+      }
+      ParseFunctionDeclarator(ConsumeParen(), D);
+    } else if (Tok.is(tok::l_square)) {
+      ParseBracketDeclarator(D);
+    } else {
+      break;
+    }
+  }
+}
+
+/// ParseParenDeclarator - We parsed the declarator D up to a paren.  This is
+/// only called before the identifier, so these are most likely just grouping
+/// parens for precedence.  If we find that these are actually function
+/// parameter parens in an abstract-declarator, we call ParseFunctionDeclarator.
+///
+///       direct-declarator:
+///         '(' declarator ')'
+/// [GNU]   '(' attributes declarator ')'
+///         direct-declarator '(' parameter-type-list ')'
+///         direct-declarator '(' identifier-list[opt] ')'
+/// [GNU]   direct-declarator '(' parameter-forward-declarations
+///                    parameter-type-list[opt] ')'
+///
+void Parser::ParseParenDeclarator(Declarator &D) {
+  SourceLocation StartLoc = ConsumeParen();
+  assert(!D.isPastIdentifier() && "Should be called before passing identifier");
+
+  // Eat any attributes before we look at whether this is a grouping or function
+  // declarator paren.  If this is a grouping paren, the attribute applies to
+  // the type being built up, for example:
+  //     int (__attribute__(()) *x)(long y)
+  // If this ends up not being a grouping paren, the attribute applies to the
+  // first argument, for example:
+  //     int (__attribute__(()) int x)
+  // In either case, we need to eat any attributes to be able to determine what
+  // sort of paren this is.
+  //
+  AttributeList *AttrList = 0;
+  bool RequiresArg = false;
+  if (Tok.is(tok::kw___attribute)) {
+    AttrList = ParseGNUAttributes();
+
+    // We require that the argument list (if this is a non-grouping paren) be
+    // present even if the attribute list was empty.
+    RequiresArg = true;
+  }
+  // Eat any Microsoft extensions.
+  if  (Tok.is(tok::kw___cdecl) || Tok.is(tok::kw___stdcall) ||
+       Tok.is(tok::kw___fastcall) || Tok.is(tok::kw___w64) ||
+       Tok.is(tok::kw___ptr64)) {
+    AttrList = ParseMicrosoftTypeAttributes(AttrList);
+  }
+
+  // If we haven't past the identifier yet (or where the identifier would be
+  // stored, if this is an abstract declarator), then this is probably just
+  // grouping parens. However, if this could be an abstract-declarator, then
+  // this could also be the start of function arguments (consider 'void()').
+  bool isGrouping;
+
+  if (!D.mayOmitIdentifier()) {
+    // If this can't be an abstract-declarator, this *must* be a grouping
+    // paren, because we haven't seen the identifier yet.
+    isGrouping = true;
+  } else if (Tok.is(tok::r_paren) ||           // 'int()' is a function.
+             (getLang().CPlusPlus && Tok.is(tok::ellipsis)) || // C++ int(...)
+             isDeclarationSpecifier()) {       // 'int(int)' is a function.
+    // This handles C99 6.7.5.3p11: in "typedef int X; void foo(X)", X is
+    // considered to be a type, not a K&R identifier-list.
+    isGrouping = false;
+  } else {
+    // Otherwise, this is a grouping paren, e.g. 'int (*X)' or 'int(X)'.
+    isGrouping = true;
+  }
+
+  // If this is a grouping paren, handle:
+  // direct-declarator: '(' declarator ')'
+  // direct-declarator: '(' attributes declarator ')'
+  if (isGrouping) {
+    bool hadGroupingParens = D.hasGroupingParens();
+    D.setGroupingParens(true);
+    if (AttrList)
+      D.AddAttributes(AttrList, SourceLocation());
+
+    ParseDeclaratorInternal(D, &Parser::ParseDirectDeclarator);
+    // Match the ')'.
+    SourceLocation Loc = MatchRHSPunctuation(tok::r_paren, StartLoc);
+
+    D.setGroupingParens(hadGroupingParens);
+    D.SetRangeEnd(Loc);
+    return;
+  }
+
+  // Okay, if this wasn't a grouping paren, it must be the start of a function
+  // argument list.  Recognize that this declarator will never have an
+  // identifier (and remember where it would have been), then call into
+  // ParseFunctionDeclarator to handle of argument list.
+  D.SetIdentifier(0, Tok.getLocation());
+
+  ParseFunctionDeclarator(StartLoc, D, AttrList, RequiresArg);
+}
+
+/// ParseFunctionDeclarator - We are after the identifier and have parsed the
+/// declarator D up to a paren, which indicates that we are parsing function
+/// arguments.
+///
+/// If AttrList is non-null, then the caller parsed those arguments immediately
+/// after the open paren - they should be considered to be the first argument of
+/// a parameter.  If RequiresArg is true, then the first argument of the
+/// function is required to be present and required to not be an identifier
+/// list.
+///
+/// This method also handles this portion of the grammar:
+///       parameter-type-list: [C99 6.7.5]
+///         parameter-list
+///         parameter-list ',' '...'
+/// [C++]   parameter-list '...'
+///
+///       parameter-list: [C99 6.7.5]
+///         parameter-declaration
+///         parameter-list ',' parameter-declaration
+///
+///       parameter-declaration: [C99 6.7.5]
+///         declaration-specifiers declarator
+/// [C++]   declaration-specifiers declarator '=' assignment-expression
+/// [GNU]   declaration-specifiers declarator attributes
+///         declaration-specifiers abstract-declarator[opt]
+/// [C++]   declaration-specifiers abstract-declarator[opt]
+///           '=' assignment-expression
+/// [GNU]   declaration-specifiers abstract-declarator[opt] attributes
+///
+/// For C++, after the parameter-list, it also parses "cv-qualifier-seq[opt]"
+/// and "exception-specification[opt]".
+///
+void Parser::ParseFunctionDeclarator(SourceLocation LParenLoc, Declarator &D,
+                                     AttributeList *AttrList,
+                                     bool RequiresArg) {
+  // lparen is already consumed!
+  assert(D.isPastIdentifier() && "Should not call before identifier!");
+
+  // This parameter list may be empty.
+  if (Tok.is(tok::r_paren)) {
+    if (RequiresArg) {
+      Diag(Tok, diag::err_argument_required_after_attribute);
+      delete AttrList;
+    }
+
+    SourceLocation RParenLoc = ConsumeParen();  // Eat the closing ')'.
+    SourceLocation EndLoc = RParenLoc;
+
+    // cv-qualifier-seq[opt].
+    DeclSpec DS;
+    bool hasExceptionSpec = false;
+    SourceLocation ThrowLoc;
+    bool hasAnyExceptionSpec = false;
+    llvm::SmallVector<TypeTy*, 2> Exceptions;
+    llvm::SmallVector<SourceRange, 2> ExceptionRanges;
+    if (getLang().CPlusPlus) {
+      ParseTypeQualifierListOpt(DS, false /*no attributes*/);
+      if (!DS.getSourceRange().getEnd().isInvalid())
+        EndLoc = DS.getSourceRange().getEnd();
+
+      // Parse exception-specification[opt].
+      if (Tok.is(tok::kw_throw)) {
+        hasExceptionSpec = true;
+        ThrowLoc = Tok.getLocation();
+        ParseExceptionSpecification(EndLoc, Exceptions, ExceptionRanges,
+                                    hasAnyExceptionSpec);
+        assert(Exceptions.size() == ExceptionRanges.size() &&
+               "Produced different number of exception types and ranges.");
+      }
+    }
+
+    // Remember that we parsed a function type, and remember the attributes.
+    // int() -> no prototype, no '...'.
+    D.AddTypeInfo(DeclaratorChunk::getFunction(/*prototype*/getLang().CPlusPlus,
+                                               /*variadic*/ false,
+                                               SourceLocation(),
+                                               /*arglist*/ 0, 0,
+                                               DS.getTypeQualifiers(),
+                                               hasExceptionSpec, ThrowLoc,
+                                               hasAnyExceptionSpec,
+                                               Exceptions.data(),
+                                               ExceptionRanges.data(),
+                                               Exceptions.size(),
+                                               LParenLoc, RParenLoc, D),
+                  EndLoc);
+    return;
+  }
+
+  // Alternatively, this parameter list may be an identifier list form for a
+  // K&R-style function:  void foo(a,b,c)
+  if (!getLang().CPlusPlus && Tok.is(tok::identifier)
+      && !TryAltiVecVectorToken()) {
+    if (!TryAnnotateTypeOrScopeToken()) {
+      // K&R identifier lists can't have typedefs as identifiers, per
+      // C99 6.7.5.3p11.
+      if (RequiresArg) {
+        Diag(Tok, diag::err_argument_required_after_attribute);
+        delete AttrList;
+      }
+      // Identifier list.  Note that '(' identifier-list ')' is only allowed for
+      // normal declarators, not for abstract-declarators.
+      return ParseFunctionDeclaratorIdentifierList(LParenLoc, D);
+    }
+  }
+
+  // Finally, a normal, non-empty parameter type list.
+
+  // Build up an array of information about the parsed arguments.
+  llvm::SmallVector<DeclaratorChunk::ParamInfo, 16> ParamInfo;
+
+  // Enter function-declaration scope, limiting any declarators to the
+  // function prototype scope, including parameter declarators.
+  ParseScope PrototypeScope(this,
+                            Scope::FunctionPrototypeScope|Scope::DeclScope);
+
+  bool IsVariadic = false;
+  SourceLocation EllipsisLoc;
+  while (1) {
+    if (Tok.is(tok::ellipsis)) {
+      IsVariadic = true;
+      EllipsisLoc = ConsumeToken();     // Consume the ellipsis.
+      break;
+    }
+
+    SourceLocation DSStart = Tok.getLocation();
+
+    // Parse the declaration-specifiers.
+    // Just use the ParsingDeclaration "scope" of the declarator.
+    DeclSpec DS;
+
+    // If the caller parsed attributes for the first argument, add them now.
+    if (AttrList) {
+      DS.AddAttributes(AttrList);
+      AttrList = 0;  // Only apply the attributes to the first parameter.
+    }
+    ParseDeclarationSpecifiers(DS);
+
+    // Parse the declarator.  This is "PrototypeContext", because we must
+    // accept either 'declarator' or 'abstract-declarator' here.
+    Declarator ParmDecl(DS, Declarator::PrototypeContext);
+    ParseDeclarator(ParmDecl);
+
+    // Parse GNU attributes, if present.
+    if (Tok.is(tok::kw___attribute)) {
+      SourceLocation Loc;
+      AttributeList *AttrList = ParseGNUAttributes(&Loc);
+      ParmDecl.AddAttributes(AttrList, Loc);
+    }
+
+    // Remember this parsed parameter in ParamInfo.
+    IdentifierInfo *ParmII = ParmDecl.getIdentifier();
+
+    // DefArgToks is used when the parsing of default arguments needs
+    // to be delayed.
+    CachedTokens *DefArgToks = 0;
+
+    // If no parameter was specified, verify that *something* was specified,
+    // otherwise we have a missing type and identifier.
+    if (DS.isEmpty() && ParmDecl.getIdentifier() == 0 &&
+        ParmDecl.getNumTypeObjects() == 0) {
+      // Completely missing, emit error.
+      Diag(DSStart, diag::err_missing_param);
+    } else {
+      // Otherwise, we have something.  Add it and let semantic analysis try
+      // to grok it and add the result to the ParamInfo we are building.
+
+      // Inform the actions module about the parameter declarator, so it gets
+      // added to the current scope.
+      DeclPtrTy Param = Actions.ActOnParamDeclarator(CurScope, ParmDecl);
+
+      // Parse the default argument, if any. We parse the default
+      // arguments in all dialects; the semantic analysis in
+      // ActOnParamDefaultArgument will reject the default argument in
+      // C.
+      if (Tok.is(tok::equal)) {
+        SourceLocation EqualLoc = Tok.getLocation();
+
+        // Parse the default argument
+        if (D.getContext() == Declarator::MemberContext) {
+          // If we're inside a class definition, cache the tokens
+          // corresponding to the default argument. We'll actually parse
+          // them when we see the end of the class definition.
+          // FIXME: Templates will require something similar.
+          // FIXME: Can we use a smart pointer for Toks?
+          DefArgToks = new CachedTokens;
+
+          if (!ConsumeAndStoreUntil(tok::comma, tok::r_paren, *DefArgToks,
+                                    tok::semi, false)) {
+            delete DefArgToks;
+            DefArgToks = 0;
+            Actions.ActOnParamDefaultArgumentError(Param);
+          } else
+            Actions.ActOnParamUnparsedDefaultArgument(Param, EqualLoc,
+                                                (*DefArgToks)[1].getLocation());
+        } else {
+          // Consume the '='.
+          ConsumeToken();
+
+          OwningExprResult DefArgResult(ParseAssignmentExpression());
+          if (DefArgResult.isInvalid()) {
+            Actions.ActOnParamDefaultArgumentError(Param);
+            SkipUntil(tok::comma, tok::r_paren, true, true);
+          } else {
+            // Inform the actions module about the default argument
+            Actions.ActOnParamDefaultArgument(Param, EqualLoc,
+                                              move(DefArgResult));
+          }
+        }
+      }
+
+      ParamInfo.push_back(DeclaratorChunk::ParamInfo(ParmII,
+                                          ParmDecl.getIdentifierLoc(), Param,
+                                          DefArgToks));
+    }
+
+    // If the next token is a comma, consume it and keep reading arguments.
+    if (Tok.isNot(tok::comma)) {
+      if (Tok.is(tok::ellipsis)) {
+        IsVariadic = true;
+        EllipsisLoc = ConsumeToken();     // Consume the ellipsis.
+        
+        if (!getLang().CPlusPlus) {
+          // We have ellipsis without a preceding ',', which is ill-formed
+          // in C. Complain and provide the fix.
+          Diag(EllipsisLoc, diag::err_missing_comma_before_ellipsis)
+            << CodeModificationHint::CreateInsertion(EllipsisLoc, ", ");
+        }
+      }
+      
+      break;
+    }
+
+    // Consume the comma.
+    ConsumeToken();
+  }
+
+  // Leave prototype scope.
+  PrototypeScope.Exit();
+
+  // If we have the closing ')', eat it.
+  SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc);
+  SourceLocation EndLoc = RParenLoc;
+
+  DeclSpec DS;
+  bool hasExceptionSpec = false;
+  SourceLocation ThrowLoc;
+  bool hasAnyExceptionSpec = false;
+  llvm::SmallVector<TypeTy*, 2> Exceptions;
+  llvm::SmallVector<SourceRange, 2> ExceptionRanges;
+  
+  if (getLang().CPlusPlus) {
+    // Parse cv-qualifier-seq[opt].
+    ParseTypeQualifierListOpt(DS, false /*no attributes*/);
+      if (!DS.getSourceRange().getEnd().isInvalid())
+        EndLoc = DS.getSourceRange().getEnd();
+
+    // Parse exception-specification[opt].
+    if (Tok.is(tok::kw_throw)) {
+      hasExceptionSpec = true;
+      ThrowLoc = Tok.getLocation();
+      ParseExceptionSpecification(EndLoc, Exceptions, ExceptionRanges,
+                                  hasAnyExceptionSpec);
+      assert(Exceptions.size() == ExceptionRanges.size() &&
+             "Produced different number of exception types and ranges.");
+    }
+  }
+
+  // Remember that we parsed a function type, and remember the attributes.
+  D.AddTypeInfo(DeclaratorChunk::getFunction(/*proto*/true, IsVariadic,
+                                             EllipsisLoc,
+                                             ParamInfo.data(), ParamInfo.size(),
+                                             DS.getTypeQualifiers(),
+                                             hasExceptionSpec, ThrowLoc,
+                                             hasAnyExceptionSpec,
+                                             Exceptions.data(),
+                                             ExceptionRanges.data(),
+                                             Exceptions.size(),
+                                             LParenLoc, RParenLoc, D),
+                EndLoc);
+}
+
+/// ParseFunctionDeclaratorIdentifierList - While parsing a function declarator
+/// we found a K&R-style identifier list instead of a type argument list.  The
+/// current token is known to be the first identifier in the list.
+///
+///       identifier-list: [C99 6.7.5]
+///         identifier
+///         identifier-list ',' identifier
+///
+void Parser::ParseFunctionDeclaratorIdentifierList(SourceLocation LParenLoc,
+                                                   Declarator &D) {
+  // Build up an array of information about the parsed arguments.
+  llvm::SmallVector<DeclaratorChunk::ParamInfo, 16> ParamInfo;
+  llvm::SmallSet<const IdentifierInfo*, 16> ParamsSoFar;
+
+  // If there was no identifier specified for the declarator, either we are in
+  // an abstract-declarator, or we are in a parameter declarator which was found
+  // to be abstract.  In abstract-declarators, identifier lists are not valid:
+  // diagnose this.
+  if (!D.getIdentifier())
+    Diag(Tok, diag::ext_ident_list_in_param);
+
+  // Tok is known to be the first identifier in the list.  Remember this
+  // identifier in ParamInfo.
+  ParamsSoFar.insert(Tok.getIdentifierInfo());
+  ParamInfo.push_back(DeclaratorChunk::ParamInfo(Tok.getIdentifierInfo(),
+                                                 Tok.getLocation(),
+                                                 DeclPtrTy()));
+
+  ConsumeToken();  // eat the first identifier.
+
+  while (Tok.is(tok::comma)) {
+    // Eat the comma.
+    ConsumeToken();
+
+    // If this isn't an identifier, report the error and skip until ')'.
+    if (Tok.isNot(tok::identifier)) {
+      Diag(Tok, diag::err_expected_ident);
+      SkipUntil(tok::r_paren);
+      return;
+    }
+
+    IdentifierInfo *ParmII = Tok.getIdentifierInfo();
+
+    // Reject 'typedef int y; int test(x, y)', but continue parsing.
+    if (Actions.getTypeName(*ParmII, Tok.getLocation(), CurScope))
+      Diag(Tok, diag::err_unexpected_typedef_ident) << ParmII;
+
+    // Verify that the argument identifier has not already been mentioned.
+    if (!ParamsSoFar.insert(ParmII)) {
+      Diag(Tok, diag::err_param_redefinition) << ParmII;
+    } else {
+      // Remember this identifier in ParamInfo.
+      ParamInfo.push_back(DeclaratorChunk::ParamInfo(ParmII,
+                                                     Tok.getLocation(),
+                                                     DeclPtrTy()));
+    }
+
+    // Eat the identifier.
+    ConsumeToken();
+  }
+
+  // If we have the closing ')', eat it and we're done.
+  SourceLocation RLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc);
+
+  // Remember that we parsed a function type, and remember the attributes.  This
+  // function type is always a K&R style function type, which is not varargs and
+  // has no prototype.
+  D.AddTypeInfo(DeclaratorChunk::getFunction(/*proto*/false, /*varargs*/false,
+                                             SourceLocation(),
+                                             &ParamInfo[0], ParamInfo.size(),
+                                             /*TypeQuals*/0,
+                                             /*exception*/false,
+                                             SourceLocation(), false, 0, 0, 0,
+                                             LParenLoc, RLoc, D),
+                RLoc);
+}
+
+/// [C90]   direct-declarator '[' constant-expression[opt] ']'
+/// [C99]   direct-declarator '[' type-qual-list[opt] assignment-expr[opt] ']'
+/// [C99]   direct-declarator '[' 'static' type-qual-list[opt] assign-expr ']'
+/// [C99]   direct-declarator '[' type-qual-list 'static' assignment-expr ']'
+/// [C99]   direct-declarator '[' type-qual-list[opt] '*' ']'
+void Parser::ParseBracketDeclarator(Declarator &D) {
+  SourceLocation StartLoc = ConsumeBracket();
+
+  // C array syntax has many features, but by-far the most common is [] and [4].
+  // This code does a fast path to handle some of the most obvious cases.
+  if (Tok.getKind() == tok::r_square) {
+    SourceLocation EndLoc = MatchRHSPunctuation(tok::r_square, StartLoc);
+    //FIXME: Use these
+    CXX0XAttributeList Attr;
+    if (getLang().CPlusPlus0x && isCXX0XAttributeSpecifier(true)) {
+      Attr = ParseCXX0XAttributes();
+    }
+    
+    // Remember that we parsed the empty array type.
+    OwningExprResult NumElements(Actions);
+    D.AddTypeInfo(DeclaratorChunk::getArray(0, false, false, 0,
+                                            StartLoc, EndLoc),
+                  EndLoc);
+    return;
+  } else if (Tok.getKind() == tok::numeric_constant &&
+             GetLookAheadToken(1).is(tok::r_square)) {
+    // [4] is very common.  Parse the numeric constant expression.
+    OwningExprResult ExprRes(Actions.ActOnNumericConstant(Tok));
+    ConsumeToken();
+
+    SourceLocation EndLoc = MatchRHSPunctuation(tok::r_square, StartLoc);
+    //FIXME: Use these
+    CXX0XAttributeList Attr;
+    if (getLang().CPlusPlus0x && isCXX0XAttributeSpecifier()) {
+      Attr = ParseCXX0XAttributes();
+    }
+
+    // If there was an error parsing the assignment-expression, recover.
+    if (ExprRes.isInvalid())
+      ExprRes.release();  // Deallocate expr, just use [].
+
+    // Remember that we parsed a array type, and remember its features.
+    D.AddTypeInfo(DeclaratorChunk::getArray(0, false, 0, ExprRes.release(),
+                                            StartLoc, EndLoc),
+                  EndLoc);
+    return;
+  }
+
+  // If valid, this location is the position where we read the 'static' keyword.
+  SourceLocation StaticLoc;
+  if (Tok.is(tok::kw_static))
+    StaticLoc = ConsumeToken();
+
+  // If there is a type-qualifier-list, read it now.
+  // Type qualifiers in an array subscript are a C99 feature.
+  DeclSpec DS;
+  ParseTypeQualifierListOpt(DS, false /*no attributes*/);
+
+  // If we haven't already read 'static', check to see if there is one after the
+  // type-qualifier-list.
+  if (!StaticLoc.isValid() && Tok.is(tok::kw_static))
+    StaticLoc = ConsumeToken();
+
+  // Handle "direct-declarator [ type-qual-list[opt] * ]".
+  bool isStar = false;
+  OwningExprResult NumElements(Actions);
+
+  // Handle the case where we have '[*]' as the array size.  However, a leading
+  // star could be the start of an expression, for example 'X[*p + 4]'.  Verify
+  // the the token after the star is a ']'.  Since stars in arrays are
+  // infrequent, use of lookahead is not costly here.
+  if (Tok.is(tok::star) && GetLookAheadToken(1).is(tok::r_square)) {
+    ConsumeToken();  // Eat the '*'.
+
+    if (StaticLoc.isValid()) {
+      Diag(StaticLoc, diag::err_unspecified_vla_size_with_static);
+      StaticLoc = SourceLocation();  // Drop the static.
+    }
+    isStar = true;
+  } else if (Tok.isNot(tok::r_square)) {
+    // Note, in C89, this production uses the constant-expr production instead
+    // of assignment-expr.  The only difference is that assignment-expr allows
+    // things like '=' and '*='.  Sema rejects these in C89 mode because they
+    // are not i-c-e's, so we don't need to distinguish between the two here.
+
+    // Parse the constant-expression or assignment-expression now (depending
+    // on dialect).
+    if (getLang().CPlusPlus)
+      NumElements = ParseConstantExpression();
+    else
+      NumElements = ParseAssignmentExpression();
+  }
+
+  // If there was an error parsing the assignment-expression, recover.
+  if (NumElements.isInvalid()) {
+    D.setInvalidType(true);
+    // If the expression was invalid, skip it.
+    SkipUntil(tok::r_square);
+    return;
+  }
+
+  SourceLocation EndLoc = MatchRHSPunctuation(tok::r_square, StartLoc);
+
+  //FIXME: Use these
+  CXX0XAttributeList Attr;
+  if (getLang().CPlusPlus0x && isCXX0XAttributeSpecifier()) {
+    Attr = ParseCXX0XAttributes();
+  }
+
+  // Remember that we parsed a array type, and remember its features.
+  D.AddTypeInfo(DeclaratorChunk::getArray(DS.getTypeQualifiers(),
+                                          StaticLoc.isValid(), isStar,
+                                          NumElements.release(),
+                                          StartLoc, EndLoc),
+                EndLoc);
+}
+
+/// [GNU]   typeof-specifier:
+///           typeof ( expressions )
+///           typeof ( type-name )
+/// [GNU/C++] typeof unary-expression
+///
+void Parser::ParseTypeofSpecifier(DeclSpec &DS) {
+  assert(Tok.is(tok::kw_typeof) && "Not a typeof specifier");
+  Token OpTok = Tok;
+  SourceLocation StartLoc = ConsumeToken();
+
+  const bool hasParens = Tok.is(tok::l_paren);
+
+  bool isCastExpr;
+  TypeTy *CastTy;
+  SourceRange CastRange;
+  OwningExprResult Operand = ParseExprAfterTypeofSizeofAlignof(OpTok,
+                                                               isCastExpr,
+                                                               CastTy,
+                                                               CastRange);
+  if (hasParens)
+    DS.setTypeofParensRange(CastRange);
+
+  if (CastRange.getEnd().isInvalid())
+    // FIXME: Not accurate, the range gets one token more than it should.
+    DS.SetRangeEnd(Tok.getLocation());
+  else
+    DS.SetRangeEnd(CastRange.getEnd());
+
+  if (isCastExpr) {
+    if (!CastTy) {
+      DS.SetTypeSpecError();
+      return;
+    }
+
+    const char *PrevSpec = 0;
+    unsigned DiagID;
+    // Check for duplicate type specifiers (e.g. "int typeof(int)").
+    if (DS.SetTypeSpecType(DeclSpec::TST_typeofType, StartLoc, PrevSpec,
+                           DiagID, CastTy))
+      Diag(StartLoc, DiagID) << PrevSpec;
+    return;
+  }
+
+  // If we get here, the operand to the typeof was an expresion.
+  if (Operand.isInvalid()) {
+    DS.SetTypeSpecError();
+    return;
+  }
+
+  const char *PrevSpec = 0;
+  unsigned DiagID;
+  // Check for duplicate type specifiers (e.g. "int typeof(int)").
+  if (DS.SetTypeSpecType(DeclSpec::TST_typeofExpr, StartLoc, PrevSpec,
+                         DiagID, Operand.release()))
+    Diag(StartLoc, DiagID) << PrevSpec;
+}
diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp
new file mode 100644
index 0000000..e1c66e2
--- /dev/null
+++ b/lib/Parse/ParseDeclCXX.cpp
@@ -0,0 +1,1975 @@
+//===--- ParseDeclCXX.cpp - C++ Declaration Parsing -----------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+//  This file implements the C++ Declaration portions of the Parser interfaces.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Basic/OperatorKinds.h"
+#include "clang/Parse/Parser.h"
+#include "clang/Parse/ParseDiagnostic.h"
+#include "clang/Parse/DeclSpec.h"
+#include "clang/Parse/Scope.h"
+#include "clang/Parse/Template.h"
+#include "RAIIObjectsForParser.h"
+using namespace clang;
+
+/// ParseNamespace - We know that the current token is a namespace keyword. This
+/// may either be a top level namespace or a block-level namespace alias.
+///
+///       namespace-definition: [C++ 7.3: basic.namespace]
+///         named-namespace-definition
+///         unnamed-namespace-definition
+///
+///       unnamed-namespace-definition:
+///         'namespace' attributes[opt] '{' namespace-body '}'
+///
+///       named-namespace-definition:
+///         original-namespace-definition
+///         extension-namespace-definition
+///
+///       original-namespace-definition:
+///         'namespace' identifier attributes[opt] '{' namespace-body '}'
+///
+///       extension-namespace-definition:
+///         'namespace' original-namespace-name '{' namespace-body '}'
+///
+///       namespace-alias-definition:  [C++ 7.3.2: namespace.alias]
+///         'namespace' identifier '=' qualified-namespace-specifier ';'
+///
+Parser::DeclPtrTy Parser::ParseNamespace(unsigned Context,
+                                         SourceLocation &DeclEnd) {
+  assert(Tok.is(tok::kw_namespace) && "Not a namespace!");
+  SourceLocation NamespaceLoc = ConsumeToken();  // eat the 'namespace'.
+
+  if (Tok.is(tok::code_completion)) {
+    Actions.CodeCompleteNamespaceDecl(CurScope);
+    ConsumeToken();
+  }
+  
+  SourceLocation IdentLoc;
+  IdentifierInfo *Ident = 0;
+
+  Token attrTok;
+
+  if (Tok.is(tok::identifier)) {
+    Ident = Tok.getIdentifierInfo();
+    IdentLoc = ConsumeToken();  // eat the identifier.
+  }
+
+  // Read label attributes, if present.
+  AttributeList *AttrList = 0;
+  if (Tok.is(tok::kw___attribute)) {
+    attrTok = Tok;
+
+    // FIXME: save these somewhere.
+    AttrList = ParseGNUAttributes();
+  }
+
+  if (Tok.is(tok::equal)) {
+    if (AttrList)
+      Diag(attrTok, diag::err_unexpected_namespace_attributes_alias);
+
+    return ParseNamespaceAlias(NamespaceLoc, IdentLoc, Ident, DeclEnd);
+  }
+
+  if (Tok.isNot(tok::l_brace)) {
+    Diag(Tok, Ident ? diag::err_expected_lbrace :
+         diag::err_expected_ident_lbrace);
+    return DeclPtrTy();
+  }
+
+  SourceLocation LBrace = ConsumeBrace();
+
+  // Enter a scope for the namespace.
+  ParseScope NamespaceScope(this, Scope::DeclScope);
+
+  DeclPtrTy NamespcDecl =
+    Actions.ActOnStartNamespaceDef(CurScope, IdentLoc, Ident, LBrace, AttrList);
+
+  PrettyStackTraceActionsDecl CrashInfo(NamespcDecl, NamespaceLoc, Actions,
+                                        PP.getSourceManager(),
+                                        "parsing namespace");
+
+  while (Tok.isNot(tok::r_brace) && Tok.isNot(tok::eof)) {
+    CXX0XAttributeList Attr;
+    if (getLang().CPlusPlus0x && isCXX0XAttributeSpecifier())
+      Attr = ParseCXX0XAttributes();
+    ParseExternalDeclaration(Attr);
+  }
+
+  // Leave the namespace scope.
+  NamespaceScope.Exit();
+
+  SourceLocation RBraceLoc = MatchRHSPunctuation(tok::r_brace, LBrace);
+  Actions.ActOnFinishNamespaceDef(NamespcDecl, RBraceLoc);
+
+  DeclEnd = RBraceLoc;
+  return NamespcDecl;
+}
+
+/// ParseNamespaceAlias - Parse the part after the '=' in a namespace
+/// alias definition.
+///
+Parser::DeclPtrTy Parser::ParseNamespaceAlias(SourceLocation NamespaceLoc,
+                                              SourceLocation AliasLoc,
+                                              IdentifierInfo *Alias,
+                                              SourceLocation &DeclEnd) {
+  assert(Tok.is(tok::equal) && "Not equal token");
+
+  ConsumeToken(); // eat the '='.
+
+  if (Tok.is(tok::code_completion)) {
+    Actions.CodeCompleteNamespaceAliasDecl(CurScope);
+    ConsumeToken();
+  }
+  
+  CXXScopeSpec SS;
+  // Parse (optional) nested-name-specifier.
+  ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/0, false);
+
+  if (SS.isInvalid() || Tok.isNot(tok::identifier)) {
+    Diag(Tok, diag::err_expected_namespace_name);
+    // Skip to end of the definition and eat the ';'.
+    SkipUntil(tok::semi);
+    return DeclPtrTy();
+  }
+
+  // Parse identifier.
+  IdentifierInfo *Ident = Tok.getIdentifierInfo();
+  SourceLocation IdentLoc = ConsumeToken();
+
+  // Eat the ';'.
+  DeclEnd = Tok.getLocation();
+  ExpectAndConsume(tok::semi, diag::err_expected_semi_after_namespace_name,
+                   "", tok::semi);
+
+  return Actions.ActOnNamespaceAliasDef(CurScope, NamespaceLoc, AliasLoc, Alias,
+                                        SS, IdentLoc, Ident);
+}
+
+/// ParseLinkage - We know that the current token is a string_literal
+/// and just before that, that extern was seen.
+///
+///       linkage-specification: [C++ 7.5p2: dcl.link]
+///         'extern' string-literal '{' declaration-seq[opt] '}'
+///         'extern' string-literal declaration
+///
+Parser::DeclPtrTy Parser::ParseLinkage(ParsingDeclSpec &DS,
+                                       unsigned Context) {
+  assert(Tok.is(tok::string_literal) && "Not a string literal!");
+  llvm::SmallVector<char, 8> LangBuffer;
+  // LangBuffer is guaranteed to be big enough.
+  LangBuffer.resize(Tok.getLength());
+  const char *LangBufPtr = &LangBuffer[0];
+  unsigned StrSize = PP.getSpelling(Tok, LangBufPtr);
+
+  SourceLocation Loc = ConsumeStringToken();
+
+  ParseScope LinkageScope(this, Scope::DeclScope);
+  DeclPtrTy LinkageSpec
+    = Actions.ActOnStartLinkageSpecification(CurScope,
+                                             /*FIXME: */SourceLocation(),
+                                             Loc, LangBufPtr, StrSize,
+                                       Tok.is(tok::l_brace)? Tok.getLocation()
+                                                           : SourceLocation());
+
+  CXX0XAttributeList Attr;
+  if (getLang().CPlusPlus0x && isCXX0XAttributeSpecifier()) {
+    Attr = ParseCXX0XAttributes();
+  }
+  
+  if (Tok.isNot(tok::l_brace)) {
+    ParseDeclarationOrFunctionDefinition(DS, Attr.AttrList);
+    return Actions.ActOnFinishLinkageSpecification(CurScope, LinkageSpec,
+                                                   SourceLocation());
+  }
+
+  DS.abort();
+
+  if (Attr.HasAttr)
+    Diag(Attr.Range.getBegin(), diag::err_attributes_not_allowed)
+      << Attr.Range;
+
+  SourceLocation LBrace = ConsumeBrace();
+  while (Tok.isNot(tok::r_brace) && Tok.isNot(tok::eof)) {
+    CXX0XAttributeList Attr;
+    if (getLang().CPlusPlus0x && isCXX0XAttributeSpecifier())
+      Attr = ParseCXX0XAttributes();
+    ParseExternalDeclaration(Attr);
+  }
+
+  SourceLocation RBrace = MatchRHSPunctuation(tok::r_brace, LBrace);
+  return Actions.ActOnFinishLinkageSpecification(CurScope, LinkageSpec, RBrace);
+}
+
+/// ParseUsingDirectiveOrDeclaration - Parse C++ using using-declaration or
+/// using-directive. Assumes that current token is 'using'.
+Parser::DeclPtrTy Parser::ParseUsingDirectiveOrDeclaration(unsigned Context,
+                                                     SourceLocation &DeclEnd,
+                                                     CXX0XAttributeList Attr) {
+  assert(Tok.is(tok::kw_using) && "Not using token");
+
+  // Eat 'using'.
+  SourceLocation UsingLoc = ConsumeToken();
+
+  if (Tok.is(tok::code_completion)) {
+    Actions.CodeCompleteUsing(CurScope);
+    ConsumeToken();
+  }
+  
+  if (Tok.is(tok::kw_namespace))
+    // Next token after 'using' is 'namespace' so it must be using-directive
+    return ParseUsingDirective(Context, UsingLoc, DeclEnd, Attr.AttrList);
+
+  if (Attr.HasAttr)
+    Diag(Attr.Range.getBegin(), diag::err_attributes_not_allowed)
+      << Attr.Range;
+
+  // Otherwise, it must be using-declaration.
+  // Ignore illegal attributes (the caller should already have issued an error.
+  return ParseUsingDeclaration(Context, UsingLoc, DeclEnd);
+}
+
+/// ParseUsingDirective - Parse C++ using-directive, assumes
+/// that current token is 'namespace' and 'using' was already parsed.
+///
+///       using-directive: [C++ 7.3.p4: namespace.udir]
+///        'using' 'namespace' ::[opt] nested-name-specifier[opt]
+///                 namespace-name ;
+/// [GNU] using-directive:
+///        'using' 'namespace' ::[opt] nested-name-specifier[opt]
+///                 namespace-name attributes[opt] ;
+///
+Parser::DeclPtrTy Parser::ParseUsingDirective(unsigned Context,
+                                              SourceLocation UsingLoc,
+                                              SourceLocation &DeclEnd,
+                                              AttributeList *Attr) {
+  assert(Tok.is(tok::kw_namespace) && "Not 'namespace' token");
+
+  // Eat 'namespace'.
+  SourceLocation NamespcLoc = ConsumeToken();
+
+  if (Tok.is(tok::code_completion)) {
+    Actions.CodeCompleteUsingDirective(CurScope);
+    ConsumeToken();
+  }
+  
+  CXXScopeSpec SS;
+  // Parse (optional) nested-name-specifier.
+  ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/0, false);
+
+  IdentifierInfo *NamespcName = 0;
+  SourceLocation IdentLoc = SourceLocation();
+
+  // Parse namespace-name.
+  if (SS.isInvalid() || Tok.isNot(tok::identifier)) {
+    Diag(Tok, diag::err_expected_namespace_name);
+    // If there was invalid namespace name, skip to end of decl, and eat ';'.
+    SkipUntil(tok::semi);
+    // FIXME: Are there cases, when we would like to call ActOnUsingDirective?
+    return DeclPtrTy();
+  }
+
+  // Parse identifier.
+  NamespcName = Tok.getIdentifierInfo();
+  IdentLoc = ConsumeToken();
+
+  // Parse (optional) attributes (most likely GNU strong-using extension).
+  bool GNUAttr = false;
+  if (Tok.is(tok::kw___attribute)) {
+    GNUAttr = true;
+    Attr = addAttributeLists(Attr, ParseGNUAttributes());
+  }
+
+  // Eat ';'.
+  DeclEnd = Tok.getLocation();
+  ExpectAndConsume(tok::semi,
+                   GNUAttr ? diag::err_expected_semi_after_attribute_list :
+                   diag::err_expected_semi_after_namespace_name, "", tok::semi);
+
+  return Actions.ActOnUsingDirective(CurScope, UsingLoc, NamespcLoc, SS,
+                                      IdentLoc, NamespcName, Attr);
+}
+
+/// ParseUsingDeclaration - Parse C++ using-declaration. Assumes that
+/// 'using' was already seen.
+///
+///     using-declaration: [C++ 7.3.p3: namespace.udecl]
+///       'using' 'typename'[opt] ::[opt] nested-name-specifier
+///               unqualified-id
+///       'using' :: unqualified-id
+///
+Parser::DeclPtrTy Parser::ParseUsingDeclaration(unsigned Context,
+                                                SourceLocation UsingLoc,
+                                                SourceLocation &DeclEnd,
+                                                AccessSpecifier AS) {
+  CXXScopeSpec SS;
+  SourceLocation TypenameLoc;
+  bool IsTypeName;
+
+  // Ignore optional 'typename'.
+  // FIXME: This is wrong; we should parse this as a typename-specifier.
+  if (Tok.is(tok::kw_typename)) {
+    TypenameLoc = Tok.getLocation();
+    ConsumeToken();
+    IsTypeName = true;
+  }
+  else
+    IsTypeName = false;
+
+  // Parse nested-name-specifier.
+  ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/0, false);
+
+  AttributeList *AttrList = 0;
+
+  // Check nested-name specifier.
+  if (SS.isInvalid()) {
+    SkipUntil(tok::semi);
+    return DeclPtrTy();
+  }
+
+  // Parse the unqualified-id. We allow parsing of both constructor and 
+  // destructor names and allow the action module to diagnose any semantic
+  // errors.
+  UnqualifiedId Name;
+  if (ParseUnqualifiedId(SS, 
+                         /*EnteringContext=*/false,
+                         /*AllowDestructorName=*/true,
+                         /*AllowConstructorName=*/true, 
+                         /*ObjectType=*/0, 
+                         Name)) {
+    SkipUntil(tok::semi);
+    return DeclPtrTy();
+  }
+  
+  // Parse (optional) attributes (most likely GNU strong-using extension).
+  if (Tok.is(tok::kw___attribute))
+    AttrList = ParseGNUAttributes();
+
+  // Eat ';'.
+  DeclEnd = Tok.getLocation();
+  ExpectAndConsume(tok::semi, diag::err_expected_semi_after,
+                   AttrList ? "attributes list" : "using declaration", 
+                   tok::semi);
+
+  return Actions.ActOnUsingDeclaration(CurScope, AS, true, UsingLoc, SS, Name,
+                                       AttrList, IsTypeName, TypenameLoc);
+}
+
+/// ParseStaticAssertDeclaration - Parse C++0x static_assert-declaratoion.
+///
+///      static_assert-declaration:
+///        static_assert ( constant-expression  ,  string-literal  ) ;
+///
+Parser::DeclPtrTy Parser::ParseStaticAssertDeclaration(SourceLocation &DeclEnd){
+  assert(Tok.is(tok::kw_static_assert) && "Not a static_assert declaration");
+  SourceLocation StaticAssertLoc = ConsumeToken();
+
+  if (Tok.isNot(tok::l_paren)) {
+    Diag(Tok, diag::err_expected_lparen);
+    return DeclPtrTy();
+  }
+
+  SourceLocation LParenLoc = ConsumeParen();
+
+  OwningExprResult AssertExpr(ParseConstantExpression());
+  if (AssertExpr.isInvalid()) {
+    SkipUntil(tok::semi);
+    return DeclPtrTy();
+  }
+
+  if (ExpectAndConsume(tok::comma, diag::err_expected_comma, "", tok::semi))
+    return DeclPtrTy();
+
+  if (Tok.isNot(tok::string_literal)) {
+    Diag(Tok, diag::err_expected_string_literal);
+    SkipUntil(tok::semi);
+    return DeclPtrTy();
+  }
+
+  OwningExprResult AssertMessage(ParseStringLiteralExpression());
+  if (AssertMessage.isInvalid())
+    return DeclPtrTy();
+
+  MatchRHSPunctuation(tok::r_paren, LParenLoc);
+
+  DeclEnd = Tok.getLocation();
+  ExpectAndConsume(tok::semi, diag::err_expected_semi_after_static_assert);
+
+  return Actions.ActOnStaticAssertDeclaration(StaticAssertLoc, move(AssertExpr),
+                                              move(AssertMessage));
+}
+
+/// ParseDecltypeSpecifier - Parse a C++0x decltype specifier.
+///
+/// 'decltype' ( expression )
+///
+void Parser::ParseDecltypeSpecifier(DeclSpec &DS) {
+  assert(Tok.is(tok::kw_decltype) && "Not a decltype specifier");
+
+  SourceLocation StartLoc = ConsumeToken();
+  SourceLocation LParenLoc = Tok.getLocation();
+
+  if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen_after,
+                       "decltype")) {
+    SkipUntil(tok::r_paren);
+    return;
+  }
+
+  // Parse the expression
+
+  // C++0x [dcl.type.simple]p4:
+  //   The operand of the decltype specifier is an unevaluated operand.
+  EnterExpressionEvaluationContext Unevaluated(Actions,
+                                               Action::Unevaluated);
+  OwningExprResult Result = ParseExpression();
+  if (Result.isInvalid()) {
+    SkipUntil(tok::r_paren);
+    return;
+  }
+
+  // Match the ')'
+  SourceLocation RParenLoc;
+  if (Tok.is(tok::r_paren))
+    RParenLoc = ConsumeParen();
+  else
+    MatchRHSPunctuation(tok::r_paren, LParenLoc);
+
+  if (RParenLoc.isInvalid())
+    return;
+
+  const char *PrevSpec = 0;
+  unsigned DiagID;
+  // Check for duplicate type specifiers (e.g. "int decltype(a)").
+  if (DS.SetTypeSpecType(DeclSpec::TST_decltype, StartLoc, PrevSpec,
+                         DiagID, Result.release()))
+    Diag(StartLoc, DiagID) << PrevSpec;
+}
+
+/// ParseClassName - Parse a C++ class-name, which names a class. Note
+/// that we only check that the result names a type; semantic analysis
+/// will need to verify that the type names a class. The result is
+/// either a type or NULL, depending on whether a type name was
+/// found.
+///
+///       class-name: [C++ 9.1]
+///         identifier
+///         simple-template-id
+///
+Parser::TypeResult Parser::ParseClassName(SourceLocation &EndLocation,
+                                          const CXXScopeSpec *SS,
+                                          bool DestrExpected) {
+  // Check whether we have a template-id that names a type.
+  if (Tok.is(tok::annot_template_id)) {
+    TemplateIdAnnotation *TemplateId
+      = static_cast<TemplateIdAnnotation *>(Tok.getAnnotationValue());
+    if (TemplateId->Kind == TNK_Type_template ||
+        TemplateId->Kind == TNK_Dependent_template_name) {
+      AnnotateTemplateIdTokenAsType(SS);
+
+      assert(Tok.is(tok::annot_typename) && "template-id -> type failed");
+      TypeTy *Type = Tok.getAnnotationValue();
+      EndLocation = Tok.getAnnotationEndLoc();
+      ConsumeToken();
+
+      if (Type)
+        return Type;
+      return true;
+    }
+
+    // Fall through to produce an error below.
+  }
+
+  if (Tok.isNot(tok::identifier)) {
+    Diag(Tok, diag::err_expected_class_name);
+    return true;
+  }
+
+  IdentifierInfo *Id = Tok.getIdentifierInfo();
+  SourceLocation IdLoc = ConsumeToken();
+
+  if (Tok.is(tok::less)) {
+    // It looks the user intended to write a template-id here, but the
+    // template-name was wrong. Try to fix that.
+    TemplateNameKind TNK = TNK_Type_template;
+    TemplateTy Template;
+    if (!Actions.DiagnoseUnknownTemplateName(*Id, IdLoc, CurScope,
+                                             SS, Template, TNK)) {
+      Diag(IdLoc, diag::err_unknown_template_name)
+        << Id;
+    }
+    
+    if (!Template)
+      return true;
+
+    // Form the template name 
+    UnqualifiedId TemplateName;
+    TemplateName.setIdentifier(Id, IdLoc);
+    
+    // Parse the full template-id, then turn it into a type.
+    if (AnnotateTemplateIdToken(Template, TNK, SS, TemplateName,
+                                SourceLocation(), true))
+      return true;
+    if (TNK == TNK_Dependent_template_name)
+      AnnotateTemplateIdTokenAsType(SS);
+    
+    // If we didn't end up with a typename token, there's nothing more we
+    // can do.
+    if (Tok.isNot(tok::annot_typename))
+      return true;
+    
+    // Retrieve the type from the annotation token, consume that token, and
+    // return.
+    EndLocation = Tok.getAnnotationEndLoc();
+    TypeTy *Type = Tok.getAnnotationValue();
+    ConsumeToken();
+    return Type;
+  }
+
+  // We have an identifier; check whether it is actually a type.
+  TypeTy *Type = Actions.getTypeName(*Id, IdLoc, CurScope, SS, true);
+  if (!Type) {    
+    Diag(IdLoc, DestrExpected ? diag::err_destructor_class_name
+                            : diag::err_expected_class_name);
+    return true;
+  }
+
+  // Consume the identifier.
+  EndLocation = IdLoc;
+  return Type;
+}
+
+/// ParseClassSpecifier - Parse a C++ class-specifier [C++ class] or
+/// elaborated-type-specifier [C++ dcl.type.elab]; we can't tell which
+/// until we reach the start of a definition or see a token that
+/// cannot start a definition. If SuppressDeclarations is true, we do know.
+///
+///       class-specifier: [C++ class]
+///         class-head '{' member-specification[opt] '}'
+///         class-head '{' member-specification[opt] '}' attributes[opt]
+///       class-head:
+///         class-key identifier[opt] base-clause[opt]
+///         class-key nested-name-specifier identifier base-clause[opt]
+///         class-key nested-name-specifier[opt] simple-template-id
+///                          base-clause[opt]
+/// [GNU]   class-key attributes[opt] identifier[opt] base-clause[opt]
+/// [GNU]   class-key attributes[opt] nested-name-specifier
+///                          identifier base-clause[opt]
+/// [GNU]   class-key attributes[opt] nested-name-specifier[opt]
+///                          simple-template-id base-clause[opt]
+///       class-key:
+///         'class'
+///         'struct'
+///         'union'
+///
+///       elaborated-type-specifier: [C++ dcl.type.elab]
+///         class-key ::[opt] nested-name-specifier[opt] identifier
+///         class-key ::[opt] nested-name-specifier[opt] 'template'[opt]
+///                          simple-template-id
+///
+///  Note that the C++ class-specifier and elaborated-type-specifier,
+///  together, subsume the C99 struct-or-union-specifier:
+///
+///       struct-or-union-specifier: [C99 6.7.2.1]
+///         struct-or-union identifier[opt] '{' struct-contents '}'
+///         struct-or-union identifier
+/// [GNU]   struct-or-union attributes[opt] identifier[opt] '{' struct-contents
+///                                                         '}' attributes[opt]
+/// [GNU]   struct-or-union attributes[opt] identifier
+///       struct-or-union:
+///         'struct'
+///         'union'
+void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
+                                 SourceLocation StartLoc, DeclSpec &DS,
+                                 const ParsedTemplateInfo &TemplateInfo,
+                                 AccessSpecifier AS, bool SuppressDeclarations){
+  DeclSpec::TST TagType;
+  if (TagTokKind == tok::kw_struct)
+    TagType = DeclSpec::TST_struct;
+  else if (TagTokKind == tok::kw_class)
+    TagType = DeclSpec::TST_class;
+  else {
+    assert(TagTokKind == tok::kw_union && "Not a class specifier");
+    TagType = DeclSpec::TST_union;
+  }
+
+  if (Tok.is(tok::code_completion)) {
+    // Code completion for a struct, class, or union name.
+    Actions.CodeCompleteTag(CurScope, TagType);
+    ConsumeToken();
+  }
+  
+  AttributeList *AttrList = 0;
+  // If attributes exist after tag, parse them.
+  if (Tok.is(tok::kw___attribute))
+    AttrList = ParseGNUAttributes();
+
+  // If declspecs exist after tag, parse them.
+  if (Tok.is(tok::kw___declspec))
+    AttrList = ParseMicrosoftDeclSpec(AttrList);
+  
+  // If C++0x attributes exist here, parse them.
+  // FIXME: Are we consistent with the ordering of parsing of different
+  // styles of attributes?
+  if (isCXX0XAttributeSpecifier())
+    AttrList = addAttributeLists(AttrList, ParseCXX0XAttributes().AttrList);
+
+  if (TagType == DeclSpec::TST_struct && Tok.is(tok::kw___is_pod)) {
+    // GNU libstdc++ 4.2 uses __is_pod as the name of a struct template, but
+    // __is_pod is a keyword in GCC >= 4.3. Therefore, when we see the
+    // token sequence "struct __is_pod", make __is_pod into a normal
+    // identifier rather than a keyword, to allow libstdc++ 4.2 to work
+    // properly.
+    Tok.getIdentifierInfo()->setTokenID(tok::identifier);
+    Tok.setKind(tok::identifier);
+  }
+
+  if (TagType == DeclSpec::TST_struct && Tok.is(tok::kw___is_empty)) {
+    // GNU libstdc++ 4.2 uses __is_empty as the name of a struct template, but
+    // __is_empty is a keyword in GCC >= 4.3. Therefore, when we see the
+    // token sequence "struct __is_empty", make __is_empty into a normal
+    // identifier rather than a keyword, to allow libstdc++ 4.2 to work
+    // properly.
+    Tok.getIdentifierInfo()->setTokenID(tok::identifier);
+    Tok.setKind(tok::identifier);
+  }
+
+  // Parse the (optional) nested-name-specifier.
+  CXXScopeSpec &SS = DS.getTypeSpecScope();
+  if (getLang().CPlusPlus) {
+    // "FOO : BAR" is not a potential typo for "FOO::BAR".
+    ColonProtectionRAIIObject X(*this);
+    
+    if (ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/0, true))
+      if (Tok.isNot(tok::identifier) && Tok.isNot(tok::annot_template_id))
+        Diag(Tok, diag::err_expected_ident);
+  }
+
+  TemplateParameterLists *TemplateParams = TemplateInfo.TemplateParams;
+
+  // Parse the (optional) class name or simple-template-id.
+  IdentifierInfo *Name = 0;
+  SourceLocation NameLoc;
+  TemplateIdAnnotation *TemplateId = 0;
+  if (Tok.is(tok::identifier)) {
+    Name = Tok.getIdentifierInfo();
+    NameLoc = ConsumeToken();
+    
+    if (Tok.is(tok::less)) {
+      // The name was supposed to refer to a template, but didn't. 
+      // Eat the template argument list and try to continue parsing this as
+      // a class (or template thereof).
+      TemplateArgList TemplateArgs;
+      SourceLocation LAngleLoc, RAngleLoc;
+      if (ParseTemplateIdAfterTemplateName(TemplateTy(), NameLoc, &SS, 
+                                           true, LAngleLoc,
+                                           TemplateArgs, RAngleLoc)) {
+        // We couldn't parse the template argument list at all, so don't
+        // try to give any location information for the list.
+        LAngleLoc = RAngleLoc = SourceLocation();
+      }
+      
+      Diag(NameLoc, diag::err_explicit_spec_non_template)
+        << (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation)
+        << (TagType == DeclSpec::TST_class? 0
+            : TagType == DeclSpec::TST_struct? 1
+            : 2)
+        << Name
+        << SourceRange(LAngleLoc, RAngleLoc);
+      
+      // Strip off the last template parameter list if it was empty, since 
+      // we've removed its template argument list.
+      if (TemplateParams && TemplateInfo.LastParameterListWasEmpty) {
+        if (TemplateParams && TemplateParams->size() > 1) {
+          TemplateParams->pop_back();
+        } else {
+          TemplateParams = 0;
+          const_cast<ParsedTemplateInfo&>(TemplateInfo).Kind 
+            = ParsedTemplateInfo::NonTemplate;
+        }
+      } else if (TemplateInfo.Kind
+                                == ParsedTemplateInfo::ExplicitInstantiation) {
+        // Pretend this is just a forward declaration.
+        TemplateParams = 0;
+        const_cast<ParsedTemplateInfo&>(TemplateInfo).Kind 
+          = ParsedTemplateInfo::NonTemplate;
+        const_cast<ParsedTemplateInfo&>(TemplateInfo).TemplateLoc 
+          = SourceLocation();
+        const_cast<ParsedTemplateInfo&>(TemplateInfo).ExternLoc
+          = SourceLocation();
+      }
+        
+      
+    }
+  } else if (Tok.is(tok::annot_template_id)) {
+    TemplateId = static_cast<TemplateIdAnnotation *>(Tok.getAnnotationValue());
+    NameLoc = ConsumeToken();
+
+    if (TemplateId->Kind != TNK_Type_template) {
+      // The template-name in the simple-template-id refers to
+      // something other than a class template. Give an appropriate
+      // error message and skip to the ';'.
+      SourceRange Range(NameLoc);
+      if (SS.isNotEmpty())
+        Range.setBegin(SS.getBeginLoc());
+
+      Diag(TemplateId->LAngleLoc, diag::err_template_spec_syntax_non_template)
+        << Name << static_cast<int>(TemplateId->Kind) << Range;
+
+      DS.SetTypeSpecError();
+      SkipUntil(tok::semi, false, true);
+      TemplateId->Destroy();
+      return;
+    }
+  }
+
+  // There are four options here.  If we have 'struct foo;', then this
+  // is either a forward declaration or a friend declaration, which
+  // have to be treated differently.  If we have 'struct foo {...' or
+  // 'struct foo :...' then this is a definition. Otherwise we have
+  // something like 'struct foo xyz', a reference.
+  // However, in some contexts, things look like declarations but are just
+  // references, e.g.
+  // new struct s;
+  // or
+  // &T::operator struct s;
+  // For these, SuppressDeclarations is true.
+  Action::TagUseKind TUK;
+  if (SuppressDeclarations)
+    TUK = Action::TUK_Reference;
+  else if (Tok.is(tok::l_brace) || (getLang().CPlusPlus && Tok.is(tok::colon))){
+    if (DS.isFriendSpecified()) {
+      // C++ [class.friend]p2:
+      //   A class shall not be defined in a friend declaration.
+      Diag(Tok.getLocation(), diag::err_friend_decl_defines_class)
+        << SourceRange(DS.getFriendSpecLoc());
+
+      // Skip everything up to the semicolon, so that this looks like a proper
+      // friend class (or template thereof) declaration.
+      SkipUntil(tok::semi, true, true);
+      TUK = Action::TUK_Friend;
+    } else {
+      // Okay, this is a class definition.
+      TUK = Action::TUK_Definition;
+    }
+  } else if (Tok.is(tok::semi))
+    TUK = DS.isFriendSpecified() ? Action::TUK_Friend : Action::TUK_Declaration;
+  else
+    TUK = Action::TUK_Reference;
+
+  if (!Name && !TemplateId && TUK != Action::TUK_Definition) {
+    // We have a declaration or reference to an anonymous class.
+    Diag(StartLoc, diag::err_anon_type_definition)
+      << DeclSpec::getSpecifierName(TagType);
+
+    SkipUntil(tok::comma, true);
+
+    if (TemplateId)
+      TemplateId->Destroy();
+    return;
+  }
+
+  // Create the tag portion of the class or class template.
+  Action::DeclResult TagOrTempResult = true; // invalid
+  Action::TypeResult TypeResult = true; // invalid
+
+  // FIXME: When TUK == TUK_Reference and we have a template-id, we need
+  // to turn that template-id into a type.
+
+  bool Owned = false;
+  if (TemplateId) {
+    // Explicit specialization, class template partial specialization,
+    // or explicit instantiation.
+    ASTTemplateArgsPtr TemplateArgsPtr(Actions,
+                                       TemplateId->getTemplateArgs(),
+                                       TemplateId->NumArgs);
+    if (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation &&
+        TUK == Action::TUK_Declaration) {
+      // This is an explicit instantiation of a class template.
+      TagOrTempResult
+        = Actions.ActOnExplicitInstantiation(CurScope,
+                                             TemplateInfo.ExternLoc,
+                                             TemplateInfo.TemplateLoc,
+                                             TagType,
+                                             StartLoc,
+                                             SS,
+                                     TemplateTy::make(TemplateId->Template),
+                                             TemplateId->TemplateNameLoc,
+                                             TemplateId->LAngleLoc,
+                                             TemplateArgsPtr,
+                                             TemplateId->RAngleLoc,
+                                             AttrList);
+    } else if (TUK == Action::TUK_Reference) {
+      TypeResult
+        = Actions.ActOnTemplateIdType(TemplateTy::make(TemplateId->Template),
+                                      TemplateId->TemplateNameLoc,
+                                      TemplateId->LAngleLoc,
+                                      TemplateArgsPtr,
+                                      TemplateId->RAngleLoc);
+
+      TypeResult = Actions.ActOnTagTemplateIdType(TypeResult, TUK,
+                                                  TagType, StartLoc);
+    } else {
+      // This is an explicit specialization or a class template
+      // partial specialization.
+      TemplateParameterLists FakedParamLists;
+
+      if (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation) {
+        // This looks like an explicit instantiation, because we have
+        // something like
+        //
+        //   template class Foo<X>
+        //
+        // but it actually has a definition. Most likely, this was
+        // meant to be an explicit specialization, but the user forgot
+        // the '<>' after 'template'.
+        assert(TUK == Action::TUK_Definition && "Expected a definition here");
+
+        SourceLocation LAngleLoc
+          = PP.getLocForEndOfToken(TemplateInfo.TemplateLoc);
+        Diag(TemplateId->TemplateNameLoc,
+             diag::err_explicit_instantiation_with_definition)
+          << SourceRange(TemplateInfo.TemplateLoc)
+          << CodeModificationHint::CreateInsertion(LAngleLoc, "<>");
+
+        // Create a fake template parameter list that contains only
+        // "template<>", so that we treat this construct as a class
+        // template specialization.
+        FakedParamLists.push_back(
+          Actions.ActOnTemplateParameterList(0, SourceLocation(),
+                                             TemplateInfo.TemplateLoc,
+                                             LAngleLoc,
+                                             0, 0,
+                                             LAngleLoc));
+        TemplateParams = &FakedParamLists;
+      }
+
+      // Build the class template specialization.
+      TagOrTempResult
+        = Actions.ActOnClassTemplateSpecialization(CurScope, TagType, TUK,
+                       StartLoc, SS,
+                       TemplateTy::make(TemplateId->Template),
+                       TemplateId->TemplateNameLoc,
+                       TemplateId->LAngleLoc,
+                       TemplateArgsPtr,
+                       TemplateId->RAngleLoc,
+                       AttrList,
+                       Action::MultiTemplateParamsArg(Actions,
+                                    TemplateParams? &(*TemplateParams)[0] : 0,
+                                 TemplateParams? TemplateParams->size() : 0));
+    }
+    TemplateId->Destroy();
+  } else if (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation &&
+             TUK == Action::TUK_Declaration) {
+    // Explicit instantiation of a member of a class template
+    // specialization, e.g.,
+    //
+    //   template struct Outer<int>::Inner;
+    //
+    TagOrTempResult
+      = Actions.ActOnExplicitInstantiation(CurScope,
+                                           TemplateInfo.ExternLoc,
+                                           TemplateInfo.TemplateLoc,
+                                           TagType, StartLoc, SS, Name,
+                                           NameLoc, AttrList);
+  } else {
+    if (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation &&
+        TUK == Action::TUK_Definition) {
+      // FIXME: Diagnose this particular error.
+    }
+
+    bool IsDependent = false;
+
+    // Declaration or definition of a class type
+    TagOrTempResult = Actions.ActOnTag(CurScope, TagType, TUK, StartLoc, SS,
+                                       Name, NameLoc, AttrList, AS,
+                                  Action::MultiTemplateParamsArg(Actions,
+                                    TemplateParams? &(*TemplateParams)[0] : 0,
+                                    TemplateParams? TemplateParams->size() : 0),
+                                       Owned, IsDependent);
+
+    // If ActOnTag said the type was dependent, try again with the
+    // less common call.
+    if (IsDependent)
+      TypeResult = Actions.ActOnDependentTag(CurScope, TagType, TUK,
+                                             SS, Name, StartLoc, NameLoc);      
+  }
+
+  // If there is a body, parse it and inform the actions module.
+  if (TUK == Action::TUK_Definition) {
+    assert(Tok.is(tok::l_brace) ||
+           (getLang().CPlusPlus && Tok.is(tok::colon)));
+    if (getLang().CPlusPlus)
+      ParseCXXMemberSpecification(StartLoc, TagType, TagOrTempResult.get());
+    else
+      ParseStructUnionBody(StartLoc, TagType, TagOrTempResult.get());
+  }
+
+  void *Result;
+  if (!TypeResult.isInvalid()) {
+    TagType = DeclSpec::TST_typename;
+    Result = TypeResult.get();
+    Owned = false;
+  } else if (!TagOrTempResult.isInvalid()) {
+    Result = TagOrTempResult.get().getAs<void>();
+  } else {
+    DS.SetTypeSpecError();
+    return;
+  }
+
+  const char *PrevSpec = 0;
+  unsigned DiagID;
+
+  // FIXME: The DeclSpec should keep the locations of both the keyword and the
+  // name (if there is one).
+  SourceLocation TSTLoc = NameLoc.isValid()? NameLoc : StartLoc;
+  
+  if (DS.SetTypeSpecType(TagType, TSTLoc, PrevSpec, DiagID,
+                         Result, Owned))
+    Diag(StartLoc, DiagID) << PrevSpec;
+  
+  // At this point, we've successfully parsed a class-specifier in 'definition'
+  // form (e.g. "struct foo { int x; }".  While we could just return here, we're
+  // going to look at what comes after it to improve error recovery.  If an
+  // impossible token occurs next, we assume that the programmer forgot a ; at
+  // the end of the declaration and recover that way.
+  //
+  // This switch enumerates the valid "follow" set for definition.
+  if (TUK == Action::TUK_Definition) {
+    switch (Tok.getKind()) {
+    case tok::semi:               // struct foo {...} ;
+    case tok::star:               // struct foo {...} *         P;
+    case tok::amp:                // struct foo {...} &         R = ...
+    case tok::identifier:         // struct foo {...} V         ;
+    case tok::r_paren:            //(struct foo {...} )         {4}
+    case tok::annot_cxxscope:     // struct foo {...} a::       b;
+    case tok::annot_typename:     // struct foo {...} a         ::b;
+    case tok::annot_template_id:  // struct foo {...} a<int>    ::b;
+    case tok::l_paren:            // struct foo {...} (         x);
+    case tok::comma:              // __builtin_offsetof(struct foo{...} ,
+    // Storage-class specifiers
+    case tok::kw_static:          // struct foo {...} static    x;
+    case tok::kw_extern:          // struct foo {...} extern    x;
+    case tok::kw_typedef:         // struct foo {...} typedef   x;
+    case tok::kw_register:        // struct foo {...} register  x;
+    case tok::kw_auto:            // struct foo {...} auto      x;
+    // Type qualifiers
+    case tok::kw_const:           // struct foo {...} const     x;
+    case tok::kw_volatile:        // struct foo {...} volatile  x;
+    case tok::kw_restrict:        // struct foo {...} restrict  x;
+    case tok::kw_inline:          // struct foo {...} inline    foo() {};
+      break;
+        
+    case tok::r_brace:  // struct bar { struct foo {...} } 
+      // Missing ';' at end of struct is accepted as an extension in C mode.
+      if (!getLang().CPlusPlus) break;
+      // FALL THROUGH.
+    default:
+      ExpectAndConsume(tok::semi, diag::err_expected_semi_after_tagdecl,
+                       TagType == DeclSpec::TST_class ? "class"
+                       : TagType == DeclSpec::TST_struct? "struct" : "union");
+      // Push this token back into the preprocessor and change our current token
+      // to ';' so that the rest of the code recovers as though there were an
+      // ';' after the definition.
+      PP.EnterToken(Tok);
+      Tok.setKind(tok::semi);  
+      break;
+    }
+  }
+}
+
+/// ParseBaseClause - Parse the base-clause of a C++ class [C++ class.derived].
+///
+///       base-clause : [C++ class.derived]
+///         ':' base-specifier-list
+///       base-specifier-list:
+///         base-specifier '...'[opt]
+///         base-specifier-list ',' base-specifier '...'[opt]
+void Parser::ParseBaseClause(DeclPtrTy ClassDecl) {
+  assert(Tok.is(tok::colon) && "Not a base clause");
+  ConsumeToken();
+
+  // Build up an array of parsed base specifiers.
+  llvm::SmallVector<BaseTy *, 8> BaseInfo;
+
+  while (true) {
+    // Parse a base-specifier.
+    BaseResult Result = ParseBaseSpecifier(ClassDecl);
+    if (Result.isInvalid()) {
+      // Skip the rest of this base specifier, up until the comma or
+      // opening brace.
+      SkipUntil(tok::comma, tok::l_brace, true, true);
+    } else {
+      // Add this to our array of base specifiers.
+      BaseInfo.push_back(Result.get());
+    }
+
+    // If the next token is a comma, consume it and keep reading
+    // base-specifiers.
+    if (Tok.isNot(tok::comma)) break;
+
+    // Consume the comma.
+    ConsumeToken();
+  }
+
+  // Attach the base specifiers
+  Actions.ActOnBaseSpecifiers(ClassDecl, BaseInfo.data(), BaseInfo.size());
+}
+
+/// ParseBaseSpecifier - Parse a C++ base-specifier. A base-specifier is
+/// one entry in the base class list of a class specifier, for example:
+///    class foo : public bar, virtual private baz {
+/// 'public bar' and 'virtual private baz' are each base-specifiers.
+///
+///       base-specifier: [C++ class.derived]
+///         ::[opt] nested-name-specifier[opt] class-name
+///         'virtual' access-specifier[opt] ::[opt] nested-name-specifier[opt]
+///                        class-name
+///         access-specifier 'virtual'[opt] ::[opt] nested-name-specifier[opt]
+///                        class-name
+Parser::BaseResult Parser::ParseBaseSpecifier(DeclPtrTy ClassDecl) {
+  bool IsVirtual = false;
+  SourceLocation StartLoc = Tok.getLocation();
+
+  // Parse the 'virtual' keyword.
+  if (Tok.is(tok::kw_virtual))  {
+    ConsumeToken();
+    IsVirtual = true;
+  }
+
+  // Parse an (optional) access specifier.
+  AccessSpecifier Access = getAccessSpecifierIfPresent();
+  if (Access != AS_none)
+    ConsumeToken();
+
+  // Parse the 'virtual' keyword (again!), in case it came after the
+  // access specifier.
+  if (Tok.is(tok::kw_virtual))  {
+    SourceLocation VirtualLoc = ConsumeToken();
+    if (IsVirtual) {
+      // Complain about duplicate 'virtual'
+      Diag(VirtualLoc, diag::err_dup_virtual)
+        << CodeModificationHint::CreateRemoval(VirtualLoc);
+    }
+
+    IsVirtual = true;
+  }
+
+  // Parse optional '::' and optional nested-name-specifier.
+  CXXScopeSpec SS;
+  ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/0, true);
+
+  // The location of the base class itself.
+  SourceLocation BaseLoc = Tok.getLocation();
+
+  // Parse the class-name.
+  SourceLocation EndLocation;
+  TypeResult BaseType = ParseClassName(EndLocation, &SS);
+  if (BaseType.isInvalid())
+    return true;
+
+  // Find the complete source range for the base-specifier.
+  SourceRange Range(StartLoc, EndLocation);
+
+  // Notify semantic analysis that we have parsed a complete
+  // base-specifier.
+  return Actions.ActOnBaseSpecifier(ClassDecl, Range, IsVirtual, Access,
+                                    BaseType.get(), BaseLoc);
+}
+
+/// getAccessSpecifierIfPresent - Determine whether the next token is
+/// a C++ access-specifier.
+///
+///       access-specifier: [C++ class.derived]
+///         'private'
+///         'protected'
+///         'public'
+AccessSpecifier Parser::getAccessSpecifierIfPresent() const {
+  switch (Tok.getKind()) {
+  default: return AS_none;
+  case tok::kw_private: return AS_private;
+  case tok::kw_protected: return AS_protected;
+  case tok::kw_public: return AS_public;
+  }
+}
+
+void Parser::HandleMemberFunctionDefaultArgs(Declarator& DeclaratorInfo,
+                                             DeclPtrTy ThisDecl) {
+  // We just declared a member function. If this member function
+  // has any default arguments, we'll need to parse them later.
+  LateParsedMethodDeclaration *LateMethod = 0;
+  DeclaratorChunk::FunctionTypeInfo &FTI
+    = DeclaratorInfo.getTypeObject(0).Fun;
+  for (unsigned ParamIdx = 0; ParamIdx < FTI.NumArgs; ++ParamIdx) {
+    if (LateMethod || FTI.ArgInfo[ParamIdx].DefaultArgTokens) {
+      if (!LateMethod) {
+        // Push this method onto the stack of late-parsed method
+        // declarations.
+        getCurrentClass().MethodDecls.push_back(
+                                LateParsedMethodDeclaration(ThisDecl));
+        LateMethod = &getCurrentClass().MethodDecls.back();
+        LateMethod->TemplateScope = CurScope->isTemplateParamScope();
+
+        // Add all of the parameters prior to this one (they don't
+        // have default arguments).
+        LateMethod->DefaultArgs.reserve(FTI.NumArgs);
+        for (unsigned I = 0; I < ParamIdx; ++I)
+          LateMethod->DefaultArgs.push_back(
+                    LateParsedDefaultArgument(FTI.ArgInfo[ParamIdx].Param));
+      }
+
+      // Add this parameter to the list of parameters (it or may
+      // not have a default argument).
+      LateMethod->DefaultArgs.push_back(
+        LateParsedDefaultArgument(FTI.ArgInfo[ParamIdx].Param,
+                                  FTI.ArgInfo[ParamIdx].DefaultArgTokens));
+    }
+  }
+}
+
+/// ParseCXXClassMemberDeclaration - Parse a C++ class member declaration.
+///
+///       member-declaration:
+///         decl-specifier-seq[opt] member-declarator-list[opt] ';'
+///         function-definition ';'[opt]
+///         ::[opt] nested-name-specifier template[opt] unqualified-id ';'[TODO]
+///         using-declaration                                            [TODO]
+/// [C++0x] static_assert-declaration
+///         template-declaration
+/// [GNU]   '__extension__' member-declaration
+///
+///       member-declarator-list:
+///         member-declarator
+///         member-declarator-list ',' member-declarator
+///
+///       member-declarator:
+///         declarator pure-specifier[opt]
+///         declarator constant-initializer[opt]
+///         identifier[opt] ':' constant-expression
+///
+///       pure-specifier:
+///         '= 0'
+///
+///       constant-initializer:
+///         '=' constant-expression
+///
+void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
+                                       const ParsedTemplateInfo &TemplateInfo) {
+  // Access declarations.
+  if (!TemplateInfo.Kind &&
+      (Tok.is(tok::identifier) || Tok.is(tok::coloncolon)) &&
+      TryAnnotateCXXScopeToken() &&
+      Tok.is(tok::annot_cxxscope)) {
+    bool isAccessDecl = false;
+    if (NextToken().is(tok::identifier))
+      isAccessDecl = GetLookAheadToken(2).is(tok::semi);
+    else
+      isAccessDecl = NextToken().is(tok::kw_operator);
+
+    if (isAccessDecl) {
+      // Collect the scope specifier token we annotated earlier.
+      CXXScopeSpec SS;
+      ParseOptionalCXXScopeSpecifier(SS, /*ObjectType*/ 0, false);
+
+      // Try to parse an unqualified-id.
+      UnqualifiedId Name;
+      if (ParseUnqualifiedId(SS, false, true, true, /*ObjectType*/ 0, Name)) {
+        SkipUntil(tok::semi);
+        return;
+      }
+
+      // TODO: recover from mistakenly-qualified operator declarations.
+      if (ExpectAndConsume(tok::semi,
+                           diag::err_expected_semi_after,
+                           "access declaration",
+                           tok::semi))
+        return;
+
+      Actions.ActOnUsingDeclaration(CurScope, AS,
+                                    false, SourceLocation(),
+                                    SS, Name,
+                                    /* AttrList */ 0,
+                                    /* IsTypeName */ false,
+                                    SourceLocation());
+      return;
+    }
+  }
+
+  // static_assert-declaration
+  if (Tok.is(tok::kw_static_assert)) {
+    // FIXME: Check for templates
+    SourceLocation DeclEnd;
+    ParseStaticAssertDeclaration(DeclEnd);
+    return;
+  }
+
+  if (Tok.is(tok::kw_template)) {
+    assert(!TemplateInfo.TemplateParams &&
+           "Nested template improperly parsed?");
+    SourceLocation DeclEnd;
+    ParseDeclarationStartingWithTemplate(Declarator::MemberContext, DeclEnd,
+                                         AS);
+    return;
+  }
+
+  // Handle:  member-declaration ::= '__extension__' member-declaration
+  if (Tok.is(tok::kw___extension__)) {
+    // __extension__ silences extension warnings in the subexpression.
+    ExtensionRAIIObject O(Diags);  // Use RAII to do this.
+    ConsumeToken();
+    return ParseCXXClassMemberDeclaration(AS, TemplateInfo);
+  }
+
+  // Don't parse FOO:BAR as if it were a typo for FOO::BAR, in this context it
+  // is a bitfield.
+  ColonProtectionRAIIObject X(*this);
+  
+  CXX0XAttributeList AttrList;
+  // Optional C++0x attribute-specifier
+  if (getLang().CPlusPlus0x && isCXX0XAttributeSpecifier())
+    AttrList = ParseCXX0XAttributes();
+
+  if (Tok.is(tok::kw_using)) {
+    // FIXME: Check for template aliases
+    
+    if (AttrList.HasAttr)
+      Diag(AttrList.Range.getBegin(), diag::err_attributes_not_allowed)
+        << AttrList.Range;
+
+    // Eat 'using'.
+    SourceLocation UsingLoc = ConsumeToken();
+
+    if (Tok.is(tok::kw_namespace)) {
+      Diag(UsingLoc, diag::err_using_namespace_in_class);
+      SkipUntil(tok::semi, true, true);
+    } else {
+      SourceLocation DeclEnd;
+      // Otherwise, it must be using-declaration.
+      ParseUsingDeclaration(Declarator::MemberContext, UsingLoc, DeclEnd, AS);
+    }
+    return;
+  }
+
+  SourceLocation DSStart = Tok.getLocation();
+  // decl-specifier-seq:
+  // Parse the common declaration-specifiers piece.
+  ParsingDeclSpec DS(*this);
+  DS.AddAttributes(AttrList.AttrList);
+  ParseDeclarationSpecifiers(DS, TemplateInfo, AS, DSC_class);
+
+  Action::MultiTemplateParamsArg TemplateParams(Actions,
+      TemplateInfo.TemplateParams? TemplateInfo.TemplateParams->data() : 0,
+      TemplateInfo.TemplateParams? TemplateInfo.TemplateParams->size() : 0);
+
+  if (Tok.is(tok::semi)) {
+    ConsumeToken();
+    Actions.ParsedFreeStandingDeclSpec(CurScope, DS);
+    return;
+  }
+
+  ParsingDeclarator DeclaratorInfo(*this, DS, Declarator::MemberContext);
+
+  if (Tok.isNot(tok::colon)) {
+    // Don't parse FOO:BAR as if it were a typo for FOO::BAR.
+    ColonProtectionRAIIObject X(*this);
+
+    // Parse the first declarator.
+    ParseDeclarator(DeclaratorInfo);
+    // Error parsing the declarator?
+    if (!DeclaratorInfo.hasName()) {
+      // If so, skip until the semi-colon or a }.
+      SkipUntil(tok::r_brace, true);
+      if (Tok.is(tok::semi))
+        ConsumeToken();
+      return;
+    }
+
+    // If attributes exist after the declarator, but before an '{', parse them.
+    if (Tok.is(tok::kw___attribute)) {
+      SourceLocation Loc;
+      AttributeList *AttrList = ParseGNUAttributes(&Loc);
+      DeclaratorInfo.AddAttributes(AttrList, Loc);
+    }
+
+    // function-definition:
+    if (Tok.is(tok::l_brace)
+        || (DeclaratorInfo.isFunctionDeclarator() &&
+            (Tok.is(tok::colon) || Tok.is(tok::kw_try)))) {
+      if (!DeclaratorInfo.isFunctionDeclarator()) {
+        Diag(Tok, diag::err_func_def_no_params);
+        ConsumeBrace();
+        SkipUntil(tok::r_brace, true);
+        return;
+      }
+
+      if (DS.getStorageClassSpec() == DeclSpec::SCS_typedef) {
+        Diag(Tok, diag::err_function_declared_typedef);
+        // This recovery skips the entire function body. It would be nice
+        // to simply call ParseCXXInlineMethodDef() below, however Sema
+        // assumes the declarator represents a function, not a typedef.
+        ConsumeBrace();
+        SkipUntil(tok::r_brace, true);
+        return;
+      }
+
+      ParseCXXInlineMethodDef(AS, DeclaratorInfo, TemplateInfo);
+      return;
+    }
+  }
+
+  // member-declarator-list:
+  //   member-declarator
+  //   member-declarator-list ',' member-declarator
+
+  llvm::SmallVector<DeclPtrTy, 8> DeclsInGroup;
+  OwningExprResult BitfieldSize(Actions);
+  OwningExprResult Init(Actions);
+  bool Deleted = false;
+
+  while (1) {
+    // member-declarator:
+    //   declarator pure-specifier[opt]
+    //   declarator constant-initializer[opt]
+    //   identifier[opt] ':' constant-expression
+
+    if (Tok.is(tok::colon)) {
+      ConsumeToken();
+      BitfieldSize = ParseConstantExpression();
+      if (BitfieldSize.isInvalid())
+        SkipUntil(tok::comma, true, true);
+    }
+
+    // pure-specifier:
+    //   '= 0'
+    //
+    // constant-initializer:
+    //   '=' constant-expression
+    //
+    // defaulted/deleted function-definition:
+    //   '=' 'default'                          [TODO]
+    //   '=' 'delete'
+
+    if (Tok.is(tok::equal)) {
+      ConsumeToken();
+      if (getLang().CPlusPlus0x && Tok.is(tok::kw_delete)) {
+        ConsumeToken();
+        Deleted = true;
+      } else {
+        Init = ParseInitializer();
+        if (Init.isInvalid())
+          SkipUntil(tok::comma, true, true);
+      }
+    }
+
+    // If attributes exist after the declarator, parse them.
+    if (Tok.is(tok::kw___attribute)) {
+      SourceLocation Loc;
+      AttributeList *AttrList = ParseGNUAttributes(&Loc);
+      DeclaratorInfo.AddAttributes(AttrList, Loc);
+    }
+
+    // NOTE: If Sema is the Action module and declarator is an instance field,
+    // this call will *not* return the created decl; It will return null.
+    // See Sema::ActOnCXXMemberDeclarator for details.
+
+    DeclPtrTy ThisDecl;
+    if (DS.isFriendSpecified()) {
+      // TODO: handle initializers, bitfields, 'delete'
+      ThisDecl = Actions.ActOnFriendFunctionDecl(CurScope, DeclaratorInfo,
+                                                 /*IsDefinition*/ false,
+                                                 move(TemplateParams));
+    } else {
+      ThisDecl = Actions.ActOnCXXMemberDeclarator(CurScope, AS,
+                                                  DeclaratorInfo,
+                                                  move(TemplateParams),
+                                                  BitfieldSize.release(),
+                                                  Init.release(),
+                                                  /*IsDefinition*/Deleted,
+                                                  Deleted);
+    }
+    if (ThisDecl)
+      DeclsInGroup.push_back(ThisDecl);
+
+    if (DeclaratorInfo.isFunctionDeclarator() &&
+        DeclaratorInfo.getDeclSpec().getStorageClassSpec()
+          != DeclSpec::SCS_typedef) {
+      HandleMemberFunctionDefaultArgs(DeclaratorInfo, ThisDecl);
+    }
+
+    DeclaratorInfo.complete(ThisDecl);
+
+    // If we don't have a comma, it is either the end of the list (a ';')
+    // or an error, bail out.
+    if (Tok.isNot(tok::comma))
+      break;
+
+    // Consume the comma.
+    ConsumeToken();
+
+    // Parse the next declarator.
+    DeclaratorInfo.clear();
+    BitfieldSize = 0;
+    Init = 0;
+    Deleted = false;
+
+    // Attributes are only allowed on the second declarator.
+    if (Tok.is(tok::kw___attribute)) {
+      SourceLocation Loc;
+      AttributeList *AttrList = ParseGNUAttributes(&Loc);
+      DeclaratorInfo.AddAttributes(AttrList, Loc);
+    }
+
+    if (Tok.isNot(tok::colon))
+      ParseDeclarator(DeclaratorInfo);
+  }
+
+  if (ExpectAndConsume(tok::semi, diag::err_expected_semi_decl_list)) {
+    // Skip to end of block or statement.
+    SkipUntil(tok::r_brace, true, true);
+    // If we stopped at a ';', eat it.
+    if (Tok.is(tok::semi)) ConsumeToken();
+    return;
+  }
+
+  Actions.FinalizeDeclaratorGroup(CurScope, DS, DeclsInGroup.data(),
+                                  DeclsInGroup.size());
+}
+
+/// ParseCXXMemberSpecification - Parse the class definition.
+///
+///       member-specification:
+///         member-declaration member-specification[opt]
+///         access-specifier ':' member-specification[opt]
+///
+void Parser::ParseCXXMemberSpecification(SourceLocation RecordLoc,
+                                         unsigned TagType, DeclPtrTy TagDecl) {
+  assert((TagType == DeclSpec::TST_struct ||
+         TagType == DeclSpec::TST_union  ||
+         TagType == DeclSpec::TST_class) && "Invalid TagType!");
+
+  PrettyStackTraceActionsDecl CrashInfo(TagDecl, RecordLoc, Actions,
+                                        PP.getSourceManager(),
+                                        "parsing struct/union/class body");
+
+  // Determine whether this is a non-nested class. Note that local
+  // classes are *not* considered to be nested classes.
+  bool NonNestedClass = true;
+  if (!ClassStack.empty()) {
+    for (const Scope *S = CurScope; S; S = S->getParent()) {
+      if (S->isClassScope()) {
+        // We're inside a class scope, so this is a nested class.
+        NonNestedClass = false;
+        break;
+      }
+
+      if ((S->getFlags() & Scope::FnScope)) {
+        // If we're in a function or function template declared in the
+        // body of a class, then this is a local class rather than a
+        // nested class.
+        const Scope *Parent = S->getParent();
+        if (Parent->isTemplateParamScope())
+          Parent = Parent->getParent();
+        if (Parent->isClassScope())
+          break;
+      }
+    }
+  }
+
+  // Enter a scope for the class.
+  ParseScope ClassScope(this, Scope::ClassScope|Scope::DeclScope);
+
+  // Note that we are parsing a new (potentially-nested) class definition.
+  ParsingClassDefinition ParsingDef(*this, TagDecl, NonNestedClass);
+
+  if (TagDecl)
+    Actions.ActOnTagStartDefinition(CurScope, TagDecl);
+
+  if (Tok.is(tok::colon)) {
+    ParseBaseClause(TagDecl);
+
+    if (!Tok.is(tok::l_brace)) {
+      Diag(Tok, diag::err_expected_lbrace_after_base_specifiers);
+      return;
+    }
+  }
+
+  assert(Tok.is(tok::l_brace));
+
+  SourceLocation LBraceLoc = ConsumeBrace();
+
+  if (!TagDecl) {
+    SkipUntil(tok::r_brace, false, false);
+    return;
+  }
+
+  Actions.ActOnStartCXXMemberDeclarations(CurScope, TagDecl, LBraceLoc);
+
+  // C++ 11p3: Members of a class defined with the keyword class are private
+  // by default. Members of a class defined with the keywords struct or union
+  // are public by default.
+  AccessSpecifier CurAS;
+  if (TagType == DeclSpec::TST_class)
+    CurAS = AS_private;
+  else
+    CurAS = AS_public;
+
+  // While we still have something to read, read the member-declarations.
+  while (Tok.isNot(tok::r_brace) && Tok.isNot(tok::eof)) {
+    // Each iteration of this loop reads one member-declaration.
+
+    // Check for extraneous top-level semicolon.
+    if (Tok.is(tok::semi)) {
+      Diag(Tok, diag::ext_extra_struct_semi)
+        << CodeModificationHint::CreateRemoval(Tok.getLocation());
+      ConsumeToken();
+      continue;
+    }
+
+    AccessSpecifier AS = getAccessSpecifierIfPresent();
+    if (AS != AS_none) {
+      // Current token is a C++ access specifier.
+      CurAS = AS;
+      ConsumeToken();
+      ExpectAndConsume(tok::colon, diag::err_expected_colon);
+      continue;
+    }
+
+    // FIXME: Make sure we don't have a template here.
+
+    // Parse all the comma separated declarators.
+    ParseCXXClassMemberDeclaration(CurAS);
+  }
+
+  SourceLocation RBraceLoc = MatchRHSPunctuation(tok::r_brace, LBraceLoc);
+
+  AttributeList *AttrList = 0;
+  // If attributes exist after class contents, parse them.
+  if (Tok.is(tok::kw___attribute))
+    AttrList = ParseGNUAttributes(); // FIXME: where should I put them?
+
+  Actions.ActOnFinishCXXMemberSpecification(CurScope, RecordLoc, TagDecl,
+                                            LBraceLoc, RBraceLoc);
+
+  // C++ 9.2p2: Within the class member-specification, the class is regarded as
+  // complete within function bodies, default arguments,
+  // exception-specifications, and constructor ctor-initializers (including
+  // such things in nested classes).
+  //
+  // FIXME: Only function bodies and constructor ctor-initializers are
+  // parsed correctly, fix the rest.
+  if (NonNestedClass) {
+    // We are not inside a nested class. This class and its nested classes
+    // are complete and we can parse the delayed portions of method
+    // declarations and the lexed inline method definitions.
+    ParseLexedMethodDeclarations(getCurrentClass());
+    ParseLexedMethodDefs(getCurrentClass());
+  }
+
+  // Leave the class scope.
+  ParsingDef.Pop();
+  ClassScope.Exit();
+
+  Actions.ActOnTagFinishDefinition(CurScope, TagDecl, RBraceLoc);
+}
+
+/// ParseConstructorInitializer - Parse a C++ constructor initializer,
+/// which explicitly initializes the members or base classes of a
+/// class (C++ [class.base.init]). For example, the three initializers
+/// after the ':' in the Derived constructor below:
+///
+/// @code
+/// class Base { };
+/// class Derived : Base {
+///   int x;
+///   float f;
+/// public:
+///   Derived(float f) : Base(), x(17), f(f) { }
+/// };
+/// @endcode
+///
+/// [C++]  ctor-initializer:
+///          ':' mem-initializer-list
+///
+/// [C++]  mem-initializer-list:
+///          mem-initializer
+///          mem-initializer , mem-initializer-list
+void Parser::ParseConstructorInitializer(DeclPtrTy ConstructorDecl) {
+  assert(Tok.is(tok::colon) && "Constructor initializer always starts with ':'");
+
+  SourceLocation ColonLoc = ConsumeToken();
+
+  llvm::SmallVector<MemInitTy*, 4> MemInitializers;
+  bool AnyErrors = false;
+  
+  do {
+    MemInitResult MemInit = ParseMemInitializer(ConstructorDecl);
+    if (!MemInit.isInvalid())
+      MemInitializers.push_back(MemInit.get());
+    else
+      AnyErrors = true;
+    
+    if (Tok.is(tok::comma))
+      ConsumeToken();
+    else if (Tok.is(tok::l_brace))
+      break;
+    else {
+      // Skip over garbage, until we get to '{'.  Don't eat the '{'.
+      Diag(Tok.getLocation(), diag::err_expected_lbrace_or_comma);
+      SkipUntil(tok::l_brace, true, true);
+      break;
+    }
+  } while (true);
+
+  Actions.ActOnMemInitializers(ConstructorDecl, ColonLoc,
+                               MemInitializers.data(), MemInitializers.size(),
+                               AnyErrors);
+}
+
+/// ParseMemInitializer - Parse a C++ member initializer, which is
+/// part of a constructor initializer that explicitly initializes one
+/// member or base class (C++ [class.base.init]). See
+/// ParseConstructorInitializer for an example.
+///
+/// [C++] mem-initializer:
+///         mem-initializer-id '(' expression-list[opt] ')'
+///
+/// [C++] mem-initializer-id:
+///         '::'[opt] nested-name-specifier[opt] class-name
+///         identifier
+Parser::MemInitResult Parser::ParseMemInitializer(DeclPtrTy ConstructorDecl) {
+  // parse '::'[opt] nested-name-specifier[opt]
+  CXXScopeSpec SS;
+  ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/0, false);
+  TypeTy *TemplateTypeTy = 0;
+  if (Tok.is(tok::annot_template_id)) {
+    TemplateIdAnnotation *TemplateId
+      = static_cast<TemplateIdAnnotation *>(Tok.getAnnotationValue());
+    if (TemplateId->Kind == TNK_Type_template ||
+        TemplateId->Kind == TNK_Dependent_template_name) {
+      AnnotateTemplateIdTokenAsType(&SS);
+      assert(Tok.is(tok::annot_typename) && "template-id -> type failed");
+      TemplateTypeTy = Tok.getAnnotationValue();
+    }
+  }
+  if (!TemplateTypeTy && Tok.isNot(tok::identifier)) {
+    Diag(Tok, diag::err_expected_member_or_base_name);
+    return true;
+  }
+
+  // Get the identifier. This may be a member name or a class name,
+  // but we'll let the semantic analysis determine which it is.
+  IdentifierInfo *II = Tok.is(tok::identifier) ? Tok.getIdentifierInfo() : 0;
+  SourceLocation IdLoc = ConsumeToken();
+
+  // Parse the '('.
+  if (Tok.isNot(tok::l_paren)) {
+    Diag(Tok, diag::err_expected_lparen);
+    return true;
+  }
+  SourceLocation LParenLoc = ConsumeParen();
+
+  // Parse the optional expression-list.
+  ExprVector ArgExprs(Actions);
+  CommaLocsTy CommaLocs;
+  if (Tok.isNot(tok::r_paren) && ParseExpressionList(ArgExprs, CommaLocs)) {
+    SkipUntil(tok::r_paren);
+    return true;
+  }
+
+  SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc);
+
+  return Actions.ActOnMemInitializer(ConstructorDecl, CurScope, SS, II,
+                                     TemplateTypeTy, IdLoc,
+                                     LParenLoc, ArgExprs.take(),
+                                     ArgExprs.size(), CommaLocs.data(),
+                                     RParenLoc);
+}
+
+/// ParseExceptionSpecification - Parse a C++ exception-specification
+/// (C++ [except.spec]).
+///
+///       exception-specification:
+///         'throw' '(' type-id-list [opt] ')'
+/// [MS]    'throw' '(' '...' ')'
+///
+///       type-id-list:
+///         type-id
+///         type-id-list ',' type-id
+///
+bool Parser::ParseExceptionSpecification(SourceLocation &EndLoc,
+                                         llvm::SmallVector<TypeTy*, 2>
+                                             &Exceptions,
+                                         llvm::SmallVector<SourceRange, 2>
+                                             &Ranges,
+                                         bool &hasAnyExceptionSpec) {
+  assert(Tok.is(tok::kw_throw) && "expected throw");
+
+  SourceLocation ThrowLoc = ConsumeToken();
+
+  if (!Tok.is(tok::l_paren)) {
+    return Diag(Tok, diag::err_expected_lparen_after) << "throw";
+  }
+  SourceLocation LParenLoc = ConsumeParen();
+
+  // Parse throw(...), a Microsoft extension that means "this function
+  // can throw anything".
+  if (Tok.is(tok::ellipsis)) {
+    hasAnyExceptionSpec = true;
+    SourceLocation EllipsisLoc = ConsumeToken();
+    if (!getLang().Microsoft)
+      Diag(EllipsisLoc, diag::ext_ellipsis_exception_spec);
+    EndLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc);
+    return false;
+  }
+
+  // Parse the sequence of type-ids.
+  SourceRange Range;
+  while (Tok.isNot(tok::r_paren)) {
+    TypeResult Res(ParseTypeName(&Range));
+    if (!Res.isInvalid()) {
+      Exceptions.push_back(Res.get());
+      Ranges.push_back(Range);
+    }
+    if (Tok.is(tok::comma))
+      ConsumeToken();
+    else
+      break;
+  }
+
+  EndLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc);
+  return false;
+}
+
+/// \brief We have just started parsing the definition of a new class,
+/// so push that class onto our stack of classes that is currently
+/// being parsed.
+void Parser::PushParsingClass(DeclPtrTy ClassDecl, bool NonNestedClass) {
+  assert((NonNestedClass || !ClassStack.empty()) &&
+         "Nested class without outer class");
+  ClassStack.push(new ParsingClass(ClassDecl, NonNestedClass));
+}
+
+/// \brief Deallocate the given parsed class and all of its nested
+/// classes.
+void Parser::DeallocateParsedClasses(Parser::ParsingClass *Class) {
+  for (unsigned I = 0, N = Class->NestedClasses.size(); I != N; ++I)
+    DeallocateParsedClasses(Class->NestedClasses[I]);
+  delete Class;
+}
+
+/// \brief Pop the top class of the stack of classes that are
+/// currently being parsed.
+///
+/// This routine should be called when we have finished parsing the
+/// definition of a class, but have not yet popped the Scope
+/// associated with the class's definition.
+///
+/// \returns true if the class we've popped is a top-level class,
+/// false otherwise.
+void Parser::PopParsingClass() {
+  assert(!ClassStack.empty() && "Mismatched push/pop for class parsing");
+
+  ParsingClass *Victim = ClassStack.top();
+  ClassStack.pop();
+  if (Victim->TopLevelClass) {
+    // Deallocate all of the nested classes of this class,
+    // recursively: we don't need to keep any of this information.
+    DeallocateParsedClasses(Victim);
+    return;
+  }
+  assert(!ClassStack.empty() && "Missing top-level class?");
+
+  if (Victim->MethodDecls.empty() && Victim->MethodDefs.empty() &&
+      Victim->NestedClasses.empty()) {
+    // The victim is a nested class, but we will not need to perform
+    // any processing after the definition of this class since it has
+    // no members whose handling was delayed. Therefore, we can just
+    // remove this nested class.
+    delete Victim;
+    return;
+  }
+
+  // This nested class has some members that will need to be processed
+  // after the top-level class is completely defined. Therefore, add
+  // it to the list of nested classes within its parent.
+  assert(CurScope->isClassScope() && "Nested class outside of class scope?");
+  ClassStack.top()->NestedClasses.push_back(Victim);
+  Victim->TemplateScope = CurScope->getParent()->isTemplateParamScope();
+}
+
+/// ParseCXX0XAttributes - Parse a C++0x attribute-specifier. Currently only
+/// parses standard attributes.
+///
+/// [C++0x] attribute-specifier:
+///         '[' '[' attribute-list ']' ']'
+///
+/// [C++0x] attribute-list:
+///         attribute[opt]
+///         attribute-list ',' attribute[opt]
+///
+/// [C++0x] attribute:
+///         attribute-token attribute-argument-clause[opt]
+///
+/// [C++0x] attribute-token:
+///         identifier
+///         attribute-scoped-token
+///
+/// [C++0x] attribute-scoped-token:
+///         attribute-namespace '::' identifier
+///
+/// [C++0x] attribute-namespace:
+///         identifier
+///
+/// [C++0x] attribute-argument-clause:
+///         '(' balanced-token-seq ')'
+///
+/// [C++0x] balanced-token-seq:
+///         balanced-token
+///         balanced-token-seq balanced-token
+///
+/// [C++0x] balanced-token:
+///         '(' balanced-token-seq ')'
+///         '[' balanced-token-seq ']'
+///         '{' balanced-token-seq '}'
+///         any token but '(', ')', '[', ']', '{', or '}'
+CXX0XAttributeList Parser::ParseCXX0XAttributes(SourceLocation *EndLoc) {
+  assert(Tok.is(tok::l_square) && NextToken().is(tok::l_square)
+      && "Not a C++0x attribute list");
+
+  SourceLocation StartLoc = Tok.getLocation(), Loc;
+  AttributeList *CurrAttr = 0;
+
+  ConsumeBracket();
+  ConsumeBracket();
+  
+  if (Tok.is(tok::comma)) {
+    Diag(Tok.getLocation(), diag::err_expected_ident);
+    ConsumeToken();
+  }
+
+  while (Tok.is(tok::identifier) || Tok.is(tok::comma)) {
+    // attribute not present
+    if (Tok.is(tok::comma)) {
+      ConsumeToken();
+      continue;
+    }
+
+    IdentifierInfo *ScopeName = 0, *AttrName = Tok.getIdentifierInfo();
+    SourceLocation ScopeLoc, AttrLoc = ConsumeToken();
+    
+    // scoped attribute
+    if (Tok.is(tok::coloncolon)) {
+      ConsumeToken();
+
+      if (!Tok.is(tok::identifier)) {
+        Diag(Tok.getLocation(), diag::err_expected_ident);
+        SkipUntil(tok::r_square, tok::comma, true, true);
+        continue;
+      }
+      
+      ScopeName = AttrName;
+      ScopeLoc = AttrLoc;
+
+      AttrName = Tok.getIdentifierInfo();
+      AttrLoc = ConsumeToken();
+    }
+
+    bool AttrParsed = false;
+    // No scoped names are supported; ideally we could put all non-standard
+    // attributes into namespaces.
+    if (!ScopeName) {
+      switch(AttributeList::getKind(AttrName))
+      {
+      // No arguments
+      case AttributeList::AT_base_check:
+      case AttributeList::AT_carries_dependency:
+      case AttributeList::AT_final:
+      case AttributeList::AT_hiding:
+      case AttributeList::AT_noreturn:
+      case AttributeList::AT_override: {
+        if (Tok.is(tok::l_paren)) {
+          Diag(Tok.getLocation(), diag::err_cxx0x_attribute_forbids_arguments)
+            << AttrName->getName();
+          break;
+        }
+
+        CurrAttr = new AttributeList(AttrName, AttrLoc, 0, AttrLoc, 0,
+                                     SourceLocation(), 0, 0, CurrAttr, false,
+                                     true);
+        AttrParsed = true;
+        break;
+      }
+
+      // One argument; must be a type-id or assignment-expression
+      case AttributeList::AT_aligned: {
+        if (Tok.isNot(tok::l_paren)) {
+          Diag(Tok.getLocation(), diag::err_cxx0x_attribute_requires_arguments)
+            << AttrName->getName();
+          break;
+        }
+        SourceLocation ParamLoc = ConsumeParen();
+
+        OwningExprResult ArgExpr = ParseCXX0XAlignArgument(ParamLoc);
+
+        MatchRHSPunctuation(tok::r_paren, ParamLoc);
+
+        ExprVector ArgExprs(Actions);
+        ArgExprs.push_back(ArgExpr.release());
+        CurrAttr = new AttributeList(AttrName, AttrLoc, 0, AttrLoc,
+                                     0, ParamLoc, ArgExprs.take(), 1, CurrAttr,
+                                     false, true);
+
+        AttrParsed = true;
+        break;
+      }
+
+      // Silence warnings
+      default: break;
+      }
+    }
+
+    // Skip the entire parameter clause, if any
+    if (!AttrParsed && Tok.is(tok::l_paren)) {
+      ConsumeParen();
+      // SkipUntil maintains the balancedness of tokens.
+      SkipUntil(tok::r_paren, false);
+    }
+  }
+
+  if (ExpectAndConsume(tok::r_square, diag::err_expected_rsquare))
+    SkipUntil(tok::r_square, false);
+  Loc = Tok.getLocation();
+  if (ExpectAndConsume(tok::r_square, diag::err_expected_rsquare))
+    SkipUntil(tok::r_square, false);
+
+  CXX0XAttributeList Attr (CurrAttr, SourceRange(StartLoc, Loc), true);
+  return Attr;
+}
+
+/// ParseCXX0XAlignArgument - Parse the argument to C++0x's [[align]]
+/// attribute.
+///
+/// FIXME: Simply returns an alignof() expression if the argument is a
+/// type. Ideally, the type should be propagated directly into Sema.
+///
+/// [C++0x] 'align' '(' type-id ')'
+/// [C++0x] 'align' '(' assignment-expression ')'
+Parser::OwningExprResult Parser::ParseCXX0XAlignArgument(SourceLocation Start) {
+  if (isTypeIdInParens()) {
+    EnterExpressionEvaluationContext Unevaluated(Actions,
+                                                  Action::Unevaluated);
+    SourceLocation TypeLoc = Tok.getLocation();
+    TypeTy *Ty = ParseTypeName().get();
+    SourceRange TypeRange(Start, Tok.getLocation());
+    return Actions.ActOnSizeOfAlignOfExpr(TypeLoc, false, true, Ty,
+                                              TypeRange);
+  } else
+    return ParseConstantExpression();
+}
diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp
new file mode 100644
index 0000000..c763c2c
--- /dev/null
+++ b/lib/Parse/ParseExpr.cpp
@@ -0,0 +1,1668 @@
+//===--- ParseExpr.cpp - Expression Parsing -------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the Expression parsing implementation.  Expressions in
+// C99 basically consist of a bunch of binary operators with unary operators and
+// other random stuff at the leaves.
+//
+// In the C99 grammar, these unary operators bind tightest and are represented
+// as the 'cast-expression' production.  Everything else is either a binary
+// operator (e.g. '/') or a ternary operator ("?:").  The unary leaves are
+// handled by ParseCastExpression, the higher level pieces are handled by
+// ParseBinaryExpression.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Parse/Parser.h"
+#include "clang/Parse/DeclSpec.h"
+#include "clang/Parse/Scope.h"
+#include "clang/Parse/Template.h"
+#include "clang/Basic/PrettyStackTrace.h"
+#include "RAIIObjectsForParser.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallString.h"
+using namespace clang;
+
+/// PrecedenceLevels - These are precedences for the binary/ternary operators in
+/// the C99 grammar.  These have been named to relate with the C99 grammar
+/// productions.  Low precedences numbers bind more weakly than high numbers.
+namespace prec {
+  enum Level {
+    Unknown         = 0,    // Not binary operator.
+    Comma           = 1,    // ,
+    Assignment      = 2,    // =, *=, /=, %=, +=, -=, <<=, >>=, &=, ^=, |=
+    Conditional     = 3,    // ?
+    LogicalOr       = 4,    // ||
+    LogicalAnd      = 5,    // &&
+    InclusiveOr     = 6,    // |
+    ExclusiveOr     = 7,    // ^
+    And             = 8,    // &
+    Equality        = 9,    // ==, !=
+    Relational      = 10,   //  >=, <=, >, <
+    Shift           = 11,   // <<, >>
+    Additive        = 12,   // -, +
+    Multiplicative  = 13,   // *, /, %
+    PointerToMember = 14    // .*, ->*
+  };
+}
+
+
+/// getBinOpPrecedence - Return the precedence of the specified binary operator
+/// token.  This returns:
+///
+static prec::Level getBinOpPrecedence(tok::TokenKind Kind,
+                                      bool GreaterThanIsOperator,
+                                      bool CPlusPlus0x) {
+  switch (Kind) {
+  case tok::greater:
+    // C++ [temp.names]p3:
+    //   [...] When parsing a template-argument-list, the first
+    //   non-nested > is taken as the ending delimiter rather than a
+    //   greater-than operator. [...]
+    if (GreaterThanIsOperator)
+      return prec::Relational;
+    return prec::Unknown;
+
+  case tok::greatergreater:
+    // C++0x [temp.names]p3:
+    //
+    //   [...] Similarly, the first non-nested >> is treated as two
+    //   consecutive but distinct > tokens, the first of which is
+    //   taken as the end of the template-argument-list and completes
+    //   the template-id. [...]
+    if (GreaterThanIsOperator || !CPlusPlus0x)
+      return prec::Shift;
+    return prec::Unknown;
+
+  default:                        return prec::Unknown;
+  case tok::comma:                return prec::Comma;
+  case tok::equal:
+  case tok::starequal:
+  case tok::slashequal:
+  case tok::percentequal:
+  case tok::plusequal:
+  case tok::minusequal:
+  case tok::lesslessequal:
+  case tok::greatergreaterequal:
+  case tok::ampequal:
+  case tok::caretequal:
+  case tok::pipeequal:            return prec::Assignment;
+  case tok::question:             return prec::Conditional;
+  case tok::pipepipe:             return prec::LogicalOr;
+  case tok::ampamp:               return prec::LogicalAnd;
+  case tok::pipe:                 return prec::InclusiveOr;
+  case tok::caret:                return prec::ExclusiveOr;
+  case tok::amp:                  return prec::And;
+  case tok::exclaimequal:
+  case tok::equalequal:           return prec::Equality;
+  case tok::lessequal:
+  case tok::less:
+  case tok::greaterequal:         return prec::Relational;
+  case tok::lessless:             return prec::Shift;
+  case tok::plus:
+  case tok::minus:                return prec::Additive;
+  case tok::percent:
+  case tok::slash:
+  case tok::star:                 return prec::Multiplicative;
+  case tok::periodstar:
+  case tok::arrowstar:            return prec::PointerToMember;
+  }
+}
+
+
+/// ParseExpression - Simple precedence-based parser for binary/ternary
+/// operators.
+///
+/// Note: we diverge from the C99 grammar when parsing the assignment-expression
+/// production.  C99 specifies that the LHS of an assignment operator should be
+/// parsed as a unary-expression, but consistency dictates that it be a
+/// conditional-expession.  In practice, the important thing here is that the
+/// LHS of an assignment has to be an l-value, which productions between
+/// unary-expression and conditional-expression don't produce.  Because we want
+/// consistency, we parse the LHS as a conditional-expression, then check for
+/// l-value-ness in semantic analysis stages.
+///
+///       pm-expression: [C++ 5.5]
+///         cast-expression
+///         pm-expression '.*' cast-expression
+///         pm-expression '->*' cast-expression
+///
+///       multiplicative-expression: [C99 6.5.5]
+///     Note: in C++, apply pm-expression instead of cast-expression
+///         cast-expression
+///         multiplicative-expression '*' cast-expression
+///         multiplicative-expression '/' cast-expression
+///         multiplicative-expression '%' cast-expression
+///
+///       additive-expression: [C99 6.5.6]
+///         multiplicative-expression
+///         additive-expression '+' multiplicative-expression
+///         additive-expression '-' multiplicative-expression
+///
+///       shift-expression: [C99 6.5.7]
+///         additive-expression
+///         shift-expression '<<' additive-expression
+///         shift-expression '>>' additive-expression
+///
+///       relational-expression: [C99 6.5.8]
+///         shift-expression
+///         relational-expression '<' shift-expression
+///         relational-expression '>' shift-expression
+///         relational-expression '<=' shift-expression
+///         relational-expression '>=' shift-expression
+///
+///       equality-expression: [C99 6.5.9]
+///         relational-expression
+///         equality-expression '==' relational-expression
+///         equality-expression '!=' relational-expression
+///
+///       AND-expression: [C99 6.5.10]
+///         equality-expression
+///         AND-expression '&' equality-expression
+///
+///       exclusive-OR-expression: [C99 6.5.11]
+///         AND-expression
+///         exclusive-OR-expression '^' AND-expression
+///
+///       inclusive-OR-expression: [C99 6.5.12]
+///         exclusive-OR-expression
+///         inclusive-OR-expression '|' exclusive-OR-expression
+///
+///       logical-AND-expression: [C99 6.5.13]
+///         inclusive-OR-expression
+///         logical-AND-expression '&&' inclusive-OR-expression
+///
+///       logical-OR-expression: [C99 6.5.14]
+///         logical-AND-expression
+///         logical-OR-expression '||' logical-AND-expression
+///
+///       conditional-expression: [C99 6.5.15]
+///         logical-OR-expression
+///         logical-OR-expression '?' expression ':' conditional-expression
+/// [GNU]   logical-OR-expression '?' ':' conditional-expression
+/// [C++] the third operand is an assignment-expression
+///
+///       assignment-expression: [C99 6.5.16]
+///         conditional-expression
+///         unary-expression assignment-operator assignment-expression
+/// [C++]   throw-expression [C++ 15]
+///
+///       assignment-operator: one of
+///         = *= /= %= += -= <<= >>= &= ^= |=
+///
+///       expression: [C99 6.5.17]
+///         assignment-expression
+///         expression ',' assignment-expression
+///
+Parser::OwningExprResult Parser::ParseExpression() {
+  OwningExprResult LHS(ParseAssignmentExpression());
+  if (LHS.isInvalid()) return move(LHS);
+
+  return ParseRHSOfBinaryExpression(move(LHS), prec::Comma);
+}
+
+/// This routine is called when the '@' is seen and consumed.
+/// Current token is an Identifier and is not a 'try'. This
+/// routine is necessary to disambiguate @try-statement from,
+/// for example, @encode-expression.
+///
+Parser::OwningExprResult
+Parser::ParseExpressionWithLeadingAt(SourceLocation AtLoc) {
+  OwningExprResult LHS(ParseObjCAtExpression(AtLoc));
+  if (LHS.isInvalid()) return move(LHS);
+
+  return ParseRHSOfBinaryExpression(move(LHS), prec::Comma);
+}
+
+/// This routine is called when a leading '__extension__' is seen and
+/// consumed.  This is necessary because the token gets consumed in the
+/// process of disambiguating between an expression and a declaration.
+Parser::OwningExprResult
+Parser::ParseExpressionWithLeadingExtension(SourceLocation ExtLoc) {
+  OwningExprResult LHS(Actions, true);
+  {
+    // Silence extension warnings in the sub-expression
+    ExtensionRAIIObject O(Diags);
+
+    LHS = ParseCastExpression(false);
+    if (LHS.isInvalid()) return move(LHS);
+  }
+
+  LHS = Actions.ActOnUnaryOp(CurScope, ExtLoc, tok::kw___extension__,
+                             move(LHS));
+  if (LHS.isInvalid()) return move(LHS);
+
+  return ParseRHSOfBinaryExpression(move(LHS), prec::Comma);
+}
+
+/// ParseAssignmentExpression - Parse an expr that doesn't include commas.
+///
+Parser::OwningExprResult Parser::ParseAssignmentExpression() {
+  if (Tok.is(tok::code_completion)) {
+    Actions.CodeCompleteOrdinaryName(CurScope, Action::CCC_Expression);
+    ConsumeToken();
+  }
+
+  if (Tok.is(tok::kw_throw))
+    return ParseThrowExpression();
+
+  OwningExprResult LHS(ParseCastExpression(false));
+  if (LHS.isInvalid()) return move(LHS);
+
+  return ParseRHSOfBinaryExpression(move(LHS), prec::Assignment);
+}
+
+/// ParseAssignmentExprWithObjCMessageExprStart - Parse an assignment expression
+/// where part of an objc message send has already been parsed.  In this case
+/// LBracLoc indicates the location of the '[' of the message send, and either
+/// ReceiverName or ReceiverExpr is non-null indicating the receiver of the
+/// message.
+///
+/// Since this handles full assignment-expression's, it handles postfix
+/// expressions and other binary operators for these expressions as well.
+Parser::OwningExprResult
+Parser::ParseAssignmentExprWithObjCMessageExprStart(SourceLocation LBracLoc,
+                                                    SourceLocation NameLoc,
+                                                   IdentifierInfo *ReceiverName,
+                                                    ExprArg ReceiverExpr) {
+  OwningExprResult R(ParseObjCMessageExpressionBody(LBracLoc, NameLoc,
+                                                    ReceiverName,
+                                                    move(ReceiverExpr)));
+  if (R.isInvalid()) return move(R);
+  R = ParsePostfixExpressionSuffix(move(R));
+  if (R.isInvalid()) return move(R);
+  return ParseRHSOfBinaryExpression(move(R), prec::Assignment);
+}
+
+
+Parser::OwningExprResult Parser::ParseConstantExpression() {
+  // C++ [basic.def.odr]p2:
+  //   An expression is potentially evaluated unless it appears where an
+  //   integral constant expression is required (see 5.19) [...].
+  EnterExpressionEvaluationContext Unevaluated(Actions,
+                                               Action::Unevaluated);
+
+  OwningExprResult LHS(ParseCastExpression(false));
+  if (LHS.isInvalid()) return move(LHS);
+
+  return ParseRHSOfBinaryExpression(move(LHS), prec::Conditional);
+}
+
+/// ParseRHSOfBinaryExpression - Parse a binary expression that starts with
+/// LHS and has a precedence of at least MinPrec.
+Parser::OwningExprResult
+Parser::ParseRHSOfBinaryExpression(OwningExprResult LHS, unsigned MinPrec) {
+  unsigned NextTokPrec = getBinOpPrecedence(Tok.getKind(),
+                                            GreaterThanIsOperator,
+                                            getLang().CPlusPlus0x);
+  SourceLocation ColonLoc;
+
+  while (1) {
+    // If this token has a lower precedence than we are allowed to parse (e.g.
+    // because we are called recursively, or because the token is not a binop),
+    // then we are done!
+    if (NextTokPrec < MinPrec)
+      return move(LHS);
+
+    // Consume the operator, saving the operator token for error reporting.
+    Token OpToken = Tok;
+    ConsumeToken();
+
+    // Special case handling for the ternary operator.
+    OwningExprResult TernaryMiddle(Actions, true);
+    if (NextTokPrec == prec::Conditional) {
+      if (Tok.isNot(tok::colon)) {
+        // Don't parse FOO:BAR as if it were a typo for FOO::BAR.
+        ColonProtectionRAIIObject X(*this);
+
+        // Handle this production specially:
+        //   logical-OR-expression '?' expression ':' conditional-expression
+        // In particular, the RHS of the '?' is 'expression', not
+        // 'logical-OR-expression' as we might expect.
+        TernaryMiddle = ParseExpression();
+        if (TernaryMiddle.isInvalid())
+          return move(TernaryMiddle);
+      } else {
+        // Special case handling of "X ? Y : Z" where Y is empty:
+        //   logical-OR-expression '?' ':' conditional-expression   [GNU]
+        TernaryMiddle = 0;
+        Diag(Tok, diag::ext_gnu_conditional_expr);
+      }
+
+      if (Tok.isNot(tok::colon)) {
+        Diag(Tok, diag::err_expected_colon);
+        Diag(OpToken, diag::note_matching) << "?";
+        return ExprError();
+      }
+
+      // Eat the colon.
+      ColonLoc = ConsumeToken();
+    }
+    
+    // Parse another leaf here for the RHS of the operator.
+    // ParseCastExpression works here because all RHS expressions in C have it
+    // as a prefix, at least. However, in C++, an assignment-expression could
+    // be a throw-expression, which is not a valid cast-expression.
+    // Therefore we need some special-casing here.
+    // Also note that the third operand of the conditional operator is
+    // an assignment-expression in C++.
+    OwningExprResult RHS(Actions);
+    if (getLang().CPlusPlus && NextTokPrec <= prec::Conditional)
+      RHS = ParseAssignmentExpression();
+    else
+      RHS = ParseCastExpression(false);
+    if (RHS.isInvalid())
+      return move(RHS);
+
+    // Remember the precedence of this operator and get the precedence of the
+    // operator immediately to the right of the RHS.
+    unsigned ThisPrec = NextTokPrec;
+    NextTokPrec = getBinOpPrecedence(Tok.getKind(), GreaterThanIsOperator,
+                                     getLang().CPlusPlus0x);
+
+    // Assignment and conditional expressions are right-associative.
+    bool isRightAssoc = ThisPrec == prec::Conditional ||
+                        ThisPrec == prec::Assignment;
+
+    // Get the precedence of the operator to the right of the RHS.  If it binds
+    // more tightly with RHS than we do, evaluate it completely first.
+    if (ThisPrec < NextTokPrec ||
+        (ThisPrec == NextTokPrec && isRightAssoc)) {
+      // If this is left-associative, only parse things on the RHS that bind
+      // more tightly than the current operator.  If it is left-associative, it
+      // is okay, to bind exactly as tightly.  For example, compile A=B=C=D as
+      // A=(B=(C=D)), where each paren is a level of recursion here.
+      // The function takes ownership of the RHS.
+      RHS = ParseRHSOfBinaryExpression(move(RHS), ThisPrec + !isRightAssoc);
+      if (RHS.isInvalid())
+        return move(RHS);
+
+      NextTokPrec = getBinOpPrecedence(Tok.getKind(), GreaterThanIsOperator,
+                                       getLang().CPlusPlus0x);
+    }
+    assert(NextTokPrec <= ThisPrec && "Recursion didn't work!");
+
+    if (!LHS.isInvalid()) {
+      // Combine the LHS and RHS into the LHS (e.g. build AST).
+      if (TernaryMiddle.isInvalid()) {
+        // If we're using '>>' as an operator within a template
+        // argument list (in C++98), suggest the addition of
+        // parentheses so that the code remains well-formed in C++0x.
+        if (!GreaterThanIsOperator && OpToken.is(tok::greatergreater))
+          SuggestParentheses(OpToken.getLocation(),
+                             diag::warn_cxx0x_right_shift_in_template_arg,
+                         SourceRange(Actions.getExprRange(LHS.get()).getBegin(),
+                                     Actions.getExprRange(RHS.get()).getEnd()));
+
+        LHS = Actions.ActOnBinOp(CurScope, OpToken.getLocation(),
+                                 OpToken.getKind(), move(LHS), move(RHS));
+      } else
+        LHS = Actions.ActOnConditionalOp(OpToken.getLocation(), ColonLoc,
+                                         move(LHS), move(TernaryMiddle),
+                                         move(RHS));
+    }
+  }
+}
+
+/// ParseCastExpression - Parse a cast-expression, or, if isUnaryExpression is
+/// true, parse a unary-expression. isAddressOfOperand exists because an
+/// id-expression that is the operand of address-of gets special treatment
+/// due to member pointers.
+///
+Parser::OwningExprResult Parser::ParseCastExpression(bool isUnaryExpression,
+                                                     bool isAddressOfOperand,
+                                                     TypeTy *TypeOfCast) {
+  bool NotCastExpr;
+  OwningExprResult Res = ParseCastExpression(isUnaryExpression,
+                                             isAddressOfOperand,
+                                             NotCastExpr,
+                                             TypeOfCast);
+  if (NotCastExpr)
+    Diag(Tok, diag::err_expected_expression);
+  return move(Res);
+}
+
+/// ParseCastExpression - Parse a cast-expression, or, if isUnaryExpression is
+/// true, parse a unary-expression. isAddressOfOperand exists because an
+/// id-expression that is the operand of address-of gets special treatment
+/// due to member pointers. NotCastExpr is set to true if the token is not the
+/// start of a cast-expression, and no diagnostic is emitted in this case.
+///
+///       cast-expression: [C99 6.5.4]
+///         unary-expression
+///         '(' type-name ')' cast-expression
+///
+///       unary-expression:  [C99 6.5.3]
+///         postfix-expression
+///         '++' unary-expression
+///         '--' unary-expression
+///         unary-operator cast-expression
+///         'sizeof' unary-expression
+///         'sizeof' '(' type-name ')'
+/// [GNU]   '__alignof' unary-expression
+/// [GNU]   '__alignof' '(' type-name ')'
+/// [C++0x] 'alignof' '(' type-id ')'
+/// [GNU]   '&&' identifier
+/// [C++]   new-expression
+/// [C++]   delete-expression
+///
+///       unary-operator: one of
+///         '&'  '*'  '+'  '-'  '~'  '!'
+/// [GNU]   '__extension__'  '__real'  '__imag'
+///
+///       primary-expression: [C99 6.5.1]
+/// [C99]   identifier
+/// [C++]   id-expression
+///         constant
+///         string-literal
+/// [C++]   boolean-literal  [C++ 2.13.5]
+/// [C++0x] 'nullptr'        [C++0x 2.14.7]
+///         '(' expression ')'
+///         '__func__'        [C99 6.4.2.2]
+/// [GNU]   '__FUNCTION__'
+/// [GNU]   '__PRETTY_FUNCTION__'
+/// [GNU]   '(' compound-statement ')'
+/// [GNU]   '__builtin_va_arg' '(' assignment-expression ',' type-name ')'
+/// [GNU]   '__builtin_offsetof' '(' type-name ',' offsetof-member-designator')'
+/// [GNU]   '__builtin_choose_expr' '(' assign-expr ',' assign-expr ','
+///                                     assign-expr ')'
+/// [GNU]   '__builtin_types_compatible_p' '(' type-name ',' type-name ')'
+/// [GNU]   '__null'
+/// [OBJC]  '[' objc-message-expr ']'
+/// [OBJC]  '@selector' '(' objc-selector-arg ')'
+/// [OBJC]  '@protocol' '(' identifier ')'
+/// [OBJC]  '@encode' '(' type-name ')'
+/// [OBJC]  objc-string-literal
+/// [C++]   simple-type-specifier '(' expression-list[opt] ')'      [C++ 5.2.3]
+/// [C++]   typename-specifier '(' expression-list[opt] ')'         [TODO]
+/// [C++]   'const_cast' '<' type-name '>' '(' expression ')'       [C++ 5.2p1]
+/// [C++]   'dynamic_cast' '<' type-name '>' '(' expression ')'     [C++ 5.2p1]
+/// [C++]   'reinterpret_cast' '<' type-name '>' '(' expression ')' [C++ 5.2p1]
+/// [C++]   'static_cast' '<' type-name '>' '(' expression ')'      [C++ 5.2p1]
+/// [C++]   'typeid' '(' expression ')'                             [C++ 5.2p1]
+/// [C++]   'typeid' '(' type-id ')'                                [C++ 5.2p1]
+/// [C++]   'this'          [C++ 9.3.2]
+/// [G++]   unary-type-trait '(' type-id ')'
+/// [G++]   binary-type-trait '(' type-id ',' type-id ')'           [TODO]
+/// [clang] '^' block-literal
+///
+///       constant: [C99 6.4.4]
+///         integer-constant
+///         floating-constant
+///         enumeration-constant -> identifier
+///         character-constant
+///
+///       id-expression: [C++ 5.1]
+///                   unqualified-id
+///                   qualified-id           [TODO]
+///
+///       unqualified-id: [C++ 5.1]
+///                   identifier
+///                   operator-function-id
+///                   conversion-function-id [TODO]
+///                   '~' class-name         [TODO]
+///                   template-id            [TODO]
+///
+///       new-expression: [C++ 5.3.4]
+///                   '::'[opt] 'new' new-placement[opt] new-type-id
+///                                     new-initializer[opt]
+///                   '::'[opt] 'new' new-placement[opt] '(' type-id ')'
+///                                     new-initializer[opt]
+///
+///       delete-expression: [C++ 5.3.5]
+///                   '::'[opt] 'delete' cast-expression
+///                   '::'[opt] 'delete' '[' ']' cast-expression
+///
+/// [GNU] unary-type-trait:
+///                   '__has_nothrow_assign'                  [TODO]
+///                   '__has_nothrow_copy'                    [TODO]
+///                   '__has_nothrow_constructor'             [TODO]
+///                   '__has_trivial_assign'                  [TODO]
+///                   '__has_trivial_copy'                    [TODO]
+///                   '__has_trivial_constructor'
+///                   '__has_trivial_destructor'
+///                   '__has_virtual_destructor'              [TODO]
+///                   '__is_abstract'                         [TODO]
+///                   '__is_class'
+///                   '__is_empty'                            [TODO]
+///                   '__is_enum'
+///                   '__is_pod'
+///                   '__is_polymorphic'
+///                   '__is_union'
+///
+/// [GNU] binary-type-trait:
+///                   '__is_base_of'                          [TODO]
+///
+Parser::OwningExprResult Parser::ParseCastExpression(bool isUnaryExpression,
+                                                     bool isAddressOfOperand,
+                                                     bool &NotCastExpr,
+                                                     TypeTy *TypeOfCast) {
+  OwningExprResult Res(Actions);
+  tok::TokenKind SavedKind = Tok.getKind();
+  NotCastExpr = false;
+
+  // This handles all of cast-expression, unary-expression, postfix-expression,
+  // and primary-expression.  We handle them together like this for efficiency
+  // and to simplify handling of an expression starting with a '(' token: which
+  // may be one of a parenthesized expression, cast-expression, compound literal
+  // expression, or statement expression.
+  //
+  // If the parsed tokens consist of a primary-expression, the cases below
+  // call ParsePostfixExpressionSuffix to handle the postfix expression
+  // suffixes.  Cases that cannot be followed by postfix exprs should
+  // return without invoking ParsePostfixExpressionSuffix.
+  switch (SavedKind) {
+  case tok::l_paren: {
+    // If this expression is limited to being a unary-expression, the parent can
+    // not start a cast expression.
+    ParenParseOption ParenExprType =
+      isUnaryExpression ? CompoundLiteral : CastExpr;
+    TypeTy *CastTy;
+    SourceLocation LParenLoc = Tok.getLocation();
+    SourceLocation RParenLoc;
+    
+    {
+      // The inside of the parens don't need to be a colon protected scope.
+      ColonProtectionRAIIObject X(*this, false);
+    
+      Res = ParseParenExpression(ParenExprType, false/*stopIfCastExr*/,
+                                 TypeOfCast, CastTy, RParenLoc);
+      if (Res.isInvalid()) return move(Res);
+    }
+
+    switch (ParenExprType) {
+    case SimpleExpr:   break;    // Nothing else to do.
+    case CompoundStmt: break;  // Nothing else to do.
+    case CompoundLiteral:
+      // We parsed '(' type-name ')' '{' ... '}'.  If any suffixes of
+      // postfix-expression exist, parse them now.
+      break;
+    case CastExpr:
+      // We have parsed the cast-expression and no postfix-expr pieces are
+      // following.
+      return move(Res);
+    }
+
+    // These can be followed by postfix-expr pieces.
+    return ParsePostfixExpressionSuffix(move(Res));
+  }
+
+    // primary-expression
+  case tok::numeric_constant:
+    // constant: integer-constant
+    // constant: floating-constant
+
+    Res = Actions.ActOnNumericConstant(Tok);
+    ConsumeToken();
+
+    // These can be followed by postfix-expr pieces.
+    return ParsePostfixExpressionSuffix(move(Res));
+
+  case tok::kw_true:
+  case tok::kw_false:
+    return ParseCXXBoolLiteral();
+
+  case tok::kw_nullptr:
+    return Actions.ActOnCXXNullPtrLiteral(ConsumeToken());
+
+  case tok::identifier: {      // primary-expression: identifier
+                               // unqualified-id: identifier
+                               // constant: enumeration-constant
+    // Turn a potentially qualified name into a annot_typename or
+    // annot_cxxscope if it would be valid.  This handles things like x::y, etc.
+    if (getLang().CPlusPlus) {
+      // Avoid the unnecessary parse-time lookup in the common case
+      // where the syntax forbids a type.
+      const Token &Next = NextToken();
+      if (Next.is(tok::coloncolon) ||
+          (!ColonIsSacred && Next.is(tok::colon)) ||
+          Next.is(tok::less) ||
+          Next.is(tok::l_paren)) {
+        // If TryAnnotateTypeOrScopeToken annotates the token, tail recurse.
+        if (TryAnnotateTypeOrScopeToken())
+          return ParseCastExpression(isUnaryExpression, isAddressOfOperand);
+      }
+    }
+
+    // Consume the identifier so that we can see if it is followed by a '(' or
+    // '.'.
+    IdentifierInfo &II = *Tok.getIdentifierInfo();
+    SourceLocation ILoc = ConsumeToken();
+    
+    // Support 'Class.property' notation.  We don't use
+    // isTokObjCMessageIdentifierReceiver(), since it allows 'super' (which is
+    // inappropriate here).
+    if (getLang().ObjC1 && Tok.is(tok::period) &&
+        Actions.getTypeName(II, ILoc, CurScope)) {
+      SourceLocation DotLoc = ConsumeToken();
+      
+      if (Tok.isNot(tok::identifier)) {
+        Diag(Tok, diag::err_expected_property_name);
+        return ExprError();
+      }
+      IdentifierInfo &PropertyName = *Tok.getIdentifierInfo();
+      SourceLocation PropertyLoc = ConsumeToken();
+      
+      Res = Actions.ActOnClassPropertyRefExpr(II, PropertyName,
+                                              ILoc, PropertyLoc);
+      // These can be followed by postfix-expr pieces.
+      return ParsePostfixExpressionSuffix(move(Res));
+    }
+   
+    // Function designators are allowed to be undeclared (C99 6.5.1p2), so we
+    // need to know whether or not this identifier is a function designator or
+    // not.
+    UnqualifiedId Name;
+    CXXScopeSpec ScopeSpec;
+    Name.setIdentifier(&II, ILoc);
+    Res = Actions.ActOnIdExpression(CurScope, ScopeSpec, Name, 
+                                    Tok.is(tok::l_paren), false);
+    // These can be followed by postfix-expr pieces.
+    return ParsePostfixExpressionSuffix(move(Res));
+  }
+  case tok::char_constant:     // constant: character-constant
+    Res = Actions.ActOnCharacterConstant(Tok);
+    ConsumeToken();
+    // These can be followed by postfix-expr pieces.
+    return ParsePostfixExpressionSuffix(move(Res));
+  case tok::kw___func__:       // primary-expression: __func__ [C99 6.4.2.2]
+  case tok::kw___FUNCTION__:   // primary-expression: __FUNCTION__ [GNU]
+  case tok::kw___PRETTY_FUNCTION__:  // primary-expression: __P..Y_F..N__ [GNU]
+    Res = Actions.ActOnPredefinedExpr(Tok.getLocation(), SavedKind);
+    ConsumeToken();
+    // These can be followed by postfix-expr pieces.
+    return ParsePostfixExpressionSuffix(move(Res));
+  case tok::string_literal:    // primary-expression: string-literal
+  case tok::wide_string_literal:
+    Res = ParseStringLiteralExpression();
+    if (Res.isInvalid()) return move(Res);
+    // This can be followed by postfix-expr pieces (e.g. "foo"[1]).
+    return ParsePostfixExpressionSuffix(move(Res));
+  case tok::kw___builtin_va_arg:
+  case tok::kw___builtin_offsetof:
+  case tok::kw___builtin_choose_expr:
+  case tok::kw___builtin_types_compatible_p:
+    return ParseBuiltinPrimaryExpression();
+  case tok::kw___null:
+    return Actions.ActOnGNUNullExpr(ConsumeToken());
+    break;
+  case tok::plusplus:      // unary-expression: '++' unary-expression
+  case tok::minusminus: {  // unary-expression: '--' unary-expression
+    SourceLocation SavedLoc = ConsumeToken();
+    Res = ParseCastExpression(true);
+    if (!Res.isInvalid())
+      Res = Actions.ActOnUnaryOp(CurScope, SavedLoc, SavedKind, move(Res));
+    return move(Res);
+  }
+  case tok::amp: {         // unary-expression: '&' cast-expression
+    // Special treatment because of member pointers
+    SourceLocation SavedLoc = ConsumeToken();
+    Res = ParseCastExpression(false, true);
+    if (!Res.isInvalid())
+      Res = Actions.ActOnUnaryOp(CurScope, SavedLoc, SavedKind, move(Res));
+    return move(Res);
+  }
+
+  case tok::star:          // unary-expression: '*' cast-expression
+  case tok::plus:          // unary-expression: '+' cast-expression
+  case tok::minus:         // unary-expression: '-' cast-expression
+  case tok::tilde:         // unary-expression: '~' cast-expression
+  case tok::exclaim:       // unary-expression: '!' cast-expression
+  case tok::kw___real:     // unary-expression: '__real' cast-expression [GNU]
+  case tok::kw___imag: {   // unary-expression: '__imag' cast-expression [GNU]
+    SourceLocation SavedLoc = ConsumeToken();
+    Res = ParseCastExpression(false);
+    if (!Res.isInvalid())
+      Res = Actions.ActOnUnaryOp(CurScope, SavedLoc, SavedKind, move(Res));
+    return move(Res);
+  }
+
+  case tok::kw___extension__:{//unary-expression:'__extension__' cast-expr [GNU]
+    // __extension__ silences extension warnings in the subexpression.
+    ExtensionRAIIObject O(Diags);  // Use RAII to do this.
+    SourceLocation SavedLoc = ConsumeToken();
+    Res = ParseCastExpression(false);
+    if (!Res.isInvalid())
+      Res = Actions.ActOnUnaryOp(CurScope, SavedLoc, SavedKind, move(Res));
+    return move(Res);
+  }
+  case tok::kw_sizeof:     // unary-expression: 'sizeof' unary-expression
+                           // unary-expression: 'sizeof' '(' type-name ')'
+  case tok::kw_alignof:
+  case tok::kw___alignof:  // unary-expression: '__alignof' unary-expression
+                           // unary-expression: '__alignof' '(' type-name ')'
+                           // unary-expression: 'alignof' '(' type-id ')'
+    return ParseSizeofAlignofExpression();
+  case tok::ampamp: {      // unary-expression: '&&' identifier
+    SourceLocation AmpAmpLoc = ConsumeToken();
+    if (Tok.isNot(tok::identifier))
+      return ExprError(Diag(Tok, diag::err_expected_ident));
+
+    Diag(AmpAmpLoc, diag::ext_gnu_address_of_label);
+    Res = Actions.ActOnAddrLabel(AmpAmpLoc, Tok.getLocation(),
+                                 Tok.getIdentifierInfo());
+    ConsumeToken();
+    return move(Res);
+  }
+  case tok::kw_const_cast:
+  case tok::kw_dynamic_cast:
+  case tok::kw_reinterpret_cast:
+  case tok::kw_static_cast:
+    Res = ParseCXXCasts();
+    // These can be followed by postfix-expr pieces.
+    return ParsePostfixExpressionSuffix(move(Res));
+  case tok::kw_typeid:
+    Res = ParseCXXTypeid();
+    // This can be followed by postfix-expr pieces.
+    return ParsePostfixExpressionSuffix(move(Res));
+  case tok::kw_this:
+    Res = ParseCXXThis();
+    // This can be followed by postfix-expr pieces.
+    return ParsePostfixExpressionSuffix(move(Res));
+
+  case tok::kw_char:
+  case tok::kw_wchar_t:
+  case tok::kw_char16_t:
+  case tok::kw_char32_t:
+  case tok::kw_bool:
+  case tok::kw_short:
+  case tok::kw_int:
+  case tok::kw_long:
+  case tok::kw_signed:
+  case tok::kw_unsigned:
+  case tok::kw_float:
+  case tok::kw_double:
+  case tok::kw_void:
+  case tok::kw_typename:
+  case tok::kw_typeof:
+  case tok::kw___vector:
+  case tok::annot_typename: {
+    if (!getLang().CPlusPlus) {
+      Diag(Tok, diag::err_expected_expression);
+      return ExprError();
+    }
+
+    if (SavedKind == tok::kw_typename) {
+      // postfix-expression: typename-specifier '(' expression-list[opt] ')'
+      if (!TryAnnotateTypeOrScopeToken())
+        return ExprError();
+    }
+
+    // postfix-expression: simple-type-specifier '(' expression-list[opt] ')'
+    //
+    DeclSpec DS;
+    ParseCXXSimpleTypeSpecifier(DS);
+    if (Tok.isNot(tok::l_paren))
+      return ExprError(Diag(Tok, diag::err_expected_lparen_after_type)
+                         << DS.getSourceRange());
+
+    Res = ParseCXXTypeConstructExpression(DS);
+    // This can be followed by postfix-expr pieces.
+    return ParsePostfixExpressionSuffix(move(Res));
+  }
+
+  case tok::annot_cxxscope: { // [C++] id-expression: qualified-id
+    Token Next = NextToken();
+    if (Next.is(tok::annot_template_id)) {
+      TemplateIdAnnotation *TemplateId
+        = static_cast<TemplateIdAnnotation *>(Next.getAnnotationValue());
+      if (TemplateId->Kind == TNK_Type_template) {
+        // We have a qualified template-id that we know refers to a
+        // type, translate it into a type and continue parsing as a
+        // cast expression.
+        CXXScopeSpec SS;
+        ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/0, false);
+        AnnotateTemplateIdTokenAsType(&SS);
+        return ParseCastExpression(isUnaryExpression, isAddressOfOperand,
+                                   NotCastExpr, TypeOfCast);
+      }
+    }
+
+    // Parse as an id-expression.
+    Res = ParseCXXIdExpression(isAddressOfOperand);
+    return ParsePostfixExpressionSuffix(move(Res));
+  }
+
+  case tok::annot_template_id: { // [C++]          template-id
+    TemplateIdAnnotation *TemplateId
+      = static_cast<TemplateIdAnnotation *>(Tok.getAnnotationValue());
+    if (TemplateId->Kind == TNK_Type_template) {
+      // We have a template-id that we know refers to a type,
+      // translate it into a type and continue parsing as a cast
+      // expression.
+      AnnotateTemplateIdTokenAsType();
+      return ParseCastExpression(isUnaryExpression, isAddressOfOperand,
+                                 NotCastExpr, TypeOfCast);
+    }
+
+    // Fall through to treat the template-id as an id-expression.
+  }
+
+  case tok::kw_operator: // [C++] id-expression: operator/conversion-function-id
+    Res = ParseCXXIdExpression(isAddressOfOperand);
+    return ParsePostfixExpressionSuffix(move(Res));
+
+  case tok::coloncolon: {
+    // ::foo::bar -> global qualified name etc.   If TryAnnotateTypeOrScopeToken
+    // annotates the token, tail recurse.
+    if (TryAnnotateTypeOrScopeToken())
+      return ParseCastExpression(isUnaryExpression, isAddressOfOperand);
+
+    // ::new -> [C++] new-expression
+    // ::delete -> [C++] delete-expression
+    SourceLocation CCLoc = ConsumeToken();
+    if (Tok.is(tok::kw_new))
+      return ParseCXXNewExpression(true, CCLoc);
+    if (Tok.is(tok::kw_delete))
+      return ParseCXXDeleteExpression(true, CCLoc);
+
+    // This is not a type name or scope specifier, it is an invalid expression.
+    Diag(CCLoc, diag::err_expected_expression);
+    return ExprError();
+  }
+
+  case tok::kw_new: // [C++] new-expression
+    return ParseCXXNewExpression(false, Tok.getLocation());
+
+  case tok::kw_delete: // [C++] delete-expression
+    return ParseCXXDeleteExpression(false, Tok.getLocation());
+
+  case tok::kw___is_pod: // [GNU] unary-type-trait
+  case tok::kw___is_class:
+  case tok::kw___is_enum:
+  case tok::kw___is_union:
+  case tok::kw___is_empty:
+  case tok::kw___is_polymorphic:
+  case tok::kw___is_abstract:
+  case tok::kw___is_literal:
+  case tok::kw___has_trivial_constructor:
+  case tok::kw___has_trivial_copy:
+  case tok::kw___has_trivial_assign:
+  case tok::kw___has_trivial_destructor:
+    return ParseUnaryTypeTrait();
+
+  case tok::at: {
+    SourceLocation AtLoc = ConsumeToken();
+    return ParseObjCAtExpression(AtLoc);
+  }
+  case tok::caret:
+    return ParsePostfixExpressionSuffix(ParseBlockLiteralExpression());
+  case tok::l_square:
+    // These can be followed by postfix-expr pieces.
+    if (getLang().ObjC1)
+      return ParsePostfixExpressionSuffix(ParseObjCMessageExpression());
+    // FALL THROUGH.
+  default:
+    NotCastExpr = true;
+    return ExprError();
+  }
+
+  // unreachable.
+  abort();
+}
+
+/// ParsePostfixExpressionSuffix - Once the leading part of a postfix-expression
+/// is parsed, this method parses any suffixes that apply.
+///
+///       postfix-expression: [C99 6.5.2]
+///         primary-expression
+///         postfix-expression '[' expression ']'
+///         postfix-expression '(' argument-expression-list[opt] ')'
+///         postfix-expression '.' identifier
+///         postfix-expression '->' identifier
+///         postfix-expression '++'
+///         postfix-expression '--'
+///         '(' type-name ')' '{' initializer-list '}'
+///         '(' type-name ')' '{' initializer-list ',' '}'
+///
+///       argument-expression-list: [C99 6.5.2]
+///         argument-expression
+///         argument-expression-list ',' assignment-expression
+///
+Parser::OwningExprResult
+Parser::ParsePostfixExpressionSuffix(OwningExprResult LHS) {
+  // Now that the primary-expression piece of the postfix-expression has been
+  // parsed, see if there are any postfix-expression pieces here.
+  SourceLocation Loc;
+  while (1) {
+    switch (Tok.getKind()) {
+    default:  // Not a postfix-expression suffix.
+      return move(LHS);
+    case tok::l_square: {  // postfix-expression: p-e '[' expression ']'
+      Loc = ConsumeBracket();
+      OwningExprResult Idx(ParseExpression());
+
+      SourceLocation RLoc = Tok.getLocation();
+
+      if (!LHS.isInvalid() && !Idx.isInvalid() && Tok.is(tok::r_square)) {
+        LHS = Actions.ActOnArraySubscriptExpr(CurScope, move(LHS), Loc,
+                                              move(Idx), RLoc);
+      } else
+        LHS = ExprError();
+
+      // Match the ']'.
+      MatchRHSPunctuation(tok::r_square, Loc);
+      break;
+    }
+
+    case tok::l_paren: {   // p-e: p-e '(' argument-expression-list[opt] ')'
+      ExprVector ArgExprs(Actions);
+      CommaLocsTy CommaLocs;
+
+      Loc = ConsumeParen();
+
+      if (Tok.is(tok::code_completion)) {
+        Actions.CodeCompleteCall(CurScope, LHS.get(), 0, 0);
+        ConsumeToken();
+      }
+      
+      if (Tok.isNot(tok::r_paren)) {
+        if (ParseExpressionList(ArgExprs, CommaLocs, &Action::CodeCompleteCall,
+                                LHS.get())) {
+          SkipUntil(tok::r_paren);
+          return ExprError();
+        }
+      }
+
+      // Match the ')'.
+      if (Tok.isNot(tok::r_paren)) {
+        MatchRHSPunctuation(tok::r_paren, Loc);
+        return ExprError();
+      }
+
+      if (!LHS.isInvalid()) {
+        assert((ArgExprs.size() == 0 || ArgExprs.size()-1 == CommaLocs.size())&&
+               "Unexpected number of commas!");
+        LHS = Actions.ActOnCallExpr(CurScope, move(LHS), Loc,
+                                    move_arg(ArgExprs), CommaLocs.data(),
+                                    Tok.getLocation());
+      }
+
+      ConsumeParen();
+      break;
+    }
+    case tok::arrow:
+    case tok::period: {
+      // postfix-expression: p-e '->' template[opt] id-expression
+      // postfix-expression: p-e '.' template[opt] id-expression
+      tok::TokenKind OpKind = Tok.getKind();
+      SourceLocation OpLoc = ConsumeToken();  // Eat the "." or "->" token.
+
+      CXXScopeSpec SS;
+      Action::TypeTy *ObjectType = 0;
+      if (getLang().CPlusPlus && !LHS.isInvalid()) {
+        LHS = Actions.ActOnStartCXXMemberReference(CurScope, move(LHS),
+                                                   OpLoc, OpKind, ObjectType);
+        if (LHS.isInvalid())
+          break;
+        ParseOptionalCXXScopeSpecifier(SS, ObjectType, false);
+      }
+
+      if (Tok.is(tok::code_completion)) {
+        // Code completion for a member access expression.
+        Actions.CodeCompleteMemberReferenceExpr(CurScope, LHS.get(),
+                                                OpLoc, OpKind == tok::arrow);
+        
+        ConsumeToken();
+      }
+      
+      UnqualifiedId Name;
+      if (ParseUnqualifiedId(SS, 
+                             /*EnteringContext=*/false, 
+                             /*AllowDestructorName=*/true,
+                             /*AllowConstructorName=*/false, 
+                             ObjectType,
+                             Name))
+        return ExprError();
+      
+      if (!LHS.isInvalid())
+        LHS = Actions.ActOnMemberAccessExpr(CurScope, move(LHS), OpLoc, OpKind,
+                                            SS, Name, ObjCImpDecl,
+                                            Tok.is(tok::l_paren));
+      
+      break;
+    }
+    case tok::plusplus:    // postfix-expression: postfix-expression '++'
+    case tok::minusminus:  // postfix-expression: postfix-expression '--'
+      if (!LHS.isInvalid()) {
+        LHS = Actions.ActOnPostfixUnaryOp(CurScope, Tok.getLocation(),
+                                          Tok.getKind(), move(LHS));
+      }
+      ConsumeToken();
+      break;
+    }
+  }
+}
+
+/// ParseExprAfterTypeofSizeofAlignof - We parsed a typeof/sizeof/alignof and
+/// we are at the start of an expression or a parenthesized type-id.
+/// OpTok is the operand token (typeof/sizeof/alignof). Returns the expression
+/// (isCastExpr == false) or the type (isCastExpr == true).
+///
+///       unary-expression:  [C99 6.5.3]
+///         'sizeof' unary-expression
+///         'sizeof' '(' type-name ')'
+/// [GNU]   '__alignof' unary-expression
+/// [GNU]   '__alignof' '(' type-name ')'
+/// [C++0x] 'alignof' '(' type-id ')'
+///
+/// [GNU]   typeof-specifier:
+///           typeof ( expressions )
+///           typeof ( type-name )
+/// [GNU/C++] typeof unary-expression
+///
+Parser::OwningExprResult
+Parser::ParseExprAfterTypeofSizeofAlignof(const Token &OpTok,
+                                          bool &isCastExpr,
+                                          TypeTy *&CastTy,
+                                          SourceRange &CastRange) {
+
+  assert((OpTok.is(tok::kw_typeof)    || OpTok.is(tok::kw_sizeof) ||
+          OpTok.is(tok::kw___alignof) || OpTok.is(tok::kw_alignof)) &&
+          "Not a typeof/sizeof/alignof expression!");
+
+  OwningExprResult Operand(Actions);
+
+  // If the operand doesn't start with an '(', it must be an expression.
+  if (Tok.isNot(tok::l_paren)) {
+    isCastExpr = false;
+    if (OpTok.is(tok::kw_typeof) && !getLang().CPlusPlus) {
+      Diag(Tok,diag::err_expected_lparen_after_id) << OpTok.getIdentifierInfo();
+      return ExprError();
+    }
+
+    // C++0x [expr.sizeof]p1:
+    //   [...] The operand is either an expression, which is an unevaluated
+    //   operand (Clause 5) [...]
+    //
+    // The GNU typeof and alignof extensions also behave as unevaluated
+    // operands.
+    EnterExpressionEvaluationContext Unevaluated(Actions,
+                                                 Action::Unevaluated);
+    Operand = ParseCastExpression(true/*isUnaryExpression*/);
+  } else {
+    // If it starts with a '(', we know that it is either a parenthesized
+    // type-name, or it is a unary-expression that starts with a compound
+    // literal, or starts with a primary-expression that is a parenthesized
+    // expression.
+    ParenParseOption ExprType = CastExpr;
+    SourceLocation LParenLoc = Tok.getLocation(), RParenLoc;
+
+    // C++0x [expr.sizeof]p1:
+    //   [...] The operand is either an expression, which is an unevaluated
+    //   operand (Clause 5) [...]
+    //
+    // The GNU typeof and alignof extensions also behave as unevaluated
+    // operands.
+    EnterExpressionEvaluationContext Unevaluated(Actions,
+                                                 Action::Unevaluated);
+    Operand = ParseParenExpression(ExprType, true/*stopIfCastExpr*/, 
+                                   0/*TypeOfCast*/,
+                                   CastTy, RParenLoc);
+    CastRange = SourceRange(LParenLoc, RParenLoc);
+
+    // If ParseParenExpression parsed a '(typename)' sequence only, then this is
+    // a type.
+    if (ExprType == CastExpr) {
+      isCastExpr = true;
+      return ExprEmpty();
+    }
+
+    // If this is a parenthesized expression, it is the start of a
+    // unary-expression, but doesn't include any postfix pieces.  Parse these
+    // now if present.
+    Operand = ParsePostfixExpressionSuffix(move(Operand));
+  }
+
+  // If we get here, the operand to the typeof/sizeof/alignof was an expresion.
+  isCastExpr = false;
+  return move(Operand);
+}
+
+
+/// ParseSizeofAlignofExpression - Parse a sizeof or alignof expression.
+///       unary-expression:  [C99 6.5.3]
+///         'sizeof' unary-expression
+///         'sizeof' '(' type-name ')'
+/// [GNU]   '__alignof' unary-expression
+/// [GNU]   '__alignof' '(' type-name ')'
+/// [C++0x] 'alignof' '(' type-id ')'
+Parser::OwningExprResult Parser::ParseSizeofAlignofExpression() {
+  assert((Tok.is(tok::kw_sizeof) || Tok.is(tok::kw___alignof)
+          || Tok.is(tok::kw_alignof)) &&
+         "Not a sizeof/alignof expression!");
+  Token OpTok = Tok;
+  ConsumeToken();
+
+  bool isCastExpr;
+  TypeTy *CastTy;
+  SourceRange CastRange;
+  OwningExprResult Operand = ParseExprAfterTypeofSizeofAlignof(OpTok,
+                                                               isCastExpr,
+                                                               CastTy,
+                                                               CastRange);
+
+  if (isCastExpr)
+    return Actions.ActOnSizeOfAlignOfExpr(OpTok.getLocation(),
+                                          OpTok.is(tok::kw_sizeof),
+                                          /*isType=*/true, CastTy,
+                                          CastRange);
+
+  // If we get here, the operand to the sizeof/alignof was an expresion.
+  if (!Operand.isInvalid())
+    Operand = Actions.ActOnSizeOfAlignOfExpr(OpTok.getLocation(),
+                                             OpTok.is(tok::kw_sizeof),
+                                             /*isType=*/false,
+                                             Operand.release(), CastRange);
+  return move(Operand);
+}
+
+/// ParseBuiltinPrimaryExpression
+///
+///       primary-expression: [C99 6.5.1]
+/// [GNU]   '__builtin_va_arg' '(' assignment-expression ',' type-name ')'
+/// [GNU]   '__builtin_offsetof' '(' type-name ',' offsetof-member-designator')'
+/// [GNU]   '__builtin_choose_expr' '(' assign-expr ',' assign-expr ','
+///                                     assign-expr ')'
+/// [GNU]   '__builtin_types_compatible_p' '(' type-name ',' type-name ')'
+///
+/// [GNU] offsetof-member-designator:
+/// [GNU]   identifier
+/// [GNU]   offsetof-member-designator '.' identifier
+/// [GNU]   offsetof-member-designator '[' expression ']'
+///
+Parser::OwningExprResult Parser::ParseBuiltinPrimaryExpression() {
+  OwningExprResult Res(Actions);
+  const IdentifierInfo *BuiltinII = Tok.getIdentifierInfo();
+
+  tok::TokenKind T = Tok.getKind();
+  SourceLocation StartLoc = ConsumeToken();   // Eat the builtin identifier.
+
+  // All of these start with an open paren.
+  if (Tok.isNot(tok::l_paren))
+    return ExprError(Diag(Tok, diag::err_expected_lparen_after_id)
+                       << BuiltinII);
+
+  SourceLocation LParenLoc = ConsumeParen();
+  // TODO: Build AST.
+
+  switch (T) {
+  default: assert(0 && "Not a builtin primary expression!");
+  case tok::kw___builtin_va_arg: {
+    OwningExprResult Expr(ParseAssignmentExpression());
+    if (Expr.isInvalid()) {
+      SkipUntil(tok::r_paren);
+      return ExprError();
+    }
+
+    if (ExpectAndConsume(tok::comma, diag::err_expected_comma, "",tok::r_paren))
+      return ExprError();
+
+    TypeResult Ty = ParseTypeName();
+
+    if (Tok.isNot(tok::r_paren)) {
+      Diag(Tok, diag::err_expected_rparen);
+      return ExprError();
+    }
+    if (Ty.isInvalid())
+      Res = ExprError();
+    else
+      Res = Actions.ActOnVAArg(StartLoc, move(Expr), Ty.get(), ConsumeParen());
+    break;
+  }
+  case tok::kw___builtin_offsetof: {
+    SourceLocation TypeLoc = Tok.getLocation();
+    TypeResult Ty = ParseTypeName();
+    if (Ty.isInvalid()) {
+      SkipUntil(tok::r_paren);
+      return ExprError();
+    }
+
+    if (ExpectAndConsume(tok::comma, diag::err_expected_comma, "",tok::r_paren))
+      return ExprError();
+
+    // We must have at least one identifier here.
+    if (Tok.isNot(tok::identifier)) {
+      Diag(Tok, diag::err_expected_ident);
+      SkipUntil(tok::r_paren);
+      return ExprError();
+    }
+
+    // Keep track of the various subcomponents we see.
+    llvm::SmallVector<Action::OffsetOfComponent, 4> Comps;
+
+    Comps.push_back(Action::OffsetOfComponent());
+    Comps.back().isBrackets = false;
+    Comps.back().U.IdentInfo = Tok.getIdentifierInfo();
+    Comps.back().LocStart = Comps.back().LocEnd = ConsumeToken();
+
+    // FIXME: This loop leaks the index expressions on error.
+    while (1) {
+      if (Tok.is(tok::period)) {
+        // offsetof-member-designator: offsetof-member-designator '.' identifier
+        Comps.push_back(Action::OffsetOfComponent());
+        Comps.back().isBrackets = false;
+        Comps.back().LocStart = ConsumeToken();
+
+        if (Tok.isNot(tok::identifier)) {
+          Diag(Tok, diag::err_expected_ident);
+          SkipUntil(tok::r_paren);
+          return ExprError();
+        }
+        Comps.back().U.IdentInfo = Tok.getIdentifierInfo();
+        Comps.back().LocEnd = ConsumeToken();
+
+      } else if (Tok.is(tok::l_square)) {
+        // offsetof-member-designator: offsetof-member-design '[' expression ']'
+        Comps.push_back(Action::OffsetOfComponent());
+        Comps.back().isBrackets = true;
+        Comps.back().LocStart = ConsumeBracket();
+        Res = ParseExpression();
+        if (Res.isInvalid()) {
+          SkipUntil(tok::r_paren);
+          return move(Res);
+        }
+        Comps.back().U.E = Res.release();
+
+        Comps.back().LocEnd =
+          MatchRHSPunctuation(tok::r_square, Comps.back().LocStart);
+      } else {
+        if (Tok.isNot(tok::r_paren)) {
+          MatchRHSPunctuation(tok::r_paren, LParenLoc);
+          Res = ExprError();
+        } else if (Ty.isInvalid()) {
+          Res = ExprError();
+        } else {
+          Res = Actions.ActOnBuiltinOffsetOf(CurScope, StartLoc, TypeLoc,
+                                             Ty.get(), &Comps[0],
+                                             Comps.size(), ConsumeParen());
+        }
+        break;
+      }
+    }
+    break;
+  }
+  case tok::kw___builtin_choose_expr: {
+    OwningExprResult Cond(ParseAssignmentExpression());
+    if (Cond.isInvalid()) {
+      SkipUntil(tok::r_paren);
+      return move(Cond);
+    }
+    if (ExpectAndConsume(tok::comma, diag::err_expected_comma, "",tok::r_paren))
+      return ExprError();
+
+    OwningExprResult Expr1(ParseAssignmentExpression());
+    if (Expr1.isInvalid()) {
+      SkipUntil(tok::r_paren);
+      return move(Expr1);
+    }
+    if (ExpectAndConsume(tok::comma, diag::err_expected_comma, "",tok::r_paren))
+      return ExprError();
+
+    OwningExprResult Expr2(ParseAssignmentExpression());
+    if (Expr2.isInvalid()) {
+      SkipUntil(tok::r_paren);
+      return move(Expr2);
+    }
+    if (Tok.isNot(tok::r_paren)) {
+      Diag(Tok, diag::err_expected_rparen);
+      return ExprError();
+    }
+    Res = Actions.ActOnChooseExpr(StartLoc, move(Cond), move(Expr1),
+                                  move(Expr2), ConsumeParen());
+    break;
+  }
+  case tok::kw___builtin_types_compatible_p:
+    TypeResult Ty1 = ParseTypeName();
+
+    if (ExpectAndConsume(tok::comma, diag::err_expected_comma, "",tok::r_paren))
+      return ExprError();
+
+    TypeResult Ty2 = ParseTypeName();
+
+    if (Tok.isNot(tok::r_paren)) {
+      Diag(Tok, diag::err_expected_rparen);
+      return ExprError();
+    }
+
+    if (Ty1.isInvalid() || Ty2.isInvalid())
+      Res = ExprError();
+    else
+      Res = Actions.ActOnTypesCompatibleExpr(StartLoc, Ty1.get(), Ty2.get(),
+                                             ConsumeParen());
+    break;
+  }
+
+  // These can be followed by postfix-expr pieces because they are
+  // primary-expressions.
+  return ParsePostfixExpressionSuffix(move(Res));
+}
+
+/// ParseParenExpression - This parses the unit that starts with a '(' token,
+/// based on what is allowed by ExprType.  The actual thing parsed is returned
+/// in ExprType. If stopIfCastExpr is true, it will only return the parsed type,
+/// not the parsed cast-expression.
+///
+///       primary-expression: [C99 6.5.1]
+///         '(' expression ')'
+/// [GNU]   '(' compound-statement ')'      (if !ParenExprOnly)
+///       postfix-expression: [C99 6.5.2]
+///         '(' type-name ')' '{' initializer-list '}'
+///         '(' type-name ')' '{' initializer-list ',' '}'
+///       cast-expression: [C99 6.5.4]
+///         '(' type-name ')' cast-expression
+///
+Parser::OwningExprResult
+Parser::ParseParenExpression(ParenParseOption &ExprType, bool stopIfCastExpr,
+                             TypeTy *TypeOfCast, TypeTy *&CastTy,
+                             SourceLocation &RParenLoc) {
+  assert(Tok.is(tok::l_paren) && "Not a paren expr!");
+  GreaterThanIsOperatorScope G(GreaterThanIsOperator, true);
+  SourceLocation OpenLoc = ConsumeParen();
+  OwningExprResult Result(Actions, true);
+  bool isAmbiguousTypeId;
+  CastTy = 0;
+
+  if (ExprType >= CompoundStmt && Tok.is(tok::l_brace)) {
+    Diag(Tok, diag::ext_gnu_statement_expr);
+    OwningStmtResult Stmt(ParseCompoundStatement(0, true));
+    ExprType = CompoundStmt;
+
+    // If the substmt parsed correctly, build the AST node.
+    if (!Stmt.isInvalid() && Tok.is(tok::r_paren))
+      Result = Actions.ActOnStmtExpr(OpenLoc, move(Stmt), Tok.getLocation());
+
+  } else if (ExprType >= CompoundLiteral &&
+             isTypeIdInParens(isAmbiguousTypeId)) {
+
+    // Otherwise, this is a compound literal expression or cast expression.
+
+    // In C++, if the type-id is ambiguous we disambiguate based on context.
+    // If stopIfCastExpr is true the context is a typeof/sizeof/alignof
+    // in which case we should treat it as type-id.
+    // if stopIfCastExpr is false, we need to determine the context past the
+    // parens, so we defer to ParseCXXAmbiguousParenExpression for that.
+    if (isAmbiguousTypeId && !stopIfCastExpr)
+      return ParseCXXAmbiguousParenExpression(ExprType, CastTy,
+                                              OpenLoc, RParenLoc);
+
+    TypeResult Ty = ParseTypeName();
+
+    // Match the ')'.
+    if (Tok.is(tok::r_paren))
+      RParenLoc = ConsumeParen();
+    else
+      MatchRHSPunctuation(tok::r_paren, OpenLoc);
+
+    if (Tok.is(tok::l_brace)) {
+      ExprType = CompoundLiteral;
+      return ParseCompoundLiteralExpression(Ty.get(), OpenLoc, RParenLoc);
+    }
+
+    if (ExprType == CastExpr) {
+      // We parsed '(' type-name ')' and the thing after it wasn't a '{'.
+
+      if (Ty.isInvalid())
+        return ExprError();
+
+      CastTy = Ty.get();
+
+      if (stopIfCastExpr) {
+        // Note that this doesn't parse the subsequent cast-expression, it just
+        // returns the parsed type to the callee.
+        return OwningExprResult(Actions);
+      }
+
+      // Parse the cast-expression that follows it next.
+      // TODO: For cast expression with CastTy.
+      Result = ParseCastExpression(false, false, CastTy);
+      if (!Result.isInvalid())
+        Result = Actions.ActOnCastExpr(CurScope, OpenLoc, CastTy, RParenLoc,
+                                       move(Result));
+      return move(Result);
+    }
+
+    Diag(Tok, diag::err_expected_lbrace_in_compound_literal);
+    return ExprError();
+  } else if (TypeOfCast) {
+    // Parse the expression-list.
+    ExprVector ArgExprs(Actions);
+    CommaLocsTy CommaLocs;
+
+    if (!ParseExpressionList(ArgExprs, CommaLocs)) {
+      ExprType = SimpleExpr;
+      Result = Actions.ActOnParenOrParenListExpr(OpenLoc, Tok.getLocation(),
+                                          move_arg(ArgExprs), TypeOfCast);
+    }
+  } else {
+    Result = ParseExpression();
+    ExprType = SimpleExpr;
+    if (!Result.isInvalid() && Tok.is(tok::r_paren))
+      Result = Actions.ActOnParenExpr(OpenLoc, Tok.getLocation(), move(Result));
+  }
+
+  // Match the ')'.
+  if (Result.isInvalid()) {
+    SkipUntil(tok::r_paren);
+    return ExprError();
+  }
+
+  if (Tok.is(tok::r_paren))
+    RParenLoc = ConsumeParen();
+  else
+    MatchRHSPunctuation(tok::r_paren, OpenLoc);
+
+  return move(Result);
+}
+
+/// ParseCompoundLiteralExpression - We have parsed the parenthesized type-name
+/// and we are at the left brace.
+///
+///       postfix-expression: [C99 6.5.2]
+///         '(' type-name ')' '{' initializer-list '}'
+///         '(' type-name ')' '{' initializer-list ',' '}'
+///
+Parser::OwningExprResult
+Parser::ParseCompoundLiteralExpression(TypeTy *Ty,
+                                       SourceLocation LParenLoc,
+                                       SourceLocation RParenLoc) {
+  assert(Tok.is(tok::l_brace) && "Not a compound literal!");
+  if (!getLang().C99)   // Compound literals don't exist in C90.
+    Diag(LParenLoc, diag::ext_c99_compound_literal);
+  OwningExprResult Result = ParseInitializer();
+  if (!Result.isInvalid() && Ty)
+    return Actions.ActOnCompoundLiteral(LParenLoc, Ty, RParenLoc, move(Result));
+  return move(Result);
+}
+
+/// ParseStringLiteralExpression - This handles the various token types that
+/// form string literals, and also handles string concatenation [C99 5.1.1.2,
+/// translation phase #6].
+///
+///       primary-expression: [C99 6.5.1]
+///         string-literal
+Parser::OwningExprResult Parser::ParseStringLiteralExpression() {
+  assert(isTokenStringLiteral() && "Not a string literal!");
+
+  // String concat.  Note that keywords like __func__ and __FUNCTION__ are not
+  // considered to be strings for concatenation purposes.
+  llvm::SmallVector<Token, 4> StringToks;
+
+  do {
+    StringToks.push_back(Tok);
+    ConsumeStringToken();
+  } while (isTokenStringLiteral());
+
+  // Pass the set of string tokens, ready for concatenation, to the actions.
+  return Actions.ActOnStringLiteral(&StringToks[0], StringToks.size());
+}
+
+/// ParseExpressionList - Used for C/C++ (argument-)expression-list.
+///
+///       argument-expression-list:
+///         assignment-expression
+///         argument-expression-list , assignment-expression
+///
+/// [C++] expression-list:
+/// [C++]   assignment-expression
+/// [C++]   expression-list , assignment-expression
+///
+bool Parser::ParseExpressionList(ExprListTy &Exprs, CommaLocsTy &CommaLocs,
+                                 void (Action::*Completer)(Scope *S, 
+                                                           void *Data,
+                                                           ExprTy **Args,
+                                                           unsigned NumArgs),
+                                 void *Data) {
+  while (1) {
+    if (Tok.is(tok::code_completion)) {
+      if (Completer)
+        (Actions.*Completer)(CurScope, Data, Exprs.data(), Exprs.size());
+      ConsumeToken();
+    }
+    
+    OwningExprResult Expr(ParseAssignmentExpression());
+    if (Expr.isInvalid())
+      return true;
+
+    Exprs.push_back(Expr.release());
+
+    if (Tok.isNot(tok::comma))
+      return false;
+    // Move to the next argument, remember where the comma was.
+    CommaLocs.push_back(ConsumeToken());
+  }
+}
+
+/// ParseBlockId - Parse a block-id, which roughly looks like int (int x).
+///
+/// [clang] block-id:
+/// [clang]   specifier-qualifier-list block-declarator
+///
+void Parser::ParseBlockId() {
+  // Parse the specifier-qualifier-list piece.
+  DeclSpec DS;
+  ParseSpecifierQualifierList(DS);
+
+  // Parse the block-declarator.
+  Declarator DeclaratorInfo(DS, Declarator::BlockLiteralContext);
+  ParseDeclarator(DeclaratorInfo);
+
+  // We do this for: ^ __attribute__((noreturn)) {, as DS has the attributes.
+  DeclaratorInfo.AddAttributes(DS.TakeAttributes(),
+                               SourceLocation());
+
+  if (Tok.is(tok::kw___attribute)) {
+    SourceLocation Loc;
+    AttributeList *AttrList = ParseGNUAttributes(&Loc);
+    DeclaratorInfo.AddAttributes(AttrList, Loc);
+  }
+
+  // Inform sema that we are starting a block.
+  Actions.ActOnBlockArguments(DeclaratorInfo, CurScope);
+}
+
+/// ParseBlockLiteralExpression - Parse a block literal, which roughly looks
+/// like ^(int x){ return x+1; }
+///
+///         block-literal:
+/// [clang]   '^' block-args[opt] compound-statement
+/// [clang]   '^' block-id compound-statement
+/// [clang] block-args:
+/// [clang]   '(' parameter-list ')'
+///
+Parser::OwningExprResult Parser::ParseBlockLiteralExpression() {
+  assert(Tok.is(tok::caret) && "block literal starts with ^");
+  SourceLocation CaretLoc = ConsumeToken();
+
+  PrettyStackTraceLoc CrashInfo(PP.getSourceManager(), CaretLoc,
+                                "block literal parsing");
+
+  // Enter a scope to hold everything within the block.  This includes the
+  // argument decls, decls within the compound expression, etc.  This also
+  // allows determining whether a variable reference inside the block is
+  // within or outside of the block.
+  ParseScope BlockScope(this, Scope::BlockScope | Scope::FnScope |
+                              Scope::BreakScope | Scope::ContinueScope |
+                              Scope::DeclScope);
+
+  // Inform sema that we are starting a block.
+  Actions.ActOnBlockStart(CaretLoc, CurScope);
+
+  // Parse the return type if present.
+  DeclSpec DS;
+  Declarator ParamInfo(DS, Declarator::BlockLiteralContext);
+  // FIXME: Since the return type isn't actually parsed, it can't be used to
+  // fill ParamInfo with an initial valid range, so do it manually.
+  ParamInfo.SetSourceRange(SourceRange(Tok.getLocation(), Tok.getLocation()));
+
+  // If this block has arguments, parse them.  There is no ambiguity here with
+  // the expression case, because the expression case requires a parameter list.
+  if (Tok.is(tok::l_paren)) {
+    ParseParenDeclarator(ParamInfo);
+    // Parse the pieces after the identifier as if we had "int(...)".
+    // SetIdentifier sets the source range end, but in this case we're past
+    // that location.
+    SourceLocation Tmp = ParamInfo.getSourceRange().getEnd();
+    ParamInfo.SetIdentifier(0, CaretLoc);
+    ParamInfo.SetRangeEnd(Tmp);
+    if (ParamInfo.isInvalidType()) {
+      // If there was an error parsing the arguments, they may have
+      // tried to use ^(x+y) which requires an argument list.  Just
+      // skip the whole block literal.
+      Actions.ActOnBlockError(CaretLoc, CurScope);
+      return ExprError();
+    }
+
+    if (Tok.is(tok::kw___attribute)) {
+      SourceLocation Loc;
+      AttributeList *AttrList = ParseGNUAttributes(&Loc);
+      ParamInfo.AddAttributes(AttrList, Loc);
+    }
+
+    // Inform sema that we are starting a block.
+    Actions.ActOnBlockArguments(ParamInfo, CurScope);
+  } else if (!Tok.is(tok::l_brace)) {
+    ParseBlockId();
+  } else {
+    // Otherwise, pretend we saw (void).
+    ParamInfo.AddTypeInfo(DeclaratorChunk::getFunction(true, false,
+                                                       SourceLocation(),
+                                                       0, 0, 0,
+                                                       false, SourceLocation(),
+                                                       false, 0, 0, 0,
+                                                       CaretLoc, CaretLoc,
+                                                       ParamInfo),
+                          CaretLoc);
+
+    if (Tok.is(tok::kw___attribute)) {
+      SourceLocation Loc;
+      AttributeList *AttrList = ParseGNUAttributes(&Loc);
+      ParamInfo.AddAttributes(AttrList, Loc);
+    }
+
+    // Inform sema that we are starting a block.
+    Actions.ActOnBlockArguments(ParamInfo, CurScope);
+  }
+
+
+  OwningExprResult Result(Actions, true);
+  if (!Tok.is(tok::l_brace)) {
+    // Saw something like: ^expr
+    Diag(Tok, diag::err_expected_expression);
+    Actions.ActOnBlockError(CaretLoc, CurScope);
+    return ExprError();
+  }
+
+  OwningStmtResult Stmt(ParseCompoundStatementBody());
+  if (!Stmt.isInvalid())
+    Result = Actions.ActOnBlockStmtExpr(CaretLoc, move(Stmt), CurScope);
+  else
+    Actions.ActOnBlockError(CaretLoc, CurScope);
+  return move(Result);
+}
diff --git a/lib/Parse/ParseExprCXX.cpp b/lib/Parse/ParseExprCXX.cpp
new file mode 100644
index 0000000..0dbe1ea
--- /dev/null
+++ b/lib/Parse/ParseExprCXX.cpp
@@ -0,0 +1,1682 @@
+//===--- ParseExprCXX.cpp - C++ Expression Parsing ------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the Expression parsing implementation for C++.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Parse/ParseDiagnostic.h"
+#include "clang/Parse/Parser.h"
+#include "clang/Parse/DeclSpec.h"
+#include "clang/Parse/Template.h"
+#include "llvm/Support/ErrorHandling.h"
+
+using namespace clang;
+
+/// \brief Parse global scope or nested-name-specifier if present.
+///
+/// Parses a C++ global scope specifier ('::') or nested-name-specifier (which
+/// may be preceded by '::'). Note that this routine will not parse ::new or
+/// ::delete; it will just leave them in the token stream.
+///
+///       '::'[opt] nested-name-specifier
+///       '::'
+///
+///       nested-name-specifier:
+///         type-name '::'
+///         namespace-name '::'
+///         nested-name-specifier identifier '::'
+///         nested-name-specifier 'template'[opt] simple-template-id '::'
+///
+///
+/// \param SS the scope specifier that will be set to the parsed
+/// nested-name-specifier (or empty)
+///
+/// \param ObjectType if this nested-name-specifier is being parsed following
+/// the "." or "->" of a member access expression, this parameter provides the
+/// type of the object whose members are being accessed.
+///
+/// \param EnteringContext whether we will be entering into the context of
+/// the nested-name-specifier after parsing it.
+///
+/// \returns true if a scope specifier was parsed.
+bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS,
+                                            Action::TypeTy *ObjectType,
+                                            bool EnteringContext) {
+  assert(getLang().CPlusPlus &&
+         "Call sites of this function should be guarded by checking for C++");
+
+  if (Tok.is(tok::annot_cxxscope)) {
+    SS.setScopeRep(Tok.getAnnotationValue());
+    SS.setRange(Tok.getAnnotationRange());
+    ConsumeToken();
+    return true;
+  }
+
+  bool HasScopeSpecifier = false;
+
+  if (Tok.is(tok::coloncolon)) {
+    // ::new and ::delete aren't nested-name-specifiers.
+    tok::TokenKind NextKind = NextToken().getKind();
+    if (NextKind == tok::kw_new || NextKind == tok::kw_delete)
+      return false;
+
+    // '::' - Global scope qualifier.
+    SourceLocation CCLoc = ConsumeToken();
+    SS.setBeginLoc(CCLoc);
+    SS.setScopeRep(Actions.ActOnCXXGlobalScopeSpecifier(CurScope, CCLoc));
+    SS.setEndLoc(CCLoc);
+    HasScopeSpecifier = true;
+  }
+
+  while (true) {
+    if (HasScopeSpecifier) {
+      // C++ [basic.lookup.classref]p5:
+      //   If the qualified-id has the form
+      //
+      //       ::class-name-or-namespace-name::...
+      //
+      //   the class-name-or-namespace-name is looked up in global scope as a
+      //   class-name or namespace-name.
+      //
+      // To implement this, we clear out the object type as soon as we've
+      // seen a leading '::' or part of a nested-name-specifier.
+      ObjectType = 0;
+      
+      if (Tok.is(tok::code_completion)) {
+        // Code completion for a nested-name-specifier, where the code
+        // code completion token follows the '::'.
+        Actions.CodeCompleteQualifiedId(CurScope, SS, EnteringContext);
+        ConsumeToken();
+      }
+    }
+
+    // nested-name-specifier:
+    //   nested-name-specifier 'template'[opt] simple-template-id '::'
+
+    // Parse the optional 'template' keyword, then make sure we have
+    // 'identifier <' after it.
+    if (Tok.is(tok::kw_template)) {
+      // If we don't have a scope specifier or an object type, this isn't a
+      // nested-name-specifier, since they aren't allowed to start with
+      // 'template'.
+      if (!HasScopeSpecifier && !ObjectType)
+        break;
+
+      TentativeParsingAction TPA(*this);
+      SourceLocation TemplateKWLoc = ConsumeToken();
+      
+      UnqualifiedId TemplateName;
+      if (Tok.is(tok::identifier)) {
+        // Consume the identifier.
+        TemplateName.setIdentifier(Tok.getIdentifierInfo(), Tok.getLocation());
+        ConsumeToken();
+      } else if (Tok.is(tok::kw_operator)) {
+        if (ParseUnqualifiedIdOperator(SS, EnteringContext, ObjectType, 
+                                       TemplateName)) {
+          TPA.Commit();
+          break;
+        }
+        
+        if (TemplateName.getKind() != UnqualifiedId::IK_OperatorFunctionId &&
+            TemplateName.getKind() != UnqualifiedId::IK_LiteralOperatorId) {
+          Diag(TemplateName.getSourceRange().getBegin(),
+               diag::err_id_after_template_in_nested_name_spec)
+            << TemplateName.getSourceRange();
+          TPA.Commit();
+          break;
+        }
+      } else {
+        TPA.Revert();
+        break;
+      }
+
+      // If the next token is not '<', we have a qualified-id that refers
+      // to a template name, such as T::template apply, but is not a 
+      // template-id.
+      if (Tok.isNot(tok::less)) {
+        TPA.Revert();
+        break;
+      }        
+      
+      // Commit to parsing the template-id.
+      TPA.Commit();
+      TemplateTy Template
+        = Actions.ActOnDependentTemplateName(TemplateKWLoc, SS, TemplateName,
+                                             ObjectType, EnteringContext);
+      if (!Template)
+        break;
+      if (AnnotateTemplateIdToken(Template, TNK_Dependent_template_name,
+                                  &SS, TemplateName, TemplateKWLoc, false))
+        break;
+
+      continue;
+    }
+
+    if (Tok.is(tok::annot_template_id) && NextToken().is(tok::coloncolon)) {
+      // We have
+      //
+      //   simple-template-id '::'
+      //
+      // So we need to check whether the simple-template-id is of the
+      // right kind (it should name a type or be dependent), and then
+      // convert it into a type within the nested-name-specifier.
+      TemplateIdAnnotation *TemplateId
+        = static_cast<TemplateIdAnnotation *>(Tok.getAnnotationValue());
+
+      if (TemplateId->Kind == TNK_Type_template ||
+          TemplateId->Kind == TNK_Dependent_template_name) {
+        AnnotateTemplateIdTokenAsType(&SS);
+
+        assert(Tok.is(tok::annot_typename) &&
+               "AnnotateTemplateIdTokenAsType isn't working");
+        Token TypeToken = Tok;
+        ConsumeToken();
+        assert(Tok.is(tok::coloncolon) && "NextToken() not working properly!");
+        SourceLocation CCLoc = ConsumeToken();
+
+        if (!HasScopeSpecifier) {
+          SS.setBeginLoc(TypeToken.getLocation());
+          HasScopeSpecifier = true;
+        }
+
+        if (TypeToken.getAnnotationValue())
+          SS.setScopeRep(
+            Actions.ActOnCXXNestedNameSpecifier(CurScope, SS,
+                                                TypeToken.getAnnotationValue(),
+                                                TypeToken.getAnnotationRange(),
+                                                CCLoc));
+        else
+          SS.setScopeRep(0);
+        SS.setEndLoc(CCLoc);
+        continue;
+      }
+
+      assert(false && "FIXME: Only type template names supported here");
+    }
+
+
+    // The rest of the nested-name-specifier possibilities start with
+    // tok::identifier.
+    if (Tok.isNot(tok::identifier))
+      break;
+
+    IdentifierInfo &II = *Tok.getIdentifierInfo();
+
+    // nested-name-specifier:
+    //   type-name '::'
+    //   namespace-name '::'
+    //   nested-name-specifier identifier '::'
+    Token Next = NextToken();
+    
+    // If we get foo:bar, this is almost certainly a typo for foo::bar.  Recover
+    // and emit a fixit hint for it.
+    if (Next.is(tok::colon) && !ColonIsSacred &&
+        Actions.IsInvalidUnlessNestedName(CurScope, SS, II, ObjectType,
+                                          EnteringContext) &&
+        // If the token after the colon isn't an identifier, it's still an
+        // error, but they probably meant something else strange so don't
+        // recover like this.
+        PP.LookAhead(1).is(tok::identifier)) {
+      Diag(Next, diag::err_unexected_colon_in_nested_name_spec)
+        << CodeModificationHint::CreateReplacement(Next.getLocation(), "::");
+      
+      // Recover as if the user wrote '::'.
+      Next.setKind(tok::coloncolon);
+    }
+    
+    if (Next.is(tok::coloncolon)) {
+      // We have an identifier followed by a '::'. Lookup this name
+      // as the name in a nested-name-specifier.
+      SourceLocation IdLoc = ConsumeToken();
+      assert((Tok.is(tok::coloncolon) || Tok.is(tok::colon)) &&
+             "NextToken() not working properly!");
+      SourceLocation CCLoc = ConsumeToken();
+
+      if (!HasScopeSpecifier) {
+        SS.setBeginLoc(IdLoc);
+        HasScopeSpecifier = true;
+      }
+
+      if (SS.isInvalid())
+        continue;
+
+      SS.setScopeRep(
+        Actions.ActOnCXXNestedNameSpecifier(CurScope, SS, IdLoc, CCLoc, II,
+                                            ObjectType, EnteringContext));
+      SS.setEndLoc(CCLoc);
+      continue;
+    }
+
+    // nested-name-specifier:
+    //   type-name '<'
+    if (Next.is(tok::less)) {
+      TemplateTy Template;
+      UnqualifiedId TemplateName;
+      TemplateName.setIdentifier(&II, Tok.getLocation());
+      if (TemplateNameKind TNK = Actions.isTemplateName(CurScope, SS, 
+                                                        TemplateName,
+                                                        ObjectType,
+                                                        EnteringContext,
+                                                        Template)) {
+        // We have found a template name, so annotate this this token
+        // with a template-id annotation. We do not permit the
+        // template-id to be translated into a type annotation,
+        // because some clients (e.g., the parsing of class template
+        // specializations) still want to see the original template-id
+        // token.
+        ConsumeToken();
+        if (AnnotateTemplateIdToken(Template, TNK, &SS, TemplateName, 
+                                    SourceLocation(), false))
+          break;
+        continue;
+      }
+    }
+
+    // We don't have any tokens that form the beginning of a
+    // nested-name-specifier, so we're done.
+    break;
+  }
+
+  return HasScopeSpecifier;
+}
+
+/// ParseCXXIdExpression - Handle id-expression.
+///
+///       id-expression:
+///         unqualified-id
+///         qualified-id
+///
+///       qualified-id:
+///         '::'[opt] nested-name-specifier 'template'[opt] unqualified-id
+///         '::' identifier
+///         '::' operator-function-id
+///         '::' template-id
+///
+/// NOTE: The standard specifies that, for qualified-id, the parser does not
+/// expect:
+///
+///   '::' conversion-function-id
+///   '::' '~' class-name
+///
+/// This may cause a slight inconsistency on diagnostics:
+///
+/// class C {};
+/// namespace A {}
+/// void f() {
+///   :: A :: ~ C(); // Some Sema error about using destructor with a
+///                  // namespace.
+///   :: ~ C(); // Some Parser error like 'unexpected ~'.
+/// }
+///
+/// We simplify the parser a bit and make it work like:
+///
+///       qualified-id:
+///         '::'[opt] nested-name-specifier 'template'[opt] unqualified-id
+///         '::' unqualified-id
+///
+/// That way Sema can handle and report similar errors for namespaces and the
+/// global scope.
+///
+/// The isAddressOfOperand parameter indicates that this id-expression is a
+/// direct operand of the address-of operator. This is, besides member contexts,
+/// the only place where a qualified-id naming a non-static class member may
+/// appear.
+///
+Parser::OwningExprResult Parser::ParseCXXIdExpression(bool isAddressOfOperand) {
+  // qualified-id:
+  //   '::'[opt] nested-name-specifier 'template'[opt] unqualified-id
+  //   '::' unqualified-id
+  //
+  CXXScopeSpec SS;
+  ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/0, false);
+  
+  UnqualifiedId Name;
+  if (ParseUnqualifiedId(SS, 
+                         /*EnteringContext=*/false, 
+                         /*AllowDestructorName=*/false, 
+                         /*AllowConstructorName=*/false, 
+                         /*ObjectType=*/0,
+                         Name))
+    return ExprError();
+
+  // This is only the direct operand of an & operator if it is not
+  // followed by a postfix-expression suffix.
+  if (isAddressOfOperand) {
+    switch (Tok.getKind()) {
+    case tok::l_square:
+    case tok::l_paren:
+    case tok::arrow:
+    case tok::period:
+    case tok::plusplus:
+    case tok::minusminus:
+      isAddressOfOperand = false;
+      break;
+
+    default:
+      break;
+    }
+  }
+  
+  return Actions.ActOnIdExpression(CurScope, SS, Name, Tok.is(tok::l_paren),
+                                   isAddressOfOperand);
+  
+}
+
+/// ParseCXXCasts - This handles the various ways to cast expressions to another
+/// type.
+///
+///       postfix-expression: [C++ 5.2p1]
+///         'dynamic_cast' '<' type-name '>' '(' expression ')'
+///         'static_cast' '<' type-name '>' '(' expression ')'
+///         'reinterpret_cast' '<' type-name '>' '(' expression ')'
+///         'const_cast' '<' type-name '>' '(' expression ')'
+///
+Parser::OwningExprResult Parser::ParseCXXCasts() {
+  tok::TokenKind Kind = Tok.getKind();
+  const char *CastName = 0;     // For error messages
+
+  switch (Kind) {
+  default: assert(0 && "Unknown C++ cast!"); abort();
+  case tok::kw_const_cast:       CastName = "const_cast";       break;
+  case tok::kw_dynamic_cast:     CastName = "dynamic_cast";     break;
+  case tok::kw_reinterpret_cast: CastName = "reinterpret_cast"; break;
+  case tok::kw_static_cast:      CastName = "static_cast";      break;
+  }
+
+  SourceLocation OpLoc = ConsumeToken();
+  SourceLocation LAngleBracketLoc = Tok.getLocation();
+
+  if (ExpectAndConsume(tok::less, diag::err_expected_less_after, CastName))
+    return ExprError();
+
+  TypeResult CastTy = ParseTypeName();
+  SourceLocation RAngleBracketLoc = Tok.getLocation();
+
+  if (ExpectAndConsume(tok::greater, diag::err_expected_greater))
+    return ExprError(Diag(LAngleBracketLoc, diag::note_matching) << "<");
+
+  SourceLocation LParenLoc = Tok.getLocation(), RParenLoc;
+
+  if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen_after, CastName))
+    return ExprError();
+
+  OwningExprResult Result = ParseExpression();
+
+  // Match the ')'.
+  RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc);
+
+  if (!Result.isInvalid() && !CastTy.isInvalid())
+    Result = Actions.ActOnCXXNamedCast(OpLoc, Kind,
+                                       LAngleBracketLoc, CastTy.get(),
+                                       RAngleBracketLoc,
+                                       LParenLoc, move(Result), RParenLoc);
+
+  return move(Result);
+}
+
+/// ParseCXXTypeid - This handles the C++ typeid expression.
+///
+///       postfix-expression: [C++ 5.2p1]
+///         'typeid' '(' expression ')'
+///         'typeid' '(' type-id ')'
+///
+Parser::OwningExprResult Parser::ParseCXXTypeid() {
+  assert(Tok.is(tok::kw_typeid) && "Not 'typeid'!");
+
+  SourceLocation OpLoc = ConsumeToken();
+  SourceLocation LParenLoc = Tok.getLocation();
+  SourceLocation RParenLoc;
+
+  // typeid expressions are always parenthesized.
+  if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen_after,
+      "typeid"))
+    return ExprError();
+
+  OwningExprResult Result(Actions);
+
+  if (isTypeIdInParens()) {
+    TypeResult Ty = ParseTypeName();
+
+    // Match the ')'.
+    MatchRHSPunctuation(tok::r_paren, LParenLoc);
+
+    if (Ty.isInvalid())
+      return ExprError();
+
+    Result = Actions.ActOnCXXTypeid(OpLoc, LParenLoc, /*isType=*/true,
+                                    Ty.get(), RParenLoc);
+  } else {
+    // C++0x [expr.typeid]p3:
+    //   When typeid is applied to an expression other than an lvalue of a
+    //   polymorphic class type [...] The expression is an unevaluated
+    //   operand (Clause 5).
+    //
+    // Note that we can't tell whether the expression is an lvalue of a
+    // polymorphic class type until after we've parsed the expression, so
+    // we the expression is potentially potentially evaluated.
+    EnterExpressionEvaluationContext Unevaluated(Actions,
+                                       Action::PotentiallyPotentiallyEvaluated);
+    Result = ParseExpression();
+
+    // Match the ')'.
+    if (Result.isInvalid())
+      SkipUntil(tok::r_paren);
+    else {
+      MatchRHSPunctuation(tok::r_paren, LParenLoc);
+
+      Result = Actions.ActOnCXXTypeid(OpLoc, LParenLoc, /*isType=*/false,
+                                      Result.release(), RParenLoc);
+    }
+  }
+
+  return move(Result);
+}
+
+/// ParseCXXBoolLiteral - This handles the C++ Boolean literals.
+///
+///       boolean-literal: [C++ 2.13.5]
+///         'true'
+///         'false'
+Parser::OwningExprResult Parser::ParseCXXBoolLiteral() {
+  tok::TokenKind Kind = Tok.getKind();
+  return Actions.ActOnCXXBoolLiteral(ConsumeToken(), Kind);
+}
+
+/// ParseThrowExpression - This handles the C++ throw expression.
+///
+///       throw-expression: [C++ 15]
+///         'throw' assignment-expression[opt]
+Parser::OwningExprResult Parser::ParseThrowExpression() {
+  assert(Tok.is(tok::kw_throw) && "Not throw!");
+  SourceLocation ThrowLoc = ConsumeToken();           // Eat the throw token.
+
+  // If the current token isn't the start of an assignment-expression,
+  // then the expression is not present.  This handles things like:
+  //   "C ? throw : (void)42", which is crazy but legal.
+  switch (Tok.getKind()) {  // FIXME: move this predicate somewhere common.
+  case tok::semi:
+  case tok::r_paren:
+  case tok::r_square:
+  case tok::r_brace:
+  case tok::colon:
+  case tok::comma:
+    return Actions.ActOnCXXThrow(ThrowLoc, ExprArg(Actions));
+
+  default:
+    OwningExprResult Expr(ParseAssignmentExpression());
+    if (Expr.isInvalid()) return move(Expr);
+    return Actions.ActOnCXXThrow(ThrowLoc, move(Expr));
+  }
+}
+
+/// ParseCXXThis - This handles the C++ 'this' pointer.
+///
+/// C++ 9.3.2: In the body of a non-static member function, the keyword this is
+/// a non-lvalue expression whose value is the address of the object for which
+/// the function is called.
+Parser::OwningExprResult Parser::ParseCXXThis() {
+  assert(Tok.is(tok::kw_this) && "Not 'this'!");
+  SourceLocation ThisLoc = ConsumeToken();
+  return Actions.ActOnCXXThis(ThisLoc);
+}
+
+/// ParseCXXTypeConstructExpression - Parse construction of a specified type.
+/// Can be interpreted either as function-style casting ("int(x)")
+/// or class type construction ("ClassType(x,y,z)")
+/// or creation of a value-initialized type ("int()").
+///
+///       postfix-expression: [C++ 5.2p1]
+///         simple-type-specifier '(' expression-list[opt] ')'      [C++ 5.2.3]
+///         typename-specifier '(' expression-list[opt] ')'         [TODO]
+///
+Parser::OwningExprResult
+Parser::ParseCXXTypeConstructExpression(const DeclSpec &DS) {
+  Declarator DeclaratorInfo(DS, Declarator::TypeNameContext);
+  TypeTy *TypeRep = Actions.ActOnTypeName(CurScope, DeclaratorInfo).get();
+
+  assert(Tok.is(tok::l_paren) && "Expected '('!");
+  SourceLocation LParenLoc = ConsumeParen();
+
+  ExprVector Exprs(Actions);
+  CommaLocsTy CommaLocs;
+
+  if (Tok.isNot(tok::r_paren)) {
+    if (ParseExpressionList(Exprs, CommaLocs)) {
+      SkipUntil(tok::r_paren);
+      return ExprError();
+    }
+  }
+
+  // Match the ')'.
+  SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc);
+
+  // TypeRep could be null, if it references an invalid typedef.
+  if (!TypeRep)
+    return ExprError();
+
+  assert((Exprs.size() == 0 || Exprs.size()-1 == CommaLocs.size())&&
+         "Unexpected number of commas!");
+  return Actions.ActOnCXXTypeConstructExpr(DS.getSourceRange(), TypeRep,
+                                           LParenLoc, move_arg(Exprs),
+                                           CommaLocs.data(), RParenLoc);
+}
+
+/// ParseCXXCondition - if/switch/while condition expression.
+///
+///       condition:
+///         expression
+///         type-specifier-seq declarator '=' assignment-expression
+/// [GNU]   type-specifier-seq declarator simple-asm-expr[opt] attributes[opt]
+///             '=' assignment-expression
+///
+/// \param ExprResult if the condition was parsed as an expression, the
+/// parsed expression.
+///
+/// \param DeclResult if the condition was parsed as a declaration, the
+/// parsed declaration.
+///
+/// \returns true if there was a parsing, false otherwise.
+bool Parser::ParseCXXCondition(OwningExprResult &ExprResult,
+                               DeclPtrTy &DeclResult) {
+  if (Tok.is(tok::code_completion)) {
+    Actions.CodeCompleteOrdinaryName(CurScope, Action::CCC_Condition);
+    ConsumeToken();
+  }
+
+  if (!isCXXConditionDeclaration()) {
+    ExprResult = ParseExpression(); // expression
+    DeclResult = DeclPtrTy();
+    return ExprResult.isInvalid();
+  }
+
+  // type-specifier-seq
+  DeclSpec DS;
+  ParseSpecifierQualifierList(DS);
+
+  // declarator
+  Declarator DeclaratorInfo(DS, Declarator::ConditionContext);
+  ParseDeclarator(DeclaratorInfo);
+
+  // simple-asm-expr[opt]
+  if (Tok.is(tok::kw_asm)) {
+    SourceLocation Loc;
+    OwningExprResult AsmLabel(ParseSimpleAsm(&Loc));
+    if (AsmLabel.isInvalid()) {
+      SkipUntil(tok::semi);
+      return true;
+    }
+    DeclaratorInfo.setAsmLabel(AsmLabel.release());
+    DeclaratorInfo.SetRangeEnd(Loc);
+  }
+
+  // If attributes are present, parse them.
+  if (Tok.is(tok::kw___attribute)) {
+    SourceLocation Loc;
+    AttributeList *AttrList = ParseGNUAttributes(&Loc);
+    DeclaratorInfo.AddAttributes(AttrList, Loc);
+  }
+
+  // Type-check the declaration itself.
+  Action::DeclResult Dcl = Actions.ActOnCXXConditionDeclaration(CurScope, 
+                                                                DeclaratorInfo);
+  DeclResult = Dcl.get();
+  ExprResult = ExprError();
+  
+  // '=' assignment-expression
+  if (Tok.is(tok::equal)) {
+    SourceLocation EqualLoc = ConsumeToken();
+    OwningExprResult AssignExpr(ParseAssignmentExpression());
+    if (!AssignExpr.isInvalid()) 
+      Actions.AddInitializerToDecl(DeclResult, move(AssignExpr));
+  } else {
+    // FIXME: C++0x allows a braced-init-list
+    Diag(Tok, diag::err_expected_equal_after_declarator);
+  }
+  
+  return false;
+}
+
+/// ParseCXXSimpleTypeSpecifier - [C++ 7.1.5.2] Simple type specifiers.
+/// This should only be called when the current token is known to be part of
+/// simple-type-specifier.
+///
+///       simple-type-specifier:
+///         '::'[opt] nested-name-specifier[opt] type-name
+///         '::'[opt] nested-name-specifier 'template' simple-template-id [TODO]
+///         char
+///         wchar_t
+///         bool
+///         short
+///         int
+///         long
+///         signed
+///         unsigned
+///         float
+///         double
+///         void
+/// [GNU]   typeof-specifier
+/// [C++0x] auto               [TODO]
+///
+///       type-name:
+///         class-name
+///         enum-name
+///         typedef-name
+///
+void Parser::ParseCXXSimpleTypeSpecifier(DeclSpec &DS) {
+  DS.SetRangeStart(Tok.getLocation());
+  const char *PrevSpec;
+  unsigned DiagID;
+  SourceLocation Loc = Tok.getLocation();
+
+  switch (Tok.getKind()) {
+  case tok::identifier:   // foo::bar
+  case tok::coloncolon:   // ::foo::bar
+    assert(0 && "Annotation token should already be formed!");
+  default:
+    assert(0 && "Not a simple-type-specifier token!");
+    abort();
+
+  // type-name
+  case tok::annot_typename: {
+    DS.SetTypeSpecType(DeclSpec::TST_typename, Loc, PrevSpec, DiagID,
+                       Tok.getAnnotationValue());
+    break;
+  }
+
+  // builtin types
+  case tok::kw_short:
+    DS.SetTypeSpecWidth(DeclSpec::TSW_short, Loc, PrevSpec, DiagID);
+    break;
+  case tok::kw_long:
+    DS.SetTypeSpecWidth(DeclSpec::TSW_long, Loc, PrevSpec, DiagID);
+    break;
+  case tok::kw_signed:
+    DS.SetTypeSpecSign(DeclSpec::TSS_signed, Loc, PrevSpec, DiagID);
+    break;
+  case tok::kw_unsigned:
+    DS.SetTypeSpecSign(DeclSpec::TSS_unsigned, Loc, PrevSpec, DiagID);
+    break;
+  case tok::kw_void:
+    DS.SetTypeSpecType(DeclSpec::TST_void, Loc, PrevSpec, DiagID);
+    break;
+  case tok::kw_char:
+    DS.SetTypeSpecType(DeclSpec::TST_char, Loc, PrevSpec, DiagID);
+    break;
+  case tok::kw_int:
+    DS.SetTypeSpecType(DeclSpec::TST_int, Loc, PrevSpec, DiagID);
+    break;
+  case tok::kw_float:
+    DS.SetTypeSpecType(DeclSpec::TST_float, Loc, PrevSpec, DiagID);
+    break;
+  case tok::kw_double:
+    DS.SetTypeSpecType(DeclSpec::TST_double, Loc, PrevSpec, DiagID);
+    break;
+  case tok::kw_wchar_t:
+    DS.SetTypeSpecType(DeclSpec::TST_wchar, Loc, PrevSpec, DiagID);
+    break;
+  case tok::kw_char16_t:
+    DS.SetTypeSpecType(DeclSpec::TST_char16, Loc, PrevSpec, DiagID);
+    break;
+  case tok::kw_char32_t:
+    DS.SetTypeSpecType(DeclSpec::TST_char32, Loc, PrevSpec, DiagID);
+    break;
+  case tok::kw_bool:
+    DS.SetTypeSpecType(DeclSpec::TST_bool, Loc, PrevSpec, DiagID);
+    break;
+
+  // GNU typeof support.
+  case tok::kw_typeof:
+    ParseTypeofSpecifier(DS);
+    DS.Finish(Diags, PP);
+    return;
+  }
+  if (Tok.is(tok::annot_typename))
+    DS.SetRangeEnd(Tok.getAnnotationEndLoc());
+  else
+    DS.SetRangeEnd(Tok.getLocation());
+  ConsumeToken();
+  DS.Finish(Diags, PP);
+}
+
+/// ParseCXXTypeSpecifierSeq - Parse a C++ type-specifier-seq (C++
+/// [dcl.name]), which is a non-empty sequence of type-specifiers,
+/// e.g., "const short int". Note that the DeclSpec is *not* finished
+/// by parsing the type-specifier-seq, because these sequences are
+/// typically followed by some form of declarator. Returns true and
+/// emits diagnostics if this is not a type-specifier-seq, false
+/// otherwise.
+///
+///   type-specifier-seq: [C++ 8.1]
+///     type-specifier type-specifier-seq[opt]
+///
+bool Parser::ParseCXXTypeSpecifierSeq(DeclSpec &DS) {
+  DS.SetRangeStart(Tok.getLocation());
+  const char *PrevSpec = 0;
+  unsigned DiagID;
+  bool isInvalid = 0;
+
+  // Parse one or more of the type specifiers.
+  if (!ParseOptionalTypeSpecifier(DS, isInvalid, PrevSpec, DiagID,
+      ParsedTemplateInfo(), /*SuppressDeclarations*/true)) {
+    Diag(Tok, diag::err_operator_missing_type_specifier);
+    return true;
+  }
+
+  while (ParseOptionalTypeSpecifier(DS, isInvalid, PrevSpec, DiagID,
+         ParsedTemplateInfo(), /*SuppressDeclarations*/true))
+  {}
+
+  return false;
+}
+
+/// \brief Finish parsing a C++ unqualified-id that is a template-id of
+/// some form. 
+///
+/// This routine is invoked when a '<' is encountered after an identifier or
+/// operator-function-id is parsed by \c ParseUnqualifiedId() to determine
+/// whether the unqualified-id is actually a template-id. This routine will
+/// then parse the template arguments and form the appropriate template-id to
+/// return to the caller.
+///
+/// \param SS the nested-name-specifier that precedes this template-id, if
+/// we're actually parsing a qualified-id.
+///
+/// \param Name for constructor and destructor names, this is the actual
+/// identifier that may be a template-name.
+///
+/// \param NameLoc the location of the class-name in a constructor or 
+/// destructor.
+///
+/// \param EnteringContext whether we're entering the scope of the 
+/// nested-name-specifier.
+///
+/// \param ObjectType if this unqualified-id occurs within a member access
+/// expression, the type of the base object whose member is being accessed.
+///
+/// \param Id as input, describes the template-name or operator-function-id
+/// that precedes the '<'. If template arguments were parsed successfully,
+/// will be updated with the template-id.
+/// 
+/// \returns true if a parse error occurred, false otherwise.
+bool Parser::ParseUnqualifiedIdTemplateId(CXXScopeSpec &SS,
+                                          IdentifierInfo *Name,
+                                          SourceLocation NameLoc,
+                                          bool EnteringContext,
+                                          TypeTy *ObjectType,
+                                          UnqualifiedId &Id) {
+  assert(Tok.is(tok::less) && "Expected '<' to finish parsing a template-id");
+  
+  TemplateTy Template;
+  TemplateNameKind TNK = TNK_Non_template;
+  switch (Id.getKind()) {
+  case UnqualifiedId::IK_Identifier:
+  case UnqualifiedId::IK_OperatorFunctionId:
+  case UnqualifiedId::IK_LiteralOperatorId:
+    TNK = Actions.isTemplateName(CurScope, SS, Id, ObjectType, EnteringContext, 
+                                 Template);
+    break;
+      
+  case UnqualifiedId::IK_ConstructorName: {
+    UnqualifiedId TemplateName;
+    TemplateName.setIdentifier(Name, NameLoc);
+    TNK = Actions.isTemplateName(CurScope, SS, TemplateName, ObjectType, 
+                                 EnteringContext, Template);
+    break;
+  }
+      
+  case UnqualifiedId::IK_DestructorName: {
+    UnqualifiedId TemplateName;
+    TemplateName.setIdentifier(Name, NameLoc);
+    if (ObjectType) {
+      Template = Actions.ActOnDependentTemplateName(SourceLocation(), SS, 
+                                                    TemplateName, ObjectType,
+                                                    EnteringContext);
+      TNK = TNK_Dependent_template_name;
+      if (!Template.get())
+        return true;
+    } else {
+      TNK = Actions.isTemplateName(CurScope, SS, TemplateName, ObjectType, 
+                                   EnteringContext, Template);
+      
+      if (TNK == TNK_Non_template && Id.DestructorName == 0) {
+        // The identifier following the destructor did not refer to a template
+        // or to a type. Complain.
+        if (ObjectType)
+          Diag(NameLoc, diag::err_ident_in_pseudo_dtor_not_a_type)
+            << Name;        
+        else
+          Diag(NameLoc, diag::err_destructor_class_name);
+        return true;        
+      }
+    }
+    break;
+  }
+      
+  default:
+    return false;
+  }
+  
+  if (TNK == TNK_Non_template)
+    return false;
+  
+  // Parse the enclosed template argument list.
+  SourceLocation LAngleLoc, RAngleLoc;
+  TemplateArgList TemplateArgs;
+  if (ParseTemplateIdAfterTemplateName(Template, Id.StartLocation,
+                                       &SS, true, LAngleLoc,
+                                       TemplateArgs,
+                                       RAngleLoc))
+    return true;
+  
+  if (Id.getKind() == UnqualifiedId::IK_Identifier ||
+      Id.getKind() == UnqualifiedId::IK_OperatorFunctionId ||
+      Id.getKind() == UnqualifiedId::IK_LiteralOperatorId) {
+    // Form a parsed representation of the template-id to be stored in the
+    // UnqualifiedId.
+    TemplateIdAnnotation *TemplateId
+      = TemplateIdAnnotation::Allocate(TemplateArgs.size());
+
+    if (Id.getKind() == UnqualifiedId::IK_Identifier) {
+      TemplateId->Name = Id.Identifier;
+      TemplateId->Operator = OO_None;
+      TemplateId->TemplateNameLoc = Id.StartLocation;
+    } else {
+      TemplateId->Name = 0;
+      TemplateId->Operator = Id.OperatorFunctionId.Operator;
+      TemplateId->TemplateNameLoc = Id.StartLocation;
+    }
+
+    TemplateId->Template = Template.getAs<void*>();
+    TemplateId->Kind = TNK;
+    TemplateId->LAngleLoc = LAngleLoc;
+    TemplateId->RAngleLoc = RAngleLoc;
+    ParsedTemplateArgument *Args = TemplateId->getTemplateArgs();
+    for (unsigned Arg = 0, ArgEnd = TemplateArgs.size(); 
+         Arg != ArgEnd; ++Arg)
+      Args[Arg] = TemplateArgs[Arg];
+    
+    Id.setTemplateId(TemplateId);
+    return false;
+  }
+
+  // Bundle the template arguments together.
+  ASTTemplateArgsPtr TemplateArgsPtr(Actions, TemplateArgs.data(),
+                                     TemplateArgs.size());
+  
+  // Constructor and destructor names.
+  Action::TypeResult Type
+    = Actions.ActOnTemplateIdType(Template, NameLoc,
+                                  LAngleLoc, TemplateArgsPtr,
+                                  RAngleLoc);
+  if (Type.isInvalid())
+    return true;
+  
+  if (Id.getKind() == UnqualifiedId::IK_ConstructorName)
+    Id.setConstructorName(Type.get(), NameLoc, RAngleLoc);
+  else
+    Id.setDestructorName(Id.StartLocation, Type.get(), RAngleLoc);
+  
+  return false;
+}
+
+/// \brief Parse an operator-function-id or conversion-function-id as part
+/// of a C++ unqualified-id.
+///
+/// This routine is responsible only for parsing the operator-function-id or
+/// conversion-function-id; it does not handle template arguments in any way.
+///
+/// \code
+///       operator-function-id: [C++ 13.5]
+///         'operator' operator
+///
+///       operator: one of
+///            new   delete  new[]   delete[]
+///            +     -    *  /    %  ^    &   |   ~
+///            !     =    <  >    += -=   *=  /=  %=
+///            ^=    &=   |= <<   >> >>= <<=  ==  !=
+///            <=    >=   && ||   ++ --   ,   ->* ->
+///            ()    []
+///
+///       conversion-function-id: [C++ 12.3.2]
+///         operator conversion-type-id
+///
+///       conversion-type-id:
+///         type-specifier-seq conversion-declarator[opt]
+///
+///       conversion-declarator:
+///         ptr-operator conversion-declarator[opt]
+/// \endcode
+///
+/// \param The nested-name-specifier that preceded this unqualified-id. If
+/// non-empty, then we are parsing the unqualified-id of a qualified-id.
+///
+/// \param EnteringContext whether we are entering the scope of the 
+/// nested-name-specifier.
+///
+/// \param ObjectType if this unqualified-id occurs within a member access
+/// expression, the type of the base object whose member is being accessed.
+///
+/// \param Result on a successful parse, contains the parsed unqualified-id.
+///
+/// \returns true if parsing fails, false otherwise.
+bool Parser::ParseUnqualifiedIdOperator(CXXScopeSpec &SS, bool EnteringContext,
+                                        TypeTy *ObjectType,
+                                        UnqualifiedId &Result) {
+  assert(Tok.is(tok::kw_operator) && "Expected 'operator' keyword");
+  
+  // Consume the 'operator' keyword.
+  SourceLocation KeywordLoc = ConsumeToken();
+  
+  // Determine what kind of operator name we have.
+  unsigned SymbolIdx = 0;
+  SourceLocation SymbolLocations[3];
+  OverloadedOperatorKind Op = OO_None;
+  switch (Tok.getKind()) {
+    case tok::kw_new:
+    case tok::kw_delete: {
+      bool isNew = Tok.getKind() == tok::kw_new;
+      // Consume the 'new' or 'delete'.
+      SymbolLocations[SymbolIdx++] = ConsumeToken();
+      if (Tok.is(tok::l_square)) {
+        // Consume the '['.
+        SourceLocation LBracketLoc = ConsumeBracket();
+        // Consume the ']'.
+        SourceLocation RBracketLoc = MatchRHSPunctuation(tok::r_square,
+                                                         LBracketLoc);
+        if (RBracketLoc.isInvalid())
+          return true;
+        
+        SymbolLocations[SymbolIdx++] = LBracketLoc;
+        SymbolLocations[SymbolIdx++] = RBracketLoc;
+        Op = isNew? OO_Array_New : OO_Array_Delete;
+      } else {
+        Op = isNew? OO_New : OO_Delete;
+      }
+      break;
+    }
+      
+#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \
+    case tok::Token:                                                     \
+      SymbolLocations[SymbolIdx++] = ConsumeToken();                     \
+      Op = OO_##Name;                                                    \
+      break;
+#define OVERLOADED_OPERATOR_MULTI(Name,Spelling,Unary,Binary,MemberOnly)
+#include "clang/Basic/OperatorKinds.def"
+      
+    case tok::l_paren: {
+      // Consume the '('.
+      SourceLocation LParenLoc = ConsumeParen();
+      // Consume the ')'.
+      SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren,
+                                                     LParenLoc);
+      if (RParenLoc.isInvalid())
+        return true;
+      
+      SymbolLocations[SymbolIdx++] = LParenLoc;
+      SymbolLocations[SymbolIdx++] = RParenLoc;
+      Op = OO_Call;
+      break;
+    }
+      
+    case tok::l_square: {
+      // Consume the '['.
+      SourceLocation LBracketLoc = ConsumeBracket();
+      // Consume the ']'.
+      SourceLocation RBracketLoc = MatchRHSPunctuation(tok::r_square,
+                                                       LBracketLoc);
+      if (RBracketLoc.isInvalid())
+        return true;
+      
+      SymbolLocations[SymbolIdx++] = LBracketLoc;
+      SymbolLocations[SymbolIdx++] = RBracketLoc;
+      Op = OO_Subscript;
+      break;
+    }
+      
+    case tok::code_completion: {
+      // Code completion for the operator name.
+      Actions.CodeCompleteOperatorName(CurScope);
+      
+      // Consume the operator token.
+      ConsumeToken();
+      
+      // Don't try to parse any further.
+      return true;
+    }
+      
+    default:
+      break;
+  }
+  
+  if (Op != OO_None) {
+    // We have parsed an operator-function-id.
+    Result.setOperatorFunctionId(KeywordLoc, Op, SymbolLocations);
+    return false;
+  }
+
+  // Parse a literal-operator-id.
+  //
+  //   literal-operator-id: [C++0x 13.5.8]
+  //     operator "" identifier
+
+  if (getLang().CPlusPlus0x && Tok.is(tok::string_literal)) {
+    if (Tok.getLength() != 2)
+      Diag(Tok.getLocation(), diag::err_operator_string_not_empty);
+    ConsumeStringToken();
+
+    if (Tok.isNot(tok::identifier)) {
+      Diag(Tok.getLocation(), diag::err_expected_ident);
+      return true;
+    }
+
+    IdentifierInfo *II = Tok.getIdentifierInfo();
+    Result.setLiteralOperatorId(II, KeywordLoc, ConsumeToken());
+    return false;
+  }
+  
+  // Parse a conversion-function-id.
+  //
+  //   conversion-function-id: [C++ 12.3.2]
+  //     operator conversion-type-id
+  //
+  //   conversion-type-id:
+  //     type-specifier-seq conversion-declarator[opt]
+  //
+  //   conversion-declarator:
+  //     ptr-operator conversion-declarator[opt]
+  
+  // Parse the type-specifier-seq.
+  DeclSpec DS;
+  if (ParseCXXTypeSpecifierSeq(DS)) // FIXME: ObjectType?
+    return true;
+  
+  // Parse the conversion-declarator, which is merely a sequence of
+  // ptr-operators.
+  Declarator D(DS, Declarator::TypeNameContext);
+  ParseDeclaratorInternal(D, /*DirectDeclParser=*/0);
+  
+  // Finish up the type.
+  Action::TypeResult Ty = Actions.ActOnTypeName(CurScope, D);
+  if (Ty.isInvalid())
+    return true;
+  
+  // Note that this is a conversion-function-id.
+  Result.setConversionFunctionId(KeywordLoc, Ty.get(), 
+                                 D.getSourceRange().getEnd());
+  return false;  
+}
+
+/// \brief Parse a C++ unqualified-id (or a C identifier), which describes the
+/// name of an entity.
+///
+/// \code
+///       unqualified-id: [C++ expr.prim.general]
+///         identifier
+///         operator-function-id
+///         conversion-function-id
+/// [C++0x] literal-operator-id [TODO]
+///         ~ class-name
+///         template-id
+///
+/// \endcode
+///
+/// \param The nested-name-specifier that preceded this unqualified-id. If
+/// non-empty, then we are parsing the unqualified-id of a qualified-id.
+///
+/// \param EnteringContext whether we are entering the scope of the 
+/// nested-name-specifier.
+///
+/// \param AllowDestructorName whether we allow parsing of a destructor name.
+///
+/// \param AllowConstructorName whether we allow parsing a constructor name.
+///
+/// \param ObjectType if this unqualified-id occurs within a member access
+/// expression, the type of the base object whose member is being accessed.
+///
+/// \param Result on a successful parse, contains the parsed unqualified-id.
+///
+/// \returns true if parsing fails, false otherwise.
+bool Parser::ParseUnqualifiedId(CXXScopeSpec &SS, bool EnteringContext,
+                                bool AllowDestructorName,
+                                bool AllowConstructorName,
+                                TypeTy *ObjectType,
+                                UnqualifiedId &Result) {
+  // unqualified-id:
+  //   identifier
+  //   template-id (when it hasn't already been annotated)
+  if (Tok.is(tok::identifier)) {
+    // Consume the identifier.
+    IdentifierInfo *Id = Tok.getIdentifierInfo();
+    SourceLocation IdLoc = ConsumeToken();
+
+    if (!getLang().CPlusPlus) {
+      // If we're not in C++, only identifiers matter. Record the
+      // identifier and return.
+      Result.setIdentifier(Id, IdLoc);
+      return false;
+    }
+
+    if (AllowConstructorName && 
+        Actions.isCurrentClassName(*Id, CurScope, &SS)) {
+      // We have parsed a constructor name.
+      Result.setConstructorName(Actions.getTypeName(*Id, IdLoc, CurScope,
+                                                    &SS, false),
+                                IdLoc, IdLoc);
+    } else {
+      // We have parsed an identifier.
+      Result.setIdentifier(Id, IdLoc);      
+    }
+
+    // If the next token is a '<', we may have a template.
+    if (Tok.is(tok::less))
+      return ParseUnqualifiedIdTemplateId(SS, Id, IdLoc, EnteringContext, 
+                                          ObjectType, Result);
+    
+    return false;
+  }
+  
+  // unqualified-id:
+  //   template-id (already parsed and annotated)
+  if (Tok.is(tok::annot_template_id)) {
+    TemplateIdAnnotation *TemplateId
+      = static_cast<TemplateIdAnnotation*>(Tok.getAnnotationValue());
+
+    // If the template-name names the current class, then this is a constructor 
+    if (AllowConstructorName && TemplateId->Name &&
+        Actions.isCurrentClassName(*TemplateId->Name, CurScope, &SS)) {
+      if (SS.isSet()) {
+        // C++ [class.qual]p2 specifies that a qualified template-name
+        // is taken as the constructor name where a constructor can be
+        // declared. Thus, the template arguments are extraneous, so
+        // complain about them and remove them entirely.
+        Diag(TemplateId->TemplateNameLoc, 
+             diag::err_out_of_line_constructor_template_id)
+          << TemplateId->Name
+          << CodeModificationHint::CreateRemoval(
+                    SourceRange(TemplateId->LAngleLoc, TemplateId->RAngleLoc));
+        Result.setConstructorName(Actions.getTypeName(*TemplateId->Name,
+                                                  TemplateId->TemplateNameLoc, 
+                                                      CurScope,
+                                                      &SS, false),
+                                  TemplateId->TemplateNameLoc, 
+                                  TemplateId->RAngleLoc);
+        TemplateId->Destroy();
+        ConsumeToken();
+        return false;
+      }
+
+      Result.setConstructorTemplateId(TemplateId);
+      ConsumeToken();
+      return false;
+    }
+
+    // We have already parsed a template-id; consume the annotation token as
+    // our unqualified-id.
+    Result.setTemplateId(TemplateId);
+    ConsumeToken();
+    return false;
+  }
+  
+  // unqualified-id:
+  //   operator-function-id
+  //   conversion-function-id
+  if (Tok.is(tok::kw_operator)) {
+    if (ParseUnqualifiedIdOperator(SS, EnteringContext, ObjectType, Result))
+      return true;
+    
+    // If we have an operator-function-id or a literal-operator-id and the next
+    // token is a '<', we may have a
+    // 
+    //   template-id:
+    //     operator-function-id < template-argument-list[opt] >
+    if ((Result.getKind() == UnqualifiedId::IK_OperatorFunctionId ||
+         Result.getKind() == UnqualifiedId::IK_LiteralOperatorId) &&
+        Tok.is(tok::less))
+      return ParseUnqualifiedIdTemplateId(SS, 0, SourceLocation(), 
+                                          EnteringContext, ObjectType, 
+                                          Result);
+    
+    return false;
+  }
+  
+  if (getLang().CPlusPlus && 
+      (AllowDestructorName || SS.isSet()) && Tok.is(tok::tilde)) {
+    // C++ [expr.unary.op]p10:
+    //   There is an ambiguity in the unary-expression ~X(), where X is a 
+    //   class-name. The ambiguity is resolved in favor of treating ~ as a 
+    //    unary complement rather than treating ~X as referring to a destructor.
+    
+    // Parse the '~'.
+    SourceLocation TildeLoc = ConsumeToken();
+    
+    // Parse the class-name.
+    if (Tok.isNot(tok::identifier)) {
+      Diag(Tok, diag::err_destructor_class_name);
+      return true;
+    }
+
+    // Parse the class-name (or template-name in a simple-template-id).
+    IdentifierInfo *ClassName = Tok.getIdentifierInfo();
+    SourceLocation ClassNameLoc = ConsumeToken();
+    
+    if (Tok.is(tok::less)) {
+      Result.setDestructorName(TildeLoc, 0, ClassNameLoc);
+      return ParseUnqualifiedIdTemplateId(SS, ClassName, ClassNameLoc,
+                                          EnteringContext, ObjectType, Result);
+    }
+    
+    // Note that this is a destructor name.
+    Action::TypeTy *Ty = Actions.getTypeName(*ClassName, ClassNameLoc,
+                                             CurScope, &SS, false, ObjectType);
+    if (!Ty) {
+      if (ObjectType)
+        Diag(ClassNameLoc, diag::err_ident_in_pseudo_dtor_not_a_type)
+          << ClassName;        
+      else
+        Diag(ClassNameLoc, diag::err_destructor_class_name);
+      return true;
+    }
+    
+    Result.setDestructorName(TildeLoc, Ty, ClassNameLoc);
+    return false;
+  }
+  
+  Diag(Tok, diag::err_expected_unqualified_id)
+    << getLang().CPlusPlus;
+  return true;
+}
+
+/// ParseCXXNewExpression - Parse a C++ new-expression. New is used to allocate
+/// memory in a typesafe manner and call constructors.
+///
+/// This method is called to parse the new expression after the optional :: has
+/// been already parsed.  If the :: was present, "UseGlobal" is true and "Start"
+/// is its location.  Otherwise, "Start" is the location of the 'new' token.
+///
+///        new-expression:
+///                   '::'[opt] 'new' new-placement[opt] new-type-id
+///                                     new-initializer[opt]
+///                   '::'[opt] 'new' new-placement[opt] '(' type-id ')'
+///                                     new-initializer[opt]
+///
+///        new-placement:
+///                   '(' expression-list ')'
+///
+///        new-type-id:
+///                   type-specifier-seq new-declarator[opt]
+///
+///        new-declarator:
+///                   ptr-operator new-declarator[opt]
+///                   direct-new-declarator
+///
+///        new-initializer:
+///                   '(' expression-list[opt] ')'
+/// [C++0x]           braced-init-list                                   [TODO]
+///
+Parser::OwningExprResult
+Parser::ParseCXXNewExpression(bool UseGlobal, SourceLocation Start) {
+  assert(Tok.is(tok::kw_new) && "expected 'new' token");
+  ConsumeToken();   // Consume 'new'
+
+  // A '(' now can be a new-placement or the '(' wrapping the type-id in the
+  // second form of new-expression. It can't be a new-type-id.
+
+  ExprVector PlacementArgs(Actions);
+  SourceLocation PlacementLParen, PlacementRParen;
+
+  bool ParenTypeId;
+  DeclSpec DS;
+  Declarator DeclaratorInfo(DS, Declarator::TypeNameContext);
+  if (Tok.is(tok::l_paren)) {
+    // If it turns out to be a placement, we change the type location.
+    PlacementLParen = ConsumeParen();
+    if (ParseExpressionListOrTypeId(PlacementArgs, DeclaratorInfo)) {
+      SkipUntil(tok::semi, /*StopAtSemi=*/true, /*DontConsume=*/true);
+      return ExprError();
+    }
+
+    PlacementRParen = MatchRHSPunctuation(tok::r_paren, PlacementLParen);
+    if (PlacementRParen.isInvalid()) {
+      SkipUntil(tok::semi, /*StopAtSemi=*/true, /*DontConsume=*/true);
+      return ExprError();
+    }
+
+    if (PlacementArgs.empty()) {
+      // Reset the placement locations. There was no placement.
+      PlacementLParen = PlacementRParen = SourceLocation();
+      ParenTypeId = true;
+    } else {
+      // We still need the type.
+      if (Tok.is(tok::l_paren)) {
+        SourceLocation LParen = ConsumeParen();
+        ParseSpecifierQualifierList(DS);
+        DeclaratorInfo.SetSourceRange(DS.getSourceRange());
+        ParseDeclarator(DeclaratorInfo);
+        MatchRHSPunctuation(tok::r_paren, LParen);
+        ParenTypeId = true;
+      } else {
+        if (ParseCXXTypeSpecifierSeq(DS))
+          DeclaratorInfo.setInvalidType(true);
+        else {
+          DeclaratorInfo.SetSourceRange(DS.getSourceRange());
+          ParseDeclaratorInternal(DeclaratorInfo,
+                                  &Parser::ParseDirectNewDeclarator);
+        }
+        ParenTypeId = false;
+      }
+    }
+  } else {
+    // A new-type-id is a simplified type-id, where essentially the
+    // direct-declarator is replaced by a direct-new-declarator.
+    if (ParseCXXTypeSpecifierSeq(DS))
+      DeclaratorInfo.setInvalidType(true);
+    else {
+      DeclaratorInfo.SetSourceRange(DS.getSourceRange());
+      ParseDeclaratorInternal(DeclaratorInfo,
+                              &Parser::ParseDirectNewDeclarator);
+    }
+    ParenTypeId = false;
+  }
+  if (DeclaratorInfo.isInvalidType()) {
+    SkipUntil(tok::semi, /*StopAtSemi=*/true, /*DontConsume=*/true);
+    return ExprError();
+  }
+
+  ExprVector ConstructorArgs(Actions);
+  SourceLocation ConstructorLParen, ConstructorRParen;
+
+  if (Tok.is(tok::l_paren)) {
+    ConstructorLParen = ConsumeParen();
+    if (Tok.isNot(tok::r_paren)) {
+      CommaLocsTy CommaLocs;
+      if (ParseExpressionList(ConstructorArgs, CommaLocs)) {
+        SkipUntil(tok::semi, /*StopAtSemi=*/true, /*DontConsume=*/true);
+        return ExprError();
+      }
+    }
+    ConstructorRParen = MatchRHSPunctuation(tok::r_paren, ConstructorLParen);
+    if (ConstructorRParen.isInvalid()) {
+      SkipUntil(tok::semi, /*StopAtSemi=*/true, /*DontConsume=*/true);
+      return ExprError();
+    }
+  }
+
+  return Actions.ActOnCXXNew(Start, UseGlobal, PlacementLParen,
+                             move_arg(PlacementArgs), PlacementRParen,
+                             ParenTypeId, DeclaratorInfo, ConstructorLParen,
+                             move_arg(ConstructorArgs), ConstructorRParen);
+}
+
+/// ParseDirectNewDeclarator - Parses a direct-new-declarator. Intended to be
+/// passed to ParseDeclaratorInternal.
+///
+///        direct-new-declarator:
+///                   '[' expression ']'
+///                   direct-new-declarator '[' constant-expression ']'
+///
+void Parser::ParseDirectNewDeclarator(Declarator &D) {
+  // Parse the array dimensions.
+  bool first = true;
+  while (Tok.is(tok::l_square)) {
+    SourceLocation LLoc = ConsumeBracket();
+    OwningExprResult Size(first ? ParseExpression()
+                                : ParseConstantExpression());
+    if (Size.isInvalid()) {
+      // Recover
+      SkipUntil(tok::r_square);
+      return;
+    }
+    first = false;
+
+    SourceLocation RLoc = MatchRHSPunctuation(tok::r_square, LLoc);
+    D.AddTypeInfo(DeclaratorChunk::getArray(0, /*static=*/false, /*star=*/false,
+                                            Size.release(), LLoc, RLoc),
+                  RLoc);
+
+    if (RLoc.isInvalid())
+      return;
+  }
+}
+
+/// ParseExpressionListOrTypeId - Parse either an expression-list or a type-id.
+/// This ambiguity appears in the syntax of the C++ new operator.
+///
+///        new-expression:
+///                   '::'[opt] 'new' new-placement[opt] '(' type-id ')'
+///                                     new-initializer[opt]
+///
+///        new-placement:
+///                   '(' expression-list ')'
+///
+bool Parser::ParseExpressionListOrTypeId(ExprListTy &PlacementArgs,
+                                         Declarator &D) {
+  // The '(' was already consumed.
+  if (isTypeIdInParens()) {
+    ParseSpecifierQualifierList(D.getMutableDeclSpec());
+    D.SetSourceRange(D.getDeclSpec().getSourceRange());
+    ParseDeclarator(D);
+    return D.isInvalidType();
+  }
+
+  // It's not a type, it has to be an expression list.
+  // Discard the comma locations - ActOnCXXNew has enough parameters.
+  CommaLocsTy CommaLocs;
+  return ParseExpressionList(PlacementArgs, CommaLocs);
+}
+
+/// ParseCXXDeleteExpression - Parse a C++ delete-expression. Delete is used
+/// to free memory allocated by new.
+///
+/// This method is called to parse the 'delete' expression after the optional
+/// '::' has been already parsed.  If the '::' was present, "UseGlobal" is true
+/// and "Start" is its location.  Otherwise, "Start" is the location of the
+/// 'delete' token.
+///
+///        delete-expression:
+///                   '::'[opt] 'delete' cast-expression
+///                   '::'[opt] 'delete' '[' ']' cast-expression
+Parser::OwningExprResult
+Parser::ParseCXXDeleteExpression(bool UseGlobal, SourceLocation Start) {
+  assert(Tok.is(tok::kw_delete) && "Expected 'delete' keyword");
+  ConsumeToken(); // Consume 'delete'
+
+  // Array delete?
+  bool ArrayDelete = false;
+  if (Tok.is(tok::l_square)) {
+    ArrayDelete = true;
+    SourceLocation LHS = ConsumeBracket();
+    SourceLocation RHS = MatchRHSPunctuation(tok::r_square, LHS);
+    if (RHS.isInvalid())
+      return ExprError();
+  }
+
+  OwningExprResult Operand(ParseCastExpression(false));
+  if (Operand.isInvalid())
+    return move(Operand);
+
+  return Actions.ActOnCXXDelete(Start, UseGlobal, ArrayDelete, move(Operand));
+}
+
+static UnaryTypeTrait UnaryTypeTraitFromTokKind(tok::TokenKind kind) {
+  switch(kind) {
+  default: assert(false && "Not a known unary type trait.");
+  case tok::kw___has_nothrow_assign:      return UTT_HasNothrowAssign;
+  case tok::kw___has_nothrow_copy:        return UTT_HasNothrowCopy;
+  case tok::kw___has_nothrow_constructor: return UTT_HasNothrowConstructor;
+  case tok::kw___has_trivial_assign:      return UTT_HasTrivialAssign;
+  case tok::kw___has_trivial_copy:        return UTT_HasTrivialCopy;
+  case tok::kw___has_trivial_constructor: return UTT_HasTrivialConstructor;
+  case tok::kw___has_trivial_destructor:  return UTT_HasTrivialDestructor;
+  case tok::kw___has_virtual_destructor:  return UTT_HasVirtualDestructor;
+  case tok::kw___is_abstract:             return UTT_IsAbstract;
+  case tok::kw___is_class:                return UTT_IsClass;
+  case tok::kw___is_empty:                return UTT_IsEmpty;
+  case tok::kw___is_enum:                 return UTT_IsEnum;
+  case tok::kw___is_pod:                  return UTT_IsPOD;
+  case tok::kw___is_polymorphic:          return UTT_IsPolymorphic;
+  case tok::kw___is_union:                return UTT_IsUnion;
+  case tok::kw___is_literal:              return UTT_IsLiteral;
+  }
+}
+
+/// ParseUnaryTypeTrait - Parse the built-in unary type-trait
+/// pseudo-functions that allow implementation of the TR1/C++0x type traits
+/// templates.
+///
+///       primary-expression:
+/// [GNU]             unary-type-trait '(' type-id ')'
+///
+Parser::OwningExprResult Parser::ParseUnaryTypeTrait() {
+  UnaryTypeTrait UTT = UnaryTypeTraitFromTokKind(Tok.getKind());
+  SourceLocation Loc = ConsumeToken();
+
+  SourceLocation LParen = Tok.getLocation();
+  if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen))
+    return ExprError();
+
+  // FIXME: Error reporting absolutely sucks! If the this fails to parse a type
+  // there will be cryptic errors about mismatched parentheses and missing
+  // specifiers.
+  TypeResult Ty = ParseTypeName();
+
+  SourceLocation RParen = MatchRHSPunctuation(tok::r_paren, LParen);
+
+  if (Ty.isInvalid())
+    return ExprError();
+
+  return Actions.ActOnUnaryTypeTrait(UTT, Loc, LParen, Ty.get(), RParen);
+}
+
+/// ParseCXXAmbiguousParenExpression - We have parsed the left paren of a
+/// parenthesized ambiguous type-id. This uses tentative parsing to disambiguate
+/// based on the context past the parens.
+Parser::OwningExprResult
+Parser::ParseCXXAmbiguousParenExpression(ParenParseOption &ExprType,
+                                         TypeTy *&CastTy,
+                                         SourceLocation LParenLoc,
+                                         SourceLocation &RParenLoc) {
+  assert(getLang().CPlusPlus && "Should only be called for C++!");
+  assert(ExprType == CastExpr && "Compound literals are not ambiguous!");
+  assert(isTypeIdInParens() && "Not a type-id!");
+
+  OwningExprResult Result(Actions, true);
+  CastTy = 0;
+
+  // We need to disambiguate a very ugly part of the C++ syntax:
+  //
+  // (T())x;  - type-id
+  // (T())*x; - type-id
+  // (T())/x; - expression
+  // (T());   - expression
+  //
+  // The bad news is that we cannot use the specialized tentative parser, since
+  // it can only verify that the thing inside the parens can be parsed as
+  // type-id, it is not useful for determining the context past the parens.
+  //
+  // The good news is that the parser can disambiguate this part without
+  // making any unnecessary Action calls.
+  //
+  // It uses a scheme similar to parsing inline methods. The parenthesized
+  // tokens are cached, the context that follows is determined (possibly by
+  // parsing a cast-expression), and then we re-introduce the cached tokens
+  // into the token stream and parse them appropriately.
+
+  ParenParseOption ParseAs;
+  CachedTokens Toks;
+
+  // Store the tokens of the parentheses. We will parse them after we determine
+  // the context that follows them.
+  if (!ConsumeAndStoreUntil(tok::r_paren, tok::unknown, Toks, tok::semi)) {
+    // We didn't find the ')' we expected.
+    MatchRHSPunctuation(tok::r_paren, LParenLoc);
+    return ExprError();
+  }
+
+  if (Tok.is(tok::l_brace)) {
+    ParseAs = CompoundLiteral;
+  } else {
+    bool NotCastExpr;
+    // FIXME: Special-case ++ and --: "(S())++;" is not a cast-expression
+    if (Tok.is(tok::l_paren) && NextToken().is(tok::r_paren)) {
+      NotCastExpr = true;
+    } else {
+      // Try parsing the cast-expression that may follow.
+      // If it is not a cast-expression, NotCastExpr will be true and no token
+      // will be consumed.
+      Result = ParseCastExpression(false/*isUnaryExpression*/,
+                                   false/*isAddressofOperand*/,
+                                   NotCastExpr, false);
+    }
+
+    // If we parsed a cast-expression, it's really a type-id, otherwise it's
+    // an expression.
+    ParseAs = NotCastExpr ? SimpleExpr : CastExpr;
+  }
+
+  // The current token should go after the cached tokens.
+  Toks.push_back(Tok);
+  // Re-enter the stored parenthesized tokens into the token stream, so we may
+  // parse them now.
+  PP.EnterTokenStream(Toks.data(), Toks.size(),
+                      true/*DisableMacroExpansion*/, false/*OwnsTokens*/);
+  // Drop the current token and bring the first cached one. It's the same token
+  // as when we entered this function.
+  ConsumeAnyToken();
+
+  if (ParseAs >= CompoundLiteral) {
+    TypeResult Ty = ParseTypeName();
+
+    // Match the ')'.
+    if (Tok.is(tok::r_paren))
+      RParenLoc = ConsumeParen();
+    else
+      MatchRHSPunctuation(tok::r_paren, LParenLoc);
+
+    if (ParseAs == CompoundLiteral) {
+      ExprType = CompoundLiteral;
+      return ParseCompoundLiteralExpression(Ty.get(), LParenLoc, RParenLoc);
+    }
+
+    // We parsed '(' type-id ')' and the thing after it wasn't a '{'.
+    assert(ParseAs == CastExpr);
+
+    if (Ty.isInvalid())
+      return ExprError();
+
+    CastTy = Ty.get();
+
+    // Result is what ParseCastExpression returned earlier.
+    if (!Result.isInvalid())
+      Result = Actions.ActOnCastExpr(CurScope, LParenLoc, CastTy, RParenLoc,
+                                     move(Result));
+    return move(Result);
+  }
+
+  // Not a compound literal, and not followed by a cast-expression.
+  assert(ParseAs == SimpleExpr);
+
+  ExprType = SimpleExpr;
+  Result = ParseExpression();
+  if (!Result.isInvalid() && Tok.is(tok::r_paren))
+    Result = Actions.ActOnParenExpr(LParenLoc, Tok.getLocation(), move(Result));
+
+  // Match the ')'.
+  if (Result.isInvalid()) {
+    SkipUntil(tok::r_paren);
+    return ExprError();
+  }
+
+  if (Tok.is(tok::r_paren))
+    RParenLoc = ConsumeParen();
+  else
+    MatchRHSPunctuation(tok::r_paren, LParenLoc);
+
+  return move(Result);
+}
diff --git a/lib/Parse/ParseInit.cpp b/lib/Parse/ParseInit.cpp
new file mode 100644
index 0000000..c4e79ca
--- /dev/null
+++ b/lib/Parse/ParseInit.cpp
@@ -0,0 +1,309 @@
+//===--- ParseInit.cpp - Initializer Parsing ------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements initializer parsing as specified by C99 6.7.8.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Parse/Designator.h"
+#include "clang/Parse/Parser.h"
+#include "clang/Parse/ParseDiagnostic.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/Support/raw_ostream.h"
+using namespace clang;
+
+
+/// MayBeDesignationStart - Return true if this token might be the start of a
+/// designator.  If we can tell it is impossible that it is a designator, return
+/// false.
+static bool MayBeDesignationStart(tok::TokenKind K, Preprocessor &PP) {
+  switch (K) {
+  default: return false;
+  case tok::period:      // designator: '.' identifier
+  case tok::l_square:    // designator: array-designator
+      return true;
+  case tok::identifier:  // designation: identifier ':'
+    return PP.LookAhead(0).is(tok::colon);
+  }
+}
+
+/// ParseInitializerWithPotentialDesignator - Parse the 'initializer' production
+/// checking to see if the token stream starts with a designator.
+///
+///       designation:
+///         designator-list '='
+/// [GNU]   array-designator
+/// [GNU]   identifier ':'
+///
+///       designator-list:
+///         designator
+///         designator-list designator
+///
+///       designator:
+///         array-designator
+///         '.' identifier
+///
+///       array-designator:
+///         '[' constant-expression ']'
+/// [GNU]   '[' constant-expression '...' constant-expression ']'
+///
+/// NOTE: [OBC] allows '[ objc-receiver objc-message-args ]' as an
+/// initializer (because it is an expression).  We need to consider this case
+/// when parsing array designators.
+///
+Parser::OwningExprResult Parser::ParseInitializerWithPotentialDesignator() {
+
+  // If this is the old-style GNU extension:
+  //   designation ::= identifier ':'
+  // Handle it as a field designator.  Otherwise, this must be the start of a
+  // normal expression.
+  if (Tok.is(tok::identifier)) {
+    const IdentifierInfo *FieldName = Tok.getIdentifierInfo();
+
+    llvm::SmallString<256> NewSyntax;
+    llvm::raw_svector_ostream(NewSyntax) << '.' << FieldName->getName()
+                                         << " = ";
+
+    SourceLocation NameLoc = ConsumeToken(); // Eat the identifier.
+
+    assert(Tok.is(tok::colon) && "MayBeDesignationStart not working properly!");
+    SourceLocation ColonLoc = ConsumeToken();
+
+    Diag(Tok, diag::ext_gnu_old_style_field_designator)
+      << CodeModificationHint::CreateReplacement(SourceRange(NameLoc,
+                                                             ColonLoc),
+                                                 NewSyntax.str());
+
+    Designation D;
+    D.AddDesignator(Designator::getField(FieldName, SourceLocation(), NameLoc));
+    return Actions.ActOnDesignatedInitializer(D, ColonLoc, true,
+                                              ParseInitializer());
+  }
+
+  // Desig - This is initialized when we see our first designator.  We may have
+  // an objc message send with no designator, so we don't want to create this
+  // eagerly.
+  Designation Desig;
+
+  // Parse each designator in the designator list until we find an initializer.
+  while (Tok.is(tok::period) || Tok.is(tok::l_square)) {
+    if (Tok.is(tok::period)) {
+      // designator: '.' identifier
+      SourceLocation DotLoc = ConsumeToken();
+
+      if (Tok.isNot(tok::identifier)) {
+        Diag(Tok.getLocation(), diag::err_expected_field_designator);
+        return ExprError();
+      }
+
+      Desig.AddDesignator(Designator::getField(Tok.getIdentifierInfo(), DotLoc,
+                                               Tok.getLocation()));
+      ConsumeToken(); // Eat the identifier.
+      continue;
+    }
+
+    // We must have either an array designator now or an objc message send.
+    assert(Tok.is(tok::l_square) && "Unexpected token!");
+
+    // Handle the two forms of array designator:
+    //   array-designator: '[' constant-expression ']'
+    //   array-designator: '[' constant-expression '...' constant-expression ']'
+    //
+    // Also, we have to handle the case where the expression after the
+    // designator an an objc message send: '[' objc-message-expr ']'.
+    // Interesting cases are:
+    //   [foo bar]         -> objc message send
+    //   [foo]             -> array designator
+    //   [foo ... bar]     -> array designator
+    //   [4][foo bar]      -> obsolete GNU designation with objc message send.
+    //
+    SourceLocation StartLoc = ConsumeBracket();
+
+    // If Objective-C is enabled and this is a typename or other identifier
+    // receiver, parse this as a message send expression.
+    if (getLang().ObjC1 && isTokObjCMessageIdentifierReceiver()) {
+      // If we have exactly one array designator, this used the GNU
+      // 'designation: array-designator' extension, otherwise there should be no
+      // designators at all!
+      if (Desig.getNumDesignators() == 1 &&
+          (Desig.getDesignator(0).isArrayDesignator() ||
+           Desig.getDesignator(0).isArrayRangeDesignator()))
+        Diag(StartLoc, diag::ext_gnu_missing_equal_designator);
+      else if (Desig.getNumDesignators() > 0)
+        Diag(Tok, diag::err_expected_equal_designator);
+
+      IdentifierInfo *Name = Tok.getIdentifierInfo();
+      SourceLocation NameLoc = ConsumeToken();
+      return ParseAssignmentExprWithObjCMessageExprStart(
+                       StartLoc, NameLoc, Name, ExprArg(Actions));
+    }
+
+    // Note that we parse this as an assignment expression, not a constant
+    // expression (allowing *=, =, etc) to handle the objc case.  Sema needs
+    // to validate that the expression is a constant.
+    OwningExprResult Idx(ParseAssignmentExpression());
+    if (Idx.isInvalid()) {
+      SkipUntil(tok::r_square);
+      return move(Idx);
+    }
+
+    // Given an expression, we could either have a designator (if the next
+    // tokens are '...' or ']' or an objc message send.  If this is an objc
+    // message send, handle it now.  An objc-message send is the start of
+    // an assignment-expression production.
+    if (getLang().ObjC1 && Tok.isNot(tok::ellipsis) &&
+        Tok.isNot(tok::r_square)) {
+
+      // If we have exactly one array designator, this used the GNU
+      // 'designation: array-designator' extension, otherwise there should be no
+      // designators at all!
+      if (Desig.getNumDesignators() == 1 &&
+          (Desig.getDesignator(0).isArrayDesignator() ||
+           Desig.getDesignator(0).isArrayRangeDesignator()))
+        Diag(StartLoc, diag::ext_gnu_missing_equal_designator);
+      else if (Desig.getNumDesignators() > 0)
+        Diag(Tok, diag::err_expected_equal_designator);
+
+      return ParseAssignmentExprWithObjCMessageExprStart(StartLoc,
+                                                         SourceLocation(),
+                                                         0, move(Idx));
+    }
+
+    // If this is a normal array designator, remember it.
+    if (Tok.isNot(tok::ellipsis)) {
+      Desig.AddDesignator(Designator::getArray(Idx.release(), StartLoc));
+    } else {
+      // Handle the gnu array range extension.
+      Diag(Tok, diag::ext_gnu_array_range);
+      SourceLocation EllipsisLoc = ConsumeToken();
+
+      OwningExprResult RHS(ParseConstantExpression());
+      if (RHS.isInvalid()) {
+        SkipUntil(tok::r_square);
+        return move(RHS);
+      }
+      Desig.AddDesignator(Designator::getArrayRange(Idx.release(),
+                                                    RHS.release(),
+                                                    StartLoc, EllipsisLoc));
+    }
+
+    SourceLocation EndLoc = MatchRHSPunctuation(tok::r_square, StartLoc);
+    Desig.getDesignator(Desig.getNumDesignators() - 1).setRBracketLoc(EndLoc);
+  }
+
+  // Okay, we're done with the designator sequence.  We know that there must be
+  // at least one designator, because the only case we can get into this method
+  // without a designator is when we have an objc message send.  That case is
+  // handled and returned from above.
+  assert(!Desig.empty() && "Designator is empty?");
+
+  // Handle a normal designator sequence end, which is an equal.
+  if (Tok.is(tok::equal)) {
+    SourceLocation EqualLoc = ConsumeToken();
+    return Actions.ActOnDesignatedInitializer(Desig, EqualLoc, false,
+                                              ParseInitializer());
+  }
+
+  // We read some number of designators and found something that isn't an = or
+  // an initializer.  If we have exactly one array designator, this
+  // is the GNU 'designation: array-designator' extension.  Otherwise, it is a
+  // parse error.
+  if (Desig.getNumDesignators() == 1 &&
+      (Desig.getDesignator(0).isArrayDesignator() ||
+       Desig.getDesignator(0).isArrayRangeDesignator())) {
+    Diag(Tok, diag::ext_gnu_missing_equal_designator)
+      << CodeModificationHint::CreateInsertion(Tok.getLocation(), "= ");
+    return Actions.ActOnDesignatedInitializer(Desig, Tok.getLocation(),
+                                              true, ParseInitializer());
+  }
+
+  Diag(Tok, diag::err_expected_equal_designator);
+  return ExprError();
+}
+
+
+/// ParseBraceInitializer - Called when parsing an initializer that has a
+/// leading open brace.
+///
+///       initializer: [C99 6.7.8]
+///         '{' initializer-list '}'
+///         '{' initializer-list ',' '}'
+/// [GNU]   '{' '}'
+///
+///       initializer-list:
+///         designation[opt] initializer
+///         initializer-list ',' designation[opt] initializer
+///
+Parser::OwningExprResult Parser::ParseBraceInitializer() {
+  SourceLocation LBraceLoc = ConsumeBrace();
+
+  /// InitExprs - This is the actual list of expressions contained in the
+  /// initializer.
+  ExprVector InitExprs(Actions);
+
+  if (Tok.is(tok::r_brace)) {
+    // Empty initializers are a C++ feature and a GNU extension to C.
+    if (!getLang().CPlusPlus)
+      Diag(LBraceLoc, diag::ext_gnu_empty_initializer);
+    // Match the '}'.
+    return Actions.ActOnInitList(LBraceLoc, Action::MultiExprArg(Actions),
+                                 ConsumeBrace());
+  }
+
+  bool InitExprsOk = true;
+
+  while (1) {
+    // Parse: designation[opt] initializer
+
+    // If we know that this cannot be a designation, just parse the nested
+    // initializer directly.
+    OwningExprResult SubElt(Actions);
+    if (MayBeDesignationStart(Tok.getKind(), PP))
+      SubElt = ParseInitializerWithPotentialDesignator();
+    else
+      SubElt = ParseInitializer();
+
+    // If we couldn't parse the subelement, bail out.
+    if (!SubElt.isInvalid()) {
+      InitExprs.push_back(SubElt.release());
+    } else {
+      InitExprsOk = false;
+
+      // We have two ways to try to recover from this error: if the code looks
+      // gramatically ok (i.e. we have a comma coming up) try to continue
+      // parsing the rest of the initializer.  This allows us to emit
+      // diagnostics for later elements that we find.  If we don't see a comma,
+      // assume there is a parse error, and just skip to recover.
+      // FIXME: This comment doesn't sound right. If there is a r_brace
+      // immediately, it can't be an error, since there is no other way of
+      // leaving this loop except through this if.
+      if (Tok.isNot(tok::comma)) {
+        SkipUntil(tok::r_brace, false, true);
+        break;
+      }
+    }
+
+    // If we don't have a comma continued list, we're done.
+    if (Tok.isNot(tok::comma)) break;
+
+    // TODO: save comma locations if some client cares.
+    ConsumeToken();
+
+    // Handle trailing comma.
+    if (Tok.is(tok::r_brace)) break;
+  }
+  if (InitExprsOk && Tok.is(tok::r_brace))
+    return Actions.ActOnInitList(LBraceLoc, move_arg(InitExprs),
+                                 ConsumeBrace());
+
+  // Match the '}'.
+  MatchRHSPunctuation(tok::r_brace, LBraceLoc);
+  return ExprError(); // an error occurred.
+}
+
diff --git a/lib/Parse/ParseObjc.cpp b/lib/Parse/ParseObjc.cpp
new file mode 100644
index 0000000..ef65204
--- /dev/null
+++ b/lib/Parse/ParseObjc.cpp
@@ -0,0 +1,1942 @@
+//===--- ParseObjC.cpp - Objective C Parsing ------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file 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/Parse/DeclSpec.h"
+#include "clang/Parse/Scope.h"
+#include "clang/Parse/ParseDiagnostic.h"
+#include "llvm/ADT/SmallVector.h"
+using namespace clang;
+
+
+/// ParseObjCAtDirectives - Handle parts of the external-declaration production:
+///       external-declaration: [C99 6.9]
+/// [OBJC]  objc-class-definition
+/// [OBJC]  objc-class-declaration
+/// [OBJC]  objc-alias-declaration
+/// [OBJC]  objc-protocol-definition
+/// [OBJC]  objc-method-definition
+/// [OBJC]  '@' 'end'
+Parser::DeclPtrTy Parser::ParseObjCAtDirectives() {
+  SourceLocation AtLoc = ConsumeToken(); // the "@"
+
+  if (Tok.is(tok::code_completion)) {
+    Actions.CodeCompleteObjCAtDirective(CurScope, ObjCImpDecl, false);
+    ConsumeToken();
+  }
+
+  switch (Tok.getObjCKeywordID()) {
+  case tok::objc_class:
+    return ParseObjCAtClassDeclaration(AtLoc);
+  case tok::objc_interface:
+    return ParseObjCAtInterfaceDeclaration(AtLoc);
+  case tok::objc_protocol:
+    return ParseObjCAtProtocolDeclaration(AtLoc);
+  case tok::objc_implementation:
+    return ParseObjCAtImplementationDeclaration(AtLoc);
+  case tok::objc_end:
+    return ParseObjCAtEndDeclaration(AtLoc);
+  case tok::objc_compatibility_alias:
+    return ParseObjCAtAliasDeclaration(AtLoc);
+  case tok::objc_synthesize:
+    return ParseObjCPropertySynthesize(AtLoc);
+  case tok::objc_dynamic:
+    return ParseObjCPropertyDynamic(AtLoc);
+  default:
+    Diag(AtLoc, diag::err_unexpected_at);
+    SkipUntil(tok::semi);
+    return DeclPtrTy();
+  }
+}
+
+///
+/// objc-class-declaration:
+///    '@' 'class' identifier-list ';'
+///
+Parser::DeclPtrTy Parser::ParseObjCAtClassDeclaration(SourceLocation atLoc) {
+  ConsumeToken(); // the identifier "class"
+  llvm::SmallVector<IdentifierInfo *, 8> ClassNames;
+  llvm::SmallVector<SourceLocation, 8> ClassLocs;
+
+
+  while (1) {
+    if (Tok.isNot(tok::identifier)) {
+      Diag(Tok, diag::err_expected_ident);
+      SkipUntil(tok::semi);
+      return DeclPtrTy();
+    }
+    ClassNames.push_back(Tok.getIdentifierInfo());
+    ClassLocs.push_back(Tok.getLocation());
+    ConsumeToken();
+
+    if (Tok.isNot(tok::comma))
+      break;
+
+    ConsumeToken();
+  }
+
+  // Consume the ';'.
+  if (ExpectAndConsume(tok::semi, diag::err_expected_semi_after, "@class"))
+    return DeclPtrTy();
+
+  return Actions.ActOnForwardClassDeclaration(atLoc, ClassNames.data(),
+                                              ClassLocs.data(),
+                                              ClassNames.size());
+}
+
+///
+///   objc-interface:
+///     objc-class-interface-attributes[opt] objc-class-interface
+///     objc-category-interface
+///
+///   objc-class-interface:
+///     '@' 'interface' identifier objc-superclass[opt]
+///       objc-protocol-refs[opt]
+///       objc-class-instance-variables[opt]
+///       objc-interface-decl-list
+///     @end
+///
+///   objc-category-interface:
+///     '@' 'interface' identifier '(' identifier[opt] ')'
+///       objc-protocol-refs[opt]
+///       objc-interface-decl-list
+///     @end
+///
+///   objc-superclass:
+///     ':' identifier
+///
+///   objc-class-interface-attributes:
+///     __attribute__((visibility("default")))
+///     __attribute__((visibility("hidden")))
+///     __attribute__((deprecated))
+///     __attribute__((unavailable))
+///     __attribute__((objc_exception)) - used by NSException on 64-bit
+///
+Parser::DeclPtrTy Parser::ParseObjCAtInterfaceDeclaration(
+  SourceLocation atLoc, AttributeList *attrList) {
+  assert(Tok.isObjCAtKeyword(tok::objc_interface) &&
+         "ParseObjCAtInterfaceDeclaration(): Expected @interface");
+  ConsumeToken(); // the "interface" identifier
+
+  // Code completion after '@interface'.
+  if (Tok.is(tok::code_completion)) {
+    Actions.CodeCompleteObjCInterfaceDecl(CurScope);
+    ConsumeToken();
+  }
+
+  if (Tok.isNot(tok::identifier)) {
+    Diag(Tok, diag::err_expected_ident); // missing class or category name.
+    return DeclPtrTy();
+  }
+
+  // We have a class or category name - consume it.
+  IdentifierInfo *nameId = Tok.getIdentifierInfo();
+  SourceLocation nameLoc = ConsumeToken();
+
+  if (Tok.is(tok::l_paren)) { // we have a category.
+    SourceLocation lparenLoc = ConsumeParen();
+    SourceLocation categoryLoc, rparenLoc;
+    IdentifierInfo *categoryId = 0;
+
+    if (Tok.is(tok::code_completion)) {
+      Actions.CodeCompleteObjCInterfaceCategory(CurScope, nameId);
+      ConsumeToken();
+    }
+    
+    // For ObjC2, the category name is optional (not an error).
+    if (Tok.is(tok::identifier)) {
+      categoryId = Tok.getIdentifierInfo();
+      categoryLoc = ConsumeToken();
+    } else if (!getLang().ObjC2) {
+      Diag(Tok, diag::err_expected_ident); // missing category name.
+      return DeclPtrTy();
+    }
+    if (Tok.isNot(tok::r_paren)) {
+      Diag(Tok, diag::err_expected_rparen);
+      SkipUntil(tok::r_paren, false); // don't stop at ';'
+      return DeclPtrTy();
+    }
+    rparenLoc = ConsumeParen();
+
+    // Next, we need to check for any protocol references.
+    SourceLocation LAngleLoc, EndProtoLoc;
+    llvm::SmallVector<DeclPtrTy, 8> ProtocolRefs;
+    llvm::SmallVector<SourceLocation, 8> ProtocolLocs;
+    if (Tok.is(tok::less) &&
+        ParseObjCProtocolReferences(ProtocolRefs, ProtocolLocs, true,
+                                    LAngleLoc, EndProtoLoc))
+      return DeclPtrTy();
+
+    if (attrList) // categories don't support attributes.
+      Diag(Tok, diag::err_objc_no_attributes_on_category);
+
+    DeclPtrTy CategoryType =
+      Actions.ActOnStartCategoryInterface(atLoc,
+                                          nameId, nameLoc,
+                                          categoryId, categoryLoc,
+                                          ProtocolRefs.data(),
+                                          ProtocolRefs.size(),
+                                          ProtocolLocs.data(),
+                                          EndProtoLoc);
+
+    ParseObjCInterfaceDeclList(CategoryType, tok::objc_not_keyword);
+    return CategoryType;
+  }
+  // Parse a class interface.
+  IdentifierInfo *superClassId = 0;
+  SourceLocation superClassLoc;
+
+  if (Tok.is(tok::colon)) { // a super class is specified.
+    ConsumeToken();
+
+    // Code completion of superclass names.
+    if (Tok.is(tok::code_completion)) {
+      Actions.CodeCompleteObjCSuperclass(CurScope, nameId);
+      ConsumeToken();
+    }
+
+    if (Tok.isNot(tok::identifier)) {
+      Diag(Tok, diag::err_expected_ident); // missing super class name.
+      return DeclPtrTy();
+    }
+    superClassId = Tok.getIdentifierInfo();
+    superClassLoc = ConsumeToken();
+  }
+  // Next, we need to check for any protocol references.
+  llvm::SmallVector<Action::DeclPtrTy, 8> ProtocolRefs;
+  llvm::SmallVector<SourceLocation, 8> ProtocolLocs;
+  SourceLocation LAngleLoc, EndProtoLoc;
+  if (Tok.is(tok::less) &&
+      ParseObjCProtocolReferences(ProtocolRefs, ProtocolLocs, true,
+                                  LAngleLoc, EndProtoLoc))
+    return DeclPtrTy();
+
+  DeclPtrTy ClsType =
+    Actions.ActOnStartClassInterface(atLoc, nameId, nameLoc,
+                                     superClassId, superClassLoc,
+                                     ProtocolRefs.data(), ProtocolRefs.size(),
+                                     ProtocolLocs.data(),
+                                     EndProtoLoc, attrList);
+
+  if (Tok.is(tok::l_brace))
+    ParseObjCClassInstanceVariables(ClsType, atLoc);
+
+  ParseObjCInterfaceDeclList(ClsType, tok::objc_interface);
+  return ClsType;
+}
+
+/// The Objective-C property callback.  This should be defined where
+/// it's used, but instead it's been lifted to here to support VS2005.
+struct Parser::ObjCPropertyCallback : FieldCallback {
+  Parser &P;
+  DeclPtrTy IDecl;
+  llvm::SmallVectorImpl<DeclPtrTy> &Props;
+  ObjCDeclSpec &OCDS;
+  SourceLocation AtLoc;
+  tok::ObjCKeywordKind MethodImplKind;
+        
+  ObjCPropertyCallback(Parser &P, DeclPtrTy IDecl,
+                       llvm::SmallVectorImpl<DeclPtrTy> &Props,
+                       ObjCDeclSpec &OCDS, SourceLocation AtLoc,
+                       tok::ObjCKeywordKind MethodImplKind) :
+    P(P), IDecl(IDecl), Props(Props), OCDS(OCDS), AtLoc(AtLoc),
+    MethodImplKind(MethodImplKind) {
+  }
+
+  DeclPtrTy invoke(FieldDeclarator &FD) {
+    if (FD.D.getIdentifier() == 0) {
+      P.Diag(AtLoc, diag::err_objc_property_requires_field_name)
+        << FD.D.getSourceRange();
+      return DeclPtrTy();
+    }
+    if (FD.BitfieldSize) {
+      P.Diag(AtLoc, diag::err_objc_property_bitfield)
+        << FD.D.getSourceRange();
+      return DeclPtrTy();
+    }
+
+    // Install the property declarator into interfaceDecl.
+    IdentifierInfo *SelName =
+      OCDS.getGetterName() ? OCDS.getGetterName() : FD.D.getIdentifier();
+
+    Selector GetterSel =
+      P.PP.getSelectorTable().getNullarySelector(SelName);
+    IdentifierInfo *SetterName = OCDS.getSetterName();
+    Selector SetterSel;
+    if (SetterName)
+      SetterSel = P.PP.getSelectorTable().getSelector(1, &SetterName);
+    else
+      SetterSel = SelectorTable::constructSetterName(P.PP.getIdentifierTable(),
+                                                     P.PP.getSelectorTable(),
+                                                     FD.D.getIdentifier());
+    bool isOverridingProperty = false;
+    DeclPtrTy Property =
+      P.Actions.ActOnProperty(P.CurScope, AtLoc, FD, OCDS,
+                              GetterSel, SetterSel, IDecl,
+                              &isOverridingProperty,
+                              MethodImplKind);
+    if (!isOverridingProperty)
+      Props.push_back(Property);
+
+    return Property;
+  }
+};
+
+///   objc-interface-decl-list:
+///     empty
+///     objc-interface-decl-list objc-property-decl [OBJC2]
+///     objc-interface-decl-list objc-method-requirement [OBJC2]
+///     objc-interface-decl-list objc-method-proto ';'
+///     objc-interface-decl-list declaration
+///     objc-interface-decl-list ';'
+///
+///   objc-method-requirement: [OBJC2]
+///     @required
+///     @optional
+///
+void Parser::ParseObjCInterfaceDeclList(DeclPtrTy interfaceDecl,
+                                        tok::ObjCKeywordKind contextKey) {
+  llvm::SmallVector<DeclPtrTy, 32> allMethods;
+  llvm::SmallVector<DeclPtrTy, 16> allProperties;
+  llvm::SmallVector<DeclGroupPtrTy, 8> allTUVariables;
+  tok::ObjCKeywordKind MethodImplKind = tok::objc_not_keyword;
+
+  SourceRange AtEnd;
+
+  while (1) {
+    // If this is a method prototype, parse it.
+    if (Tok.is(tok::minus) || Tok.is(tok::plus)) {
+      DeclPtrTy methodPrototype =
+        ParseObjCMethodPrototype(interfaceDecl, MethodImplKind);
+      allMethods.push_back(methodPrototype);
+      // Consume the ';' here, since ParseObjCMethodPrototype() is re-used for
+      // method definitions.
+      ExpectAndConsume(tok::semi, diag::err_expected_semi_after_method_proto,
+                       "", tok::semi);
+      continue;
+    }
+
+    // Ignore excess semicolons.
+    if (Tok.is(tok::semi)) {
+      ConsumeToken();
+      continue;
+    }
+
+    // If we got to the end of the file, exit the loop.
+    if (Tok.is(tok::eof))
+      break;
+
+    // Code completion within an Objective-C interface.
+    if (Tok.is(tok::code_completion)) {
+      Actions.CodeCompleteOrdinaryName(CurScope, 
+                                  ObjCImpDecl? Action::CCC_ObjCImplementation
+                                             : Action::CCC_ObjCInterface);
+      ConsumeToken();
+    }
+    
+    // If we don't have an @ directive, parse it as a function definition.
+    if (Tok.isNot(tok::at)) {
+      // The code below does not consume '}'s because it is afraid of eating the
+      // end of a namespace.  Because of the way this code is structured, an
+      // erroneous r_brace would cause an infinite loop if not handled here.
+      if (Tok.is(tok::r_brace))
+        break;
+
+      // FIXME: as the name implies, this rule allows function definitions.
+      // We could pass a flag or check for functions during semantic analysis.
+      allTUVariables.push_back(ParseDeclarationOrFunctionDefinition(0));
+      continue;
+    }
+
+    // Otherwise, we have an @ directive, eat the @.
+    SourceLocation AtLoc = ConsumeToken(); // the "@"
+    if (Tok.is(tok::code_completion)) {
+      Actions.CodeCompleteObjCAtDirective(CurScope, ObjCImpDecl, true);
+      ConsumeToken();
+      break;
+    }
+
+    tok::ObjCKeywordKind DirectiveKind = Tok.getObjCKeywordID();
+
+    if (DirectiveKind == tok::objc_end) { // @end -> terminate list
+      AtEnd.setBegin(AtLoc);
+      AtEnd.setEnd(Tok.getLocation());
+      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(AtLoc, diag::err_objc_illegal_interface_qual);
+      // Skip until we see an '@' or '}' or ';'.
+      SkipUntil(tok::r_brace, tok::at);
+      break;
+
+    case tok::objc_required:
+    case tok::objc_optional:
+      // This is only valid on protocols.
+      // FIXME: Should this check for ObjC2 being enabled?
+      if (contextKey != tok::objc_protocol)
+        Diag(AtLoc, diag::err_objc_directive_only_in_protocol);
+      else
+        MethodImplKind = DirectiveKind;
+      break;
+
+    case tok::objc_property:
+      if (!getLang().ObjC2)
+        Diag(AtLoc, diag::err_objc_propertoes_require_objc2);
+
+      ObjCDeclSpec OCDS;
+      // Parse property attribute list, if any.
+      if (Tok.is(tok::l_paren))
+        ParseObjCPropertyAttribute(OCDS, interfaceDecl,
+                                   allMethods.data(), allMethods.size());
+
+      ObjCPropertyCallback Callback(*this, interfaceDecl, allProperties,
+                                    OCDS, AtLoc, MethodImplKind);
+
+      // Parse all the comma separated declarators.
+      DeclSpec DS;
+      ParseStructDeclaration(DS, Callback);
+
+      ExpectAndConsume(tok::semi, diag::err_expected_semi_decl_list, "",
+                       tok::at);
+      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.is(tok::code_completion)) {
+    Actions.CodeCompleteObjCAtDirective(CurScope, ObjCImpDecl, true);
+    ConsumeToken();
+  } else 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.
+  // This passes in an invalid SourceLocation for AtEndLoc when EOF is hit.
+  Actions.ActOnAtEnd(AtEnd, interfaceDecl,
+                     allMethods.data(), allMethods.size(),
+                     allProperties.data(), allProperties.size(),
+                     allTUVariables.data(), allTUVariables.size());
+}
+
+///   Parse property attribute declarations.
+///
+///   property-attr-decl: '(' property-attrlist ')'
+///   property-attrlist:
+///     property-attribute
+///     property-attrlist ',' property-attribute
+///   property-attribute:
+///     getter '=' identifier
+///     setter '=' identifier ':'
+///     readonly
+///     readwrite
+///     assign
+///     retain
+///     copy
+///     nonatomic
+///
+void Parser::ParseObjCPropertyAttribute(ObjCDeclSpec &DS, DeclPtrTy ClassDecl,
+                                        DeclPtrTy *Methods, 
+                                        unsigned NumMethods) {
+  assert(Tok.getKind() == tok::l_paren);
+  SourceLocation LHSLoc = ConsumeParen(); // consume '('
+
+  while (1) {
+    if (Tok.is(tok::code_completion)) {
+      Actions.CodeCompleteObjCPropertyFlags(CurScope, DS);
+      ConsumeToken();
+    }
+    const IdentifierInfo *II = Tok.getIdentifierInfo();
+
+    // If this is not an identifier at all, bail out early.
+    if (II == 0) {
+      MatchRHSPunctuation(tok::r_paren, LHSLoc);
+      return;
+    }
+
+    SourceLocation AttrName = ConsumeToken(); // consume last attribute name
+
+    if (II->isStr("readonly"))
+      DS.setPropertyAttributes(ObjCDeclSpec::DQ_PR_readonly);
+    else if (II->isStr("assign"))
+      DS.setPropertyAttributes(ObjCDeclSpec::DQ_PR_assign);
+    else if (II->isStr("readwrite"))
+      DS.setPropertyAttributes(ObjCDeclSpec::DQ_PR_readwrite);
+    else if (II->isStr("retain"))
+      DS.setPropertyAttributes(ObjCDeclSpec::DQ_PR_retain);
+    else if (II->isStr("copy"))
+      DS.setPropertyAttributes(ObjCDeclSpec::DQ_PR_copy);
+    else if (II->isStr("nonatomic"))
+      DS.setPropertyAttributes(ObjCDeclSpec::DQ_PR_nonatomic);
+    else if (II->isStr("getter") || II->isStr("setter")) {
+      // getter/setter require extra treatment.
+      if (ExpectAndConsume(tok::equal, diag::err_objc_expected_equal, "",
+                           tok::r_paren))
+        return;
+
+      if (Tok.is(tok::code_completion)) {
+        if (II->getNameStart()[0] == 's')
+          Actions.CodeCompleteObjCPropertySetter(CurScope, ClassDecl,
+                                                 Methods, NumMethods);
+        else
+          Actions.CodeCompleteObjCPropertyGetter(CurScope, ClassDecl,
+                                                 Methods, NumMethods);
+        ConsumeToken();
+      }
+
+      if (Tok.isNot(tok::identifier)) {
+        Diag(Tok, diag::err_expected_ident);
+        SkipUntil(tok::r_paren);
+        return;
+      }
+
+      if (II->getNameStart()[0] == 's') {
+        DS.setPropertyAttributes(ObjCDeclSpec::DQ_PR_setter);
+        DS.setSetterName(Tok.getIdentifierInfo());
+        ConsumeToken();  // consume method name
+
+        if (ExpectAndConsume(tok::colon, diag::err_expected_colon, "",
+                             tok::r_paren))
+          return;
+      } else {
+        DS.setPropertyAttributes(ObjCDeclSpec::DQ_PR_getter);
+        DS.setGetterName(Tok.getIdentifierInfo());
+        ConsumeToken();  // consume method name
+      }
+    } else {
+      Diag(AttrName, diag::err_objc_expected_property_attr) << II;
+      SkipUntil(tok::r_paren);
+      return;
+    }
+
+    if (Tok.isNot(tok::comma))
+      break;
+
+    ConsumeToken();
+  }
+
+  MatchRHSPunctuation(tok::r_paren, LHSLoc);
+}
+
+///   objc-method-proto:
+///     objc-instance-method objc-method-decl objc-method-attributes[opt]
+///     objc-class-method objc-method-decl objc-method-attributes[opt]
+///
+///   objc-instance-method: '-'
+///   objc-class-method: '+'
+///
+///   objc-method-attributes:         [OBJC2]
+///     __attribute__((deprecated))
+///
+Parser::DeclPtrTy Parser::ParseObjCMethodPrototype(DeclPtrTy IDecl,
+                                          tok::ObjCKeywordKind MethodImplKind) {
+  assert((Tok.is(tok::minus) || Tok.is(tok::plus)) && "expected +/-");
+
+  tok::TokenKind methodType = Tok.getKind();
+  SourceLocation mLoc = ConsumeToken();
+
+  DeclPtrTy MDecl = ParseObjCMethodDecl(mLoc, methodType, IDecl,MethodImplKind);
+  // Since this rule is used for both method declarations and definitions,
+  // the caller is (optionally) responsible for consuming the ';'.
+  return MDecl;
+}
+
+///   objc-selector:
+///     identifier
+///     one of
+///       enum struct union if else while do for switch case default
+///       break continue return goto asm sizeof typeof __alignof
+///       unsigned long const short volatile signed restrict _Complex
+///       in out inout bycopy byref oneway int char float double void _Bool
+///
+IdentifierInfo *Parser::ParseObjCSelectorPiece(SourceLocation &SelectorLoc) {
+  switch (Tok.getKind()) {
+  default:
+    return 0;
+  case tok::identifier:
+  case tok::kw_asm:
+  case tok::kw_auto:
+  case tok::kw_bool:
+  case tok::kw_break:
+  case tok::kw_case:
+  case tok::kw_catch:
+  case tok::kw_char:
+  case tok::kw_class:
+  case tok::kw_const:
+  case tok::kw_const_cast:
+  case tok::kw_continue:
+  case tok::kw_default:
+  case tok::kw_delete:
+  case tok::kw_do:
+  case tok::kw_double:
+  case tok::kw_dynamic_cast:
+  case tok::kw_else:
+  case tok::kw_enum:
+  case tok::kw_explicit:
+  case tok::kw_export:
+  case tok::kw_extern:
+  case tok::kw_false:
+  case tok::kw_float:
+  case tok::kw_for:
+  case tok::kw_friend:
+  case tok::kw_goto:
+  case tok::kw_if:
+  case tok::kw_inline:
+  case tok::kw_int:
+  case tok::kw_long:
+  case tok::kw_mutable:
+  case tok::kw_namespace:
+  case tok::kw_new:
+  case tok::kw_operator:
+  case tok::kw_private:
+  case tok::kw_protected:
+  case tok::kw_public:
+  case tok::kw_register:
+  case tok::kw_reinterpret_cast:
+  case tok::kw_restrict:
+  case tok::kw_return:
+  case tok::kw_short:
+  case tok::kw_signed:
+  case tok::kw_sizeof:
+  case tok::kw_static:
+  case tok::kw_static_cast:
+  case tok::kw_struct:
+  case tok::kw_switch:
+  case tok::kw_template:
+  case tok::kw_this:
+  case tok::kw_throw:
+  case tok::kw_true:
+  case tok::kw_try:
+  case tok::kw_typedef:
+  case tok::kw_typeid:
+  case tok::kw_typename:
+  case tok::kw_typeof:
+  case tok::kw_union:
+  case tok::kw_unsigned:
+  case tok::kw_using:
+  case tok::kw_virtual:
+  case tok::kw_void:
+  case tok::kw_volatile:
+  case tok::kw_wchar_t:
+  case tok::kw_while:
+  case tok::kw__Bool:
+  case tok::kw__Complex:
+  case tok::kw___alignof:
+    IdentifierInfo *II = Tok.getIdentifierInfo();
+    SelectorLoc = ConsumeToken();
+    return II;
+  }
+}
+
+///  objc-for-collection-in: 'in'
+///
+bool Parser::isTokIdentifier_in() const {
+  // FIXME: May have to do additional look-ahead to only allow for
+  // valid tokens following an 'in'; such as an identifier, unary operators,
+  // '[' etc.
+  return (getLang().ObjC2 && Tok.is(tok::identifier) &&
+          Tok.getIdentifierInfo() == ObjCTypeQuals[objc_in]);
+}
+
+/// ParseObjCTypeQualifierList - This routine parses the objective-c's type
+/// qualifier list and builds their bitmask representation in the input
+/// argument.
+///
+///   objc-type-qualifiers:
+///     objc-type-qualifier
+///     objc-type-qualifiers objc-type-qualifier
+///
+void Parser::ParseObjCTypeQualifierList(ObjCDeclSpec &DS) {
+  while (1) {
+    if (Tok.isNot(tok::identifier))
+      return;
+
+    const IdentifierInfo *II = Tok.getIdentifierInfo();
+    for (unsigned i = 0; i != objc_NumQuals; ++i) {
+      if (II != ObjCTypeQuals[i])
+        continue;
+
+      ObjCDeclSpec::ObjCDeclQualifier Qual;
+      switch (i) {
+      default: assert(0 && "Unknown decl qualifier");
+      case objc_in:     Qual = ObjCDeclSpec::DQ_In; break;
+      case objc_out:    Qual = ObjCDeclSpec::DQ_Out; break;
+      case objc_inout:  Qual = ObjCDeclSpec::DQ_Inout; break;
+      case objc_oneway: Qual = ObjCDeclSpec::DQ_Oneway; break;
+      case objc_bycopy: Qual = ObjCDeclSpec::DQ_Bycopy; break;
+      case objc_byref:  Qual = ObjCDeclSpec::DQ_Byref; break;
+      }
+      DS.setObjCDeclQualifier(Qual);
+      ConsumeToken();
+      II = 0;
+      break;
+    }
+
+    // If this wasn't a recognized qualifier, bail out.
+    if (II) return;
+  }
+}
+
+///   objc-type-name:
+///     '(' objc-type-qualifiers[opt] type-name ')'
+///     '(' objc-type-qualifiers[opt] ')'
+///
+Parser::TypeTy *Parser::ParseObjCTypeName(ObjCDeclSpec &DS) {
+  assert(Tok.is(tok::l_paren) && "expected (");
+
+  SourceLocation LParenLoc = ConsumeParen();
+  SourceLocation TypeStartLoc = Tok.getLocation();
+
+  // Parse type qualifiers, in, inout, etc.
+  ParseObjCTypeQualifierList(DS);
+
+  TypeTy *Ty = 0;
+  if (isTypeSpecifierQualifier()) {
+    TypeResult TypeSpec = ParseTypeName();
+    if (!TypeSpec.isInvalid())
+      Ty = TypeSpec.get();
+  }
+
+  if (Tok.is(tok::r_paren))
+    ConsumeParen();
+  else if (Tok.getLocation() == TypeStartLoc) {
+    // If we didn't eat any tokens, then this isn't a type.
+    Diag(Tok, diag::err_expected_type);
+    SkipUntil(tok::r_paren);
+  } else {
+    // Otherwise, we found *something*, but didn't get a ')' in the right
+    // place.  Emit an error then return what we have as the type.
+    MatchRHSPunctuation(tok::r_paren, LParenLoc);
+  }
+  return Ty;
+}
+
+///   objc-method-decl:
+///     objc-selector
+///     objc-keyword-selector objc-parmlist[opt]
+///     objc-type-name objc-selector
+///     objc-type-name objc-keyword-selector objc-parmlist[opt]
+///
+///   objc-keyword-selector:
+///     objc-keyword-decl
+///     objc-keyword-selector objc-keyword-decl
+///
+///   objc-keyword-decl:
+///     objc-selector ':' objc-type-name objc-keyword-attributes[opt] identifier
+///     objc-selector ':' objc-keyword-attributes[opt] identifier
+///     ':' objc-type-name objc-keyword-attributes[opt] identifier
+///     ':' objc-keyword-attributes[opt] identifier
+///
+///   objc-parmlist:
+///     objc-parms objc-ellipsis[opt]
+///
+///   objc-parms:
+///     objc-parms , parameter-declaration
+///
+///   objc-ellipsis:
+///     , ...
+///
+///   objc-keyword-attributes:         [OBJC2]
+///     __attribute__((unused))
+///
+Parser::DeclPtrTy Parser::ParseObjCMethodDecl(SourceLocation mLoc,
+                                              tok::TokenKind mType,
+                                              DeclPtrTy IDecl,
+                                          tok::ObjCKeywordKind MethodImplKind) {
+  ParsingDeclRAIIObject PD(*this);
+
+  // Parse the return type if present.
+  TypeTy *ReturnType = 0;
+  ObjCDeclSpec DSRet;
+  if (Tok.is(tok::l_paren))
+    ReturnType = ParseObjCTypeName(DSRet);
+
+  SourceLocation selLoc;
+  IdentifierInfo *SelIdent = ParseObjCSelectorPiece(selLoc);
+
+  // An unnamed colon is valid.
+  if (!SelIdent && Tok.isNot(tok::colon)) { // missing selector name.
+    Diag(Tok, diag::err_expected_selector_for_method)
+      << SourceRange(mLoc, Tok.getLocation());
+    // Skip until we get a ; or {}.
+    SkipUntil(tok::r_brace);
+    return DeclPtrTy();
+  }
+
+  llvm::SmallVector<Declarator, 8> CargNames;
+  if (Tok.isNot(tok::colon)) {
+    // If attributes exist after the method, parse them.
+    AttributeList *MethodAttrs = 0;
+    if (getLang().ObjC2 && Tok.is(tok::kw___attribute))
+      MethodAttrs = ParseGNUAttributes();
+
+    Selector Sel = PP.getSelectorTable().getNullarySelector(SelIdent);
+    DeclPtrTy Result
+         = Actions.ActOnMethodDeclaration(mLoc, Tok.getLocation(),
+                                          mType, IDecl, DSRet, ReturnType, Sel,
+                                          0, CargNames, MethodAttrs,
+                                          MethodImplKind);
+    PD.complete(Result);
+    return Result;
+  }
+
+  llvm::SmallVector<IdentifierInfo *, 12> KeyIdents;
+  llvm::SmallVector<Action::ObjCArgInfo, 12> ArgInfos;
+
+  while (1) {
+    Action::ObjCArgInfo ArgInfo;
+
+    // Each iteration parses a single keyword argument.
+    if (Tok.isNot(tok::colon)) {
+      Diag(Tok, diag::err_expected_colon);
+      break;
+    }
+    ConsumeToken(); // Eat the ':'.
+
+    ArgInfo.Type = 0;
+    if (Tok.is(tok::l_paren)) // Parse the argument type if present.
+      ArgInfo.Type = ParseObjCTypeName(ArgInfo.DeclSpec);
+
+    // If attributes exist before the argument name, parse them.
+    ArgInfo.ArgAttrs = 0;
+    if (getLang().ObjC2 && Tok.is(tok::kw___attribute))
+      ArgInfo.ArgAttrs = ParseGNUAttributes();
+
+    if (Tok.isNot(tok::identifier)) {
+      Diag(Tok, diag::err_expected_ident); // missing argument name.
+      break;
+    }
+
+    ArgInfo.Name = Tok.getIdentifierInfo();
+    ArgInfo.NameLoc = Tok.getLocation();
+    ConsumeToken(); // Eat the identifier.
+
+    ArgInfos.push_back(ArgInfo);
+    KeyIdents.push_back(SelIdent);
+
+    // Check for another keyword selector.
+    SourceLocation Loc;
+    SelIdent = ParseObjCSelectorPiece(Loc);
+    if (!SelIdent && Tok.isNot(tok::colon))
+      break;
+    // We have a selector or a colon, continue parsing.
+  }
+
+  bool isVariadic = false;
+
+  // Parse the (optional) parameter list.
+  while (Tok.is(tok::comma)) {
+    ConsumeToken();
+    if (Tok.is(tok::ellipsis)) {
+      isVariadic = true;
+      ConsumeToken();
+      break;
+    }
+    DeclSpec DS;
+    ParseDeclarationSpecifiers(DS);
+    // Parse the declarator.
+    Declarator ParmDecl(DS, Declarator::PrototypeContext);
+    ParseDeclarator(ParmDecl);
+    CargNames.push_back(ParmDecl);
+  }
+
+  // FIXME: Add support for optional parmameter list...
+  // If attributes exist after the method, parse them.
+  AttributeList *MethodAttrs = 0;
+  if (getLang().ObjC2 && Tok.is(tok::kw___attribute))
+    MethodAttrs = ParseGNUAttributes();
+
+  if (KeyIdents.size() == 0)
+    return DeclPtrTy();
+  Selector Sel = PP.getSelectorTable().getSelector(KeyIdents.size(),
+                                                   &KeyIdents[0]);
+  DeclPtrTy Result
+       = Actions.ActOnMethodDeclaration(mLoc, Tok.getLocation(),
+                                        mType, IDecl, DSRet, ReturnType, Sel,
+                                        &ArgInfos[0], CargNames, MethodAttrs,
+                                        MethodImplKind, isVariadic);
+  PD.complete(Result);
+  return Result;
+}
+
+///   objc-protocol-refs:
+///     '<' identifier-list '>'
+///
+bool Parser::
+ParseObjCProtocolReferences(llvm::SmallVectorImpl<Action::DeclPtrTy> &Protocols,
+                            llvm::SmallVectorImpl<SourceLocation> &ProtocolLocs,
+                            bool WarnOnDeclarations,
+                            SourceLocation &LAngleLoc, SourceLocation &EndLoc) {
+  assert(Tok.is(tok::less) && "expected <");
+
+  LAngleLoc = ConsumeToken(); // the "<"
+
+  llvm::SmallVector<IdentifierLocPair, 8> ProtocolIdents;
+
+  while (1) {
+    if (Tok.is(tok::code_completion)) {
+      Actions.CodeCompleteObjCProtocolReferences(ProtocolIdents.data(), 
+                                                 ProtocolIdents.size());
+      ConsumeToken();
+    }
+
+    if (Tok.isNot(tok::identifier)) {
+      Diag(Tok, diag::err_expected_ident);
+      SkipUntil(tok::greater);
+      return true;
+    }
+    ProtocolIdents.push_back(std::make_pair(Tok.getIdentifierInfo(),
+                                       Tok.getLocation()));
+    ProtocolLocs.push_back(Tok.getLocation());
+    ConsumeToken();
+
+    if (Tok.isNot(tok::comma))
+      break;
+    ConsumeToken();
+  }
+
+  // Consume the '>'.
+  if (Tok.isNot(tok::greater)) {
+    Diag(Tok, diag::err_expected_greater);
+    return true;
+  }
+
+  EndLoc = ConsumeAnyToken();
+
+  // Convert the list of protocols identifiers into a list of protocol decls.
+  Actions.FindProtocolDeclaration(WarnOnDeclarations,
+                                  &ProtocolIdents[0], ProtocolIdents.size(),
+                                  Protocols);
+  return false;
+}
+
+///   objc-class-instance-variables:
+///     '{' objc-instance-variable-decl-list[opt] '}'
+///
+///   objc-instance-variable-decl-list:
+///     objc-visibility-spec
+///     objc-instance-variable-decl ';'
+///     ';'
+///     objc-instance-variable-decl-list objc-visibility-spec
+///     objc-instance-variable-decl-list objc-instance-variable-decl ';'
+///     objc-instance-variable-decl-list ';'
+///
+///   objc-visibility-spec:
+///     @private
+///     @protected
+///     @public
+///     @package [OBJC2]
+///
+///   objc-instance-variable-decl:
+///     struct-declaration
+///
+void Parser::ParseObjCClassInstanceVariables(DeclPtrTy interfaceDecl,
+                                             SourceLocation atLoc) {
+  assert(Tok.is(tok::l_brace) && "expected {");
+  llvm::SmallVector<DeclPtrTy, 32> AllIvarDecls;
+
+  ParseScope ClassScope(this, Scope::DeclScope|Scope::ClassScope);
+
+  SourceLocation LBraceLoc = ConsumeBrace(); // the "{"
+
+  tok::ObjCKeywordKind visibility = tok::objc_protected;
+  // 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.
+
+    // Check for extraneous top-level semicolon.
+    if (Tok.is(tok::semi)) {
+      Diag(Tok, diag::ext_extra_struct_semi)
+        << CodeModificationHint::CreateRemoval(Tok.getLocation());
+      ConsumeToken();
+      continue;
+    }
+
+    // Set the default visibility to private.
+    if (Tok.is(tok::at)) { // parse objc-visibility-spec
+      ConsumeToken(); // eat the @ sign
+      
+      if (Tok.is(tok::code_completion)) {
+        Actions.CodeCompleteObjCAtVisibility(CurScope);
+        ConsumeToken();
+      }
+      
+      switch (Tok.getObjCKeywordID()) {
+      case tok::objc_private:
+      case tok::objc_public:
+      case tok::objc_protected:
+      case tok::objc_package:
+        visibility = Tok.getObjCKeywordID();
+        ConsumeToken();
+        continue;
+      default:
+        Diag(Tok, diag::err_objc_illegal_visibility_spec);
+        continue;
+      }
+    }
+
+    if (Tok.is(tok::code_completion)) {
+      Actions.CodeCompleteOrdinaryName(CurScope, 
+                                       Action::CCC_ObjCInstanceVariableList);
+      ConsumeToken();
+    }
+    
+    struct ObjCIvarCallback : FieldCallback {
+      Parser &P;
+      DeclPtrTy IDecl;
+      tok::ObjCKeywordKind visibility;
+      llvm::SmallVectorImpl<DeclPtrTy> &AllIvarDecls;
+
+      ObjCIvarCallback(Parser &P, DeclPtrTy IDecl, tok::ObjCKeywordKind V,
+                       llvm::SmallVectorImpl<DeclPtrTy> &AllIvarDecls) :
+        P(P), IDecl(IDecl), visibility(V), AllIvarDecls(AllIvarDecls) {
+      }
+
+      DeclPtrTy invoke(FieldDeclarator &FD) {
+        // Install the declarator into the interface decl.
+        DeclPtrTy Field
+          = P.Actions.ActOnIvar(P.CurScope,
+                                FD.D.getDeclSpec().getSourceRange().getBegin(),
+                                IDecl, FD.D, FD.BitfieldSize, visibility);
+        AllIvarDecls.push_back(Field);
+        return Field;
+      }
+    } Callback(*this, interfaceDecl, visibility, AllIvarDecls);
+
+    // Parse all the comma separated declarators.
+    DeclSpec DS;
+    ParseStructDeclaration(DS, Callback);
+
+    if (Tok.is(tok::semi)) {
+      ConsumeToken();
+    } else {
+      Diag(Tok, diag::err_expected_semi_decl_list);
+      // Skip to end of block or statement
+      SkipUntil(tok::r_brace, true, true);
+    }
+  }
+  SourceLocation RBraceLoc = MatchRHSPunctuation(tok::r_brace, LBraceLoc);
+  // 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(CurScope, atLoc, interfaceDecl,
+                      AllIvarDecls.data(), AllIvarDecls.size(),
+                      LBraceLoc, RBraceLoc, 0);
+  return;
+}
+
+///   objc-protocol-declaration:
+///     objc-protocol-definition
+///     objc-protocol-forward-reference
+///
+///   objc-protocol-definition:
+///     @protocol identifier
+///       objc-protocol-refs[opt]
+///       objc-interface-decl-list
+///     @end
+///
+///   objc-protocol-forward-reference:
+///     @protocol identifier-list ';'
+///
+///   "@protocol identifier ;" should be resolved as "@protocol
+///   identifier-list ;": objc-interface-decl-list may not start with a
+///   semicolon in the first alternative if objc-protocol-refs are omitted.
+Parser::DeclPtrTy Parser::ParseObjCAtProtocolDeclaration(SourceLocation AtLoc,
+                                                      AttributeList *attrList) {
+  assert(Tok.isObjCAtKeyword(tok::objc_protocol) &&
+         "ParseObjCAtProtocolDeclaration(): Expected @protocol");
+  ConsumeToken(); // the "protocol" identifier
+
+  if (Tok.is(tok::code_completion)) {
+    Actions.CodeCompleteObjCProtocolDecl(CurScope);
+    ConsumeToken();
+  }
+
+  if (Tok.isNot(tok::identifier)) {
+    Diag(Tok, diag::err_expected_ident); // missing protocol name.
+    return DeclPtrTy();
+  }
+  // Save the protocol name, then consume it.
+  IdentifierInfo *protocolName = Tok.getIdentifierInfo();
+  SourceLocation nameLoc = ConsumeToken();
+
+  if (Tok.is(tok::semi)) { // forward declaration of one protocol.
+    IdentifierLocPair ProtoInfo(protocolName, nameLoc);
+    ConsumeToken();
+    return Actions.ActOnForwardProtocolDeclaration(AtLoc, &ProtoInfo, 1,
+                                                   attrList);
+  }
+
+  if (Tok.is(tok::comma)) { // list of forward declarations.
+    llvm::SmallVector<IdentifierLocPair, 8> ProtocolRefs;
+    ProtocolRefs.push_back(std::make_pair(protocolName, nameLoc));
+
+    // Parse the list of forward declarations.
+    while (1) {
+      ConsumeToken(); // the ','
+      if (Tok.isNot(tok::identifier)) {
+        Diag(Tok, diag::err_expected_ident);
+        SkipUntil(tok::semi);
+        return DeclPtrTy();
+      }
+      ProtocolRefs.push_back(IdentifierLocPair(Tok.getIdentifierInfo(),
+                                               Tok.getLocation()));
+      ConsumeToken(); // the identifier
+
+      if (Tok.isNot(tok::comma))
+        break;
+    }
+    // Consume the ';'.
+    if (ExpectAndConsume(tok::semi, diag::err_expected_semi_after, "@protocol"))
+      return DeclPtrTy();
+
+    return Actions.ActOnForwardProtocolDeclaration(AtLoc,
+                                                   &ProtocolRefs[0],
+                                                   ProtocolRefs.size(),
+                                                   attrList);
+  }
+
+  // Last, and definitely not least, parse a protocol declaration.
+  SourceLocation LAngleLoc, EndProtoLoc;
+
+  llvm::SmallVector<DeclPtrTy, 8> ProtocolRefs;
+  llvm::SmallVector<SourceLocation, 8> ProtocolLocs;
+  if (Tok.is(tok::less) &&
+      ParseObjCProtocolReferences(ProtocolRefs, ProtocolLocs, false,
+                                  LAngleLoc, EndProtoLoc))
+    return DeclPtrTy();
+
+  DeclPtrTy ProtoType =
+    Actions.ActOnStartProtocolInterface(AtLoc, protocolName, nameLoc,
+                                        ProtocolRefs.data(),
+                                        ProtocolRefs.size(),
+                                        ProtocolLocs.data(),
+                                        EndProtoLoc, attrList);
+  ParseObjCInterfaceDeclList(ProtoType, tok::objc_protocol);
+  return ProtoType;
+}
+
+///   objc-implementation:
+///     objc-class-implementation-prologue
+///     objc-category-implementation-prologue
+///
+///   objc-class-implementation-prologue:
+///     @implementation identifier objc-superclass[opt]
+///       objc-class-instance-variables[opt]
+///
+///   objc-category-implementation-prologue:
+///     @implementation identifier ( identifier )
+Parser::DeclPtrTy Parser::ParseObjCAtImplementationDeclaration(
+  SourceLocation atLoc) {
+  assert(Tok.isObjCAtKeyword(tok::objc_implementation) &&
+         "ParseObjCAtImplementationDeclaration(): Expected @implementation");
+  ConsumeToken(); // the "implementation" identifier
+
+  // Code completion after '@implementation'.
+  if (Tok.is(tok::code_completion)) {
+    Actions.CodeCompleteObjCImplementationDecl(CurScope);
+    ConsumeToken();
+  }
+
+  if (Tok.isNot(tok::identifier)) {
+    Diag(Tok, diag::err_expected_ident); // missing class or category name.
+    return DeclPtrTy();
+  }
+  // We have a class or category name - consume it.
+  IdentifierInfo *nameId = Tok.getIdentifierInfo();
+  SourceLocation nameLoc = ConsumeToken(); // consume class or category name
+
+  if (Tok.is(tok::l_paren)) {
+    // we have a category implementation.
+    SourceLocation lparenLoc = ConsumeParen();
+    SourceLocation categoryLoc, rparenLoc;
+    IdentifierInfo *categoryId = 0;
+
+    if (Tok.is(tok::code_completion)) {
+      Actions.CodeCompleteObjCImplementationCategory(CurScope, nameId);
+      ConsumeToken();
+    }
+    
+    if (Tok.is(tok::identifier)) {
+      categoryId = Tok.getIdentifierInfo();
+      categoryLoc = ConsumeToken();
+    } else {
+      Diag(Tok, diag::err_expected_ident); // missing category name.
+      return DeclPtrTy();
+    }
+    if (Tok.isNot(tok::r_paren)) {
+      Diag(Tok, diag::err_expected_rparen);
+      SkipUntil(tok::r_paren, false); // don't stop at ';'
+      return DeclPtrTy();
+    }
+    rparenLoc = ConsumeParen();
+    DeclPtrTy ImplCatType = Actions.ActOnStartCategoryImplementation(
+                                    atLoc, nameId, nameLoc, categoryId,
+                                    categoryLoc);
+    ObjCImpDecl = ImplCatType;
+    PendingObjCImpDecl.push_back(ObjCImpDecl);
+    return DeclPtrTy();
+  }
+  // We have a class implementation
+  SourceLocation superClassLoc;
+  IdentifierInfo *superClassId = 0;
+  if (Tok.is(tok::colon)) {
+    // We have a super class
+    ConsumeToken();
+    if (Tok.isNot(tok::identifier)) {
+      Diag(Tok, diag::err_expected_ident); // missing super class name.
+      return DeclPtrTy();
+    }
+    superClassId = Tok.getIdentifierInfo();
+    superClassLoc = ConsumeToken(); // Consume super class name
+  }
+  DeclPtrTy ImplClsType = Actions.ActOnStartClassImplementation(
+                                  atLoc, nameId, nameLoc,
+                                  superClassId, superClassLoc);
+
+  if (Tok.is(tok::l_brace)) // we have ivars
+    ParseObjCClassInstanceVariables(ImplClsType/*FIXME*/, atLoc);
+  ObjCImpDecl = ImplClsType;
+  PendingObjCImpDecl.push_back(ObjCImpDecl);
+  
+  return DeclPtrTy();
+}
+
+Parser::DeclPtrTy Parser::ParseObjCAtEndDeclaration(SourceRange atEnd) {
+  assert(Tok.isObjCAtKeyword(tok::objc_end) &&
+         "ParseObjCAtEndDeclaration(): Expected @end");
+  DeclPtrTy Result = ObjCImpDecl;
+  ConsumeToken(); // the "end" identifier
+  if (ObjCImpDecl) {
+    Actions.ActOnAtEnd(atEnd, ObjCImpDecl);
+    ObjCImpDecl = DeclPtrTy();
+    PendingObjCImpDecl.pop_back();
+  }
+  else {
+    // missing @implementation
+    Diag(atEnd.getBegin(), diag::warn_expected_implementation);
+  }
+  return Result;
+}
+
+Parser::DeclGroupPtrTy Parser::RetrievePendingObjCImpDecl() {
+  if (PendingObjCImpDecl.empty())
+    return Actions.ConvertDeclToDeclGroup(DeclPtrTy());
+  DeclPtrTy ImpDecl = PendingObjCImpDecl.pop_back_val();
+  Actions.ActOnAtEnd(SourceRange(), ImpDecl);
+  return Actions.ConvertDeclToDeclGroup(ImpDecl);
+}
+
+///   compatibility-alias-decl:
+///     @compatibility_alias alias-name  class-name ';'
+///
+Parser::DeclPtrTy Parser::ParseObjCAtAliasDeclaration(SourceLocation atLoc) {
+  assert(Tok.isObjCAtKeyword(tok::objc_compatibility_alias) &&
+         "ParseObjCAtAliasDeclaration(): Expected @compatibility_alias");
+  ConsumeToken(); // consume compatibility_alias
+  if (Tok.isNot(tok::identifier)) {
+    Diag(Tok, diag::err_expected_ident);
+    return DeclPtrTy();
+  }
+  IdentifierInfo *aliasId = Tok.getIdentifierInfo();
+  SourceLocation aliasLoc = ConsumeToken(); // consume alias-name
+  if (Tok.isNot(tok::identifier)) {
+    Diag(Tok, diag::err_expected_ident);
+    return DeclPtrTy();
+  }
+  IdentifierInfo *classId = Tok.getIdentifierInfo();
+  SourceLocation classLoc = ConsumeToken(); // consume class-name;
+  if (Tok.isNot(tok::semi)) {
+    Diag(Tok, diag::err_expected_semi_after) << "@compatibility_alias";
+    return DeclPtrTy();
+  }
+  return Actions.ActOnCompatiblityAlias(atLoc, aliasId, aliasLoc,
+                                        classId, classLoc);
+}
+
+///   property-synthesis:
+///     @synthesize property-ivar-list ';'
+///
+///   property-ivar-list:
+///     property-ivar
+///     property-ivar-list ',' property-ivar
+///
+///   property-ivar:
+///     identifier
+///     identifier '=' identifier
+///
+Parser::DeclPtrTy Parser::ParseObjCPropertySynthesize(SourceLocation atLoc) {
+  assert(Tok.isObjCAtKeyword(tok::objc_synthesize) &&
+         "ParseObjCPropertyDynamic(): Expected '@synthesize'");
+  SourceLocation loc = ConsumeToken(); // consume synthesize
+
+  while (true) {
+    if (Tok.is(tok::code_completion)) {
+      Actions.CodeCompleteObjCPropertyDefinition(CurScope, ObjCImpDecl);
+      ConsumeToken();
+    }
+    
+    if (Tok.isNot(tok::identifier)) {
+      Diag(Tok, diag::err_synthesized_property_name);
+      SkipUntil(tok::semi);
+      return DeclPtrTy();
+    }
+    
+    IdentifierInfo *propertyIvar = 0;
+    IdentifierInfo *propertyId = Tok.getIdentifierInfo();
+    SourceLocation propertyLoc = ConsumeToken(); // consume property name
+    if (Tok.is(tok::equal)) {
+      // property '=' ivar-name
+      ConsumeToken(); // consume '='
+      
+      if (Tok.is(tok::code_completion)) {
+        Actions.CodeCompleteObjCPropertySynthesizeIvar(CurScope, propertyId,
+                                                       ObjCImpDecl);
+        ConsumeToken();
+      }
+      
+      if (Tok.isNot(tok::identifier)) {
+        Diag(Tok, diag::err_expected_ident);
+        break;
+      }
+      propertyIvar = Tok.getIdentifierInfo();
+      ConsumeToken(); // consume ivar-name
+    }
+    Actions.ActOnPropertyImplDecl(atLoc, propertyLoc, true, ObjCImpDecl,
+                                  propertyId, propertyIvar);
+    if (Tok.isNot(tok::comma))
+      break;
+    ConsumeToken(); // consume ','
+  }
+  if (Tok.isNot(tok::semi)) {
+    Diag(Tok, diag::err_expected_semi_after) << "@synthesize";
+    SkipUntil(tok::semi);
+  }
+  else
+    ConsumeToken(); // consume ';'
+  return DeclPtrTy();
+}
+
+///   property-dynamic:
+///     @dynamic  property-list
+///
+///   property-list:
+///     identifier
+///     property-list ',' identifier
+///
+Parser::DeclPtrTy Parser::ParseObjCPropertyDynamic(SourceLocation atLoc) {
+  assert(Tok.isObjCAtKeyword(tok::objc_dynamic) &&
+         "ParseObjCPropertyDynamic(): Expected '@dynamic'");
+  SourceLocation loc = ConsumeToken(); // consume dynamic
+  while (true) {
+    if (Tok.is(tok::code_completion)) {
+      Actions.CodeCompleteObjCPropertyDefinition(CurScope, ObjCImpDecl);
+      ConsumeToken();
+    }
+    
+    if (Tok.isNot(tok::identifier)) {
+      Diag(Tok, diag::err_expected_ident);
+      SkipUntil(tok::semi);
+      return DeclPtrTy();
+    }
+    
+    IdentifierInfo *propertyId = Tok.getIdentifierInfo();
+    SourceLocation propertyLoc = ConsumeToken(); // consume property name
+    Actions.ActOnPropertyImplDecl(atLoc, propertyLoc, false, ObjCImpDecl,
+                                  propertyId, 0);
+
+    if (Tok.isNot(tok::comma))
+      break;
+    ConsumeToken(); // consume ','
+  }
+  if (Tok.isNot(tok::semi))
+    Diag(Tok, diag::err_expected_semi_after) << "@dynamic";
+  return DeclPtrTy();
+}
+
+///  objc-throw-statement:
+///    throw expression[opt];
+///
+Parser::OwningStmtResult Parser::ParseObjCThrowStmt(SourceLocation atLoc) {
+  OwningExprResult Res(Actions);
+  ConsumeToken(); // consume throw
+  if (Tok.isNot(tok::semi)) {
+    Res = ParseExpression();
+    if (Res.isInvalid()) {
+      SkipUntil(tok::semi);
+      return StmtError();
+    }
+  }
+  ConsumeToken(); // consume ';'
+  return Actions.ActOnObjCAtThrowStmt(atLoc, move(Res), CurScope);
+}
+
+/// objc-synchronized-statement:
+///   @synchronized '(' expression ')' compound-statement
+///
+Parser::OwningStmtResult
+Parser::ParseObjCSynchronizedStmt(SourceLocation atLoc) {
+  ConsumeToken(); // consume synchronized
+  if (Tok.isNot(tok::l_paren)) {
+    Diag(Tok, diag::err_expected_lparen_after) << "@synchronized";
+    return StmtError();
+  }
+  ConsumeParen();  // '('
+  OwningExprResult Res(ParseExpression());
+  if (Res.isInvalid()) {
+    SkipUntil(tok::semi);
+    return StmtError();
+  }
+  if (Tok.isNot(tok::r_paren)) {
+    Diag(Tok, diag::err_expected_lbrace);
+    return StmtError();
+  }
+  ConsumeParen();  // ')'
+  if (Tok.isNot(tok::l_brace)) {
+    Diag(Tok, diag::err_expected_lbrace);
+    return StmtError();
+  }
+  // Enter a scope to hold everything within the compound stmt.  Compound
+  // statements can always hold declarations.
+  ParseScope BodyScope(this, Scope::DeclScope);
+
+  OwningStmtResult SynchBody(ParseCompoundStatementBody());
+
+  BodyScope.Exit();
+  if (SynchBody.isInvalid())
+    SynchBody = Actions.ActOnNullStmt(Tok.getLocation());
+  return Actions.ActOnObjCAtSynchronizedStmt(atLoc, move(Res), move(SynchBody));
+}
+
+///  objc-try-catch-statement:
+///    @try compound-statement objc-catch-list[opt]
+///    @try compound-statement objc-catch-list[opt] @finally compound-statement
+///
+///  objc-catch-list:
+///    @catch ( parameter-declaration ) compound-statement
+///    objc-catch-list @catch ( catch-parameter-declaration ) compound-statement
+///  catch-parameter-declaration:
+///     parameter-declaration
+///     '...' [OBJC2]
+///
+Parser::OwningStmtResult Parser::ParseObjCTryStmt(SourceLocation atLoc) {
+  bool catch_or_finally_seen = false;
+
+  ConsumeToken(); // consume try
+  if (Tok.isNot(tok::l_brace)) {
+    Diag(Tok, diag::err_expected_lbrace);
+    return StmtError();
+  }
+  OwningStmtResult CatchStmts(Actions);
+  OwningStmtResult FinallyStmt(Actions);
+  ParseScope TryScope(this, Scope::DeclScope);
+  OwningStmtResult TryBody(ParseCompoundStatementBody());
+  TryScope.Exit();
+  if (TryBody.isInvalid())
+    TryBody = Actions.ActOnNullStmt(Tok.getLocation());
+
+  while (Tok.is(tok::at)) {
+    // At this point, we need to lookahead to determine if this @ is the start
+    // of an @catch or @finally.  We don't want to consume the @ token if this
+    // is an @try or @encode or something else.
+    Token AfterAt = GetLookAheadToken(1);
+    if (!AfterAt.isObjCAtKeyword(tok::objc_catch) &&
+        !AfterAt.isObjCAtKeyword(tok::objc_finally))
+      break;
+
+    SourceLocation AtCatchFinallyLoc = ConsumeToken();
+    if (Tok.isObjCAtKeyword(tok::objc_catch)) {
+      DeclPtrTy FirstPart;
+      ConsumeToken(); // consume catch
+      if (Tok.is(tok::l_paren)) {
+        ConsumeParen();
+        ParseScope CatchScope(this, Scope::DeclScope|Scope::AtCatchScope);
+        if (Tok.isNot(tok::ellipsis)) {
+          DeclSpec DS;
+          ParseDeclarationSpecifiers(DS);
+          // For some odd reason, the name of the exception variable is
+          // optional. As a result, we need to use "PrototypeContext", because
+          // we must accept either 'declarator' or 'abstract-declarator' here.
+          Declarator ParmDecl(DS, Declarator::PrototypeContext);
+          ParseDeclarator(ParmDecl);
+
+          // Inform the actions module about the parameter declarator, so it
+          // gets added to the current scope.
+          // FIXME. Probably can build a VarDecl and avoid setting DeclContext.
+          FirstPart = Actions.ActOnParamDeclarator(CurScope, ParmDecl);
+          Actions.ActOnObjCCatchParam(FirstPart);
+        } else
+          ConsumeToken(); // consume '...'
+
+        SourceLocation RParenLoc;
+
+        if (Tok.is(tok::r_paren))
+          RParenLoc = ConsumeParen();
+        else // Skip over garbage, until we get to ')'.  Eat the ')'.
+          SkipUntil(tok::r_paren, true, false);
+
+        OwningStmtResult CatchBody(Actions, true);
+        if (Tok.is(tok::l_brace))
+          CatchBody = ParseCompoundStatementBody();
+        else
+          Diag(Tok, diag::err_expected_lbrace);
+        if (CatchBody.isInvalid())
+          CatchBody = Actions.ActOnNullStmt(Tok.getLocation());
+        CatchStmts = Actions.ActOnObjCAtCatchStmt(AtCatchFinallyLoc,
+                        RParenLoc, FirstPart, move(CatchBody),
+                        move(CatchStmts));
+      } else {
+        Diag(AtCatchFinallyLoc, diag::err_expected_lparen_after)
+          << "@catch clause";
+        return StmtError();
+      }
+      catch_or_finally_seen = true;
+    } else {
+      assert(Tok.isObjCAtKeyword(tok::objc_finally) && "Lookahead confused?");
+      ConsumeToken(); // consume finally
+      ParseScope FinallyScope(this, Scope::DeclScope);
+
+      OwningStmtResult FinallyBody(Actions, true);
+      if (Tok.is(tok::l_brace))
+        FinallyBody = ParseCompoundStatementBody();
+      else
+        Diag(Tok, diag::err_expected_lbrace);
+      if (FinallyBody.isInvalid())
+        FinallyBody = Actions.ActOnNullStmt(Tok.getLocation());
+      FinallyStmt = Actions.ActOnObjCAtFinallyStmt(AtCatchFinallyLoc,
+                                                   move(FinallyBody));
+      catch_or_finally_seen = true;
+      break;
+    }
+  }
+  if (!catch_or_finally_seen) {
+    Diag(atLoc, diag::err_missing_catch_finally);
+    return StmtError();
+  }
+  return Actions.ActOnObjCAtTryStmt(atLoc, move(TryBody), move(CatchStmts),
+                                    move(FinallyStmt));
+}
+
+///   objc-method-def: objc-method-proto ';'[opt] '{' body '}'
+///
+Parser::DeclPtrTy Parser::ParseObjCMethodDefinition() {
+  DeclPtrTy MDecl = ParseObjCMethodPrototype(ObjCImpDecl);
+
+  PrettyStackTraceActionsDecl CrashInfo(MDecl, Tok.getLocation(), Actions,
+                                        PP.getSourceManager(),
+                                        "parsing Objective-C method");
+
+  // parse optional ';'
+  if (Tok.is(tok::semi)) {
+    if (ObjCImpDecl) {
+      Diag(Tok, diag::warn_semicolon_before_method_body)
+        << CodeModificationHint::CreateRemoval(Tok.getLocation());
+    }
+    ConsumeToken();
+  }
+
+  // We should have an opening brace now.
+  if (Tok.isNot(tok::l_brace)) {
+    Diag(Tok, diag::err_expected_method_body);
+
+    // Skip over garbage, until we get to '{'.  Don't eat the '{'.
+    SkipUntil(tok::l_brace, true, true);
+
+    // If we didn't find the '{', bail out.
+    if (Tok.isNot(tok::l_brace))
+      return DeclPtrTy();
+  }
+  SourceLocation BraceLoc = Tok.getLocation();
+
+  // Enter a scope for the method body.
+  ParseScope BodyScope(this, Scope::FnScope|Scope::DeclScope);
+
+  // Tell the actions module that we have entered a method definition with the
+  // specified Declarator for the method.
+  Actions.ActOnStartOfObjCMethodDef(CurScope, MDecl);
+
+  OwningStmtResult FnBody(ParseCompoundStatementBody());
+
+  // If the function body could not be parsed, make a bogus compoundstmt.
+  if (FnBody.isInvalid())
+    FnBody = Actions.ActOnCompoundStmt(BraceLoc, BraceLoc,
+                                       MultiStmtArg(Actions), false);
+
+  // TODO: Pass argument information.
+  Actions.ActOnFinishFunctionBody(MDecl, move(FnBody));
+
+  // Leave the function body scope.
+  BodyScope.Exit();
+
+  return MDecl;
+}
+
+Parser::OwningStmtResult Parser::ParseObjCAtStatement(SourceLocation AtLoc) {
+  if (Tok.is(tok::code_completion)) {
+    Actions.CodeCompleteObjCAtStatement(CurScope);
+    ConsumeToken();
+    return StmtError();
+  }
+  
+  if (Tok.isObjCAtKeyword(tok::objc_try))
+    return ParseObjCTryStmt(AtLoc);
+  
+  if (Tok.isObjCAtKeyword(tok::objc_throw))
+    return ParseObjCThrowStmt(AtLoc);
+  
+  if (Tok.isObjCAtKeyword(tok::objc_synchronized))
+    return ParseObjCSynchronizedStmt(AtLoc);
+  
+  OwningExprResult Res(ParseExpressionWithLeadingAt(AtLoc));
+  if (Res.isInvalid()) {
+    // If the expression is invalid, skip ahead to the next semicolon. Not
+    // doing this opens us up to the possibility of infinite loops if
+    // ParseExpression does not consume any tokens.
+    SkipUntil(tok::semi);
+    return StmtError();
+  }
+  
+  // Otherwise, eat the semicolon.
+  ExpectAndConsume(tok::semi, diag::err_expected_semi_after_expr);
+  return Actions.ActOnExprStmt(Actions.MakeFullExpr(Res));
+}
+
+Parser::OwningExprResult Parser::ParseObjCAtExpression(SourceLocation AtLoc) {
+  switch (Tok.getKind()) {
+  case tok::code_completion:
+    Actions.CodeCompleteObjCAtExpression(CurScope);
+    ConsumeToken();
+    return ExprError();
+
+  case tok::string_literal:    // primary-expression: string-literal
+  case tok::wide_string_literal:
+    return ParsePostfixExpressionSuffix(ParseObjCStringLiteral(AtLoc));
+  default:
+    if (Tok.getIdentifierInfo() == 0)
+      return ExprError(Diag(AtLoc, diag::err_unexpected_at));
+
+    switch (Tok.getIdentifierInfo()->getObjCKeywordID()) {
+    case tok::objc_encode:
+      return ParsePostfixExpressionSuffix(ParseObjCEncodeExpression(AtLoc));
+    case tok::objc_protocol:
+      return ParsePostfixExpressionSuffix(ParseObjCProtocolExpression(AtLoc));
+    case tok::objc_selector:
+      return ParsePostfixExpressionSuffix(ParseObjCSelectorExpression(AtLoc));
+    default:
+      return ExprError(Diag(AtLoc, diag::err_unexpected_at));
+    }
+  }
+}
+
+///   objc-message-expr:
+///     '[' objc-receiver objc-message-args ']'
+///
+///   objc-receiver:
+///     expression
+///     class-name
+///     type-name
+Parser::OwningExprResult Parser::ParseObjCMessageExpression() {
+  assert(Tok.is(tok::l_square) && "'[' expected");
+  SourceLocation LBracLoc = ConsumeBracket(); // consume '['
+
+  // Parse receiver
+  if (isTokObjCMessageIdentifierReceiver()) {
+    IdentifierInfo *ReceiverName = Tok.getIdentifierInfo();
+    if (ReceiverName != Ident_super || GetLookAheadToken(1).isNot(tok::period)) {
+      SourceLocation NameLoc = ConsumeToken();
+      return ParseObjCMessageExpressionBody(LBracLoc, NameLoc, ReceiverName,
+                                            ExprArg(Actions));
+    }
+  }
+
+  OwningExprResult Res(ParseExpression());
+  if (Res.isInvalid()) {
+    SkipUntil(tok::r_square);
+    return move(Res);
+  }
+
+  return ParseObjCMessageExpressionBody(LBracLoc, SourceLocation(),
+                                        0, move(Res));
+}
+
+/// ParseObjCMessageExpressionBody - Having parsed "'[' objc-receiver", parse
+/// the rest of a message expression.
+///
+///   objc-message-args:
+///     objc-selector
+///     objc-keywordarg-list
+///
+///   objc-keywordarg-list:
+///     objc-keywordarg
+///     objc-keywordarg-list objc-keywordarg
+///
+///   objc-keywordarg:
+///     selector-name[opt] ':' objc-keywordexpr
+///
+///   objc-keywordexpr:
+///     nonempty-expr-list
+///
+///   nonempty-expr-list:
+///     assignment-expression
+///     nonempty-expr-list , assignment-expression
+///
+Parser::OwningExprResult
+Parser::ParseObjCMessageExpressionBody(SourceLocation LBracLoc,
+                                       SourceLocation NameLoc,
+                                       IdentifierInfo *ReceiverName,
+                                       ExprArg ReceiverExpr) {
+  if (Tok.is(tok::code_completion)) {
+    if (ReceiverName)
+      Actions.CodeCompleteObjCClassMessage(CurScope, ReceiverName, NameLoc, 
+                                           0, 0);
+    else
+      Actions.CodeCompleteObjCInstanceMessage(CurScope, ReceiverExpr.get(), 
+                                              0, 0);
+    ConsumeToken();
+  }
+  
+  // Parse objc-selector
+  SourceLocation Loc;
+  IdentifierInfo *selIdent = ParseObjCSelectorPiece(Loc);
+
+  SourceLocation SelectorLoc = Loc;
+
+  llvm::SmallVector<IdentifierInfo *, 12> KeyIdents;
+  ExprVector KeyExprs(Actions);
+
+  if (Tok.is(tok::colon)) {
+    while (1) {
+      // Each iteration parses a single keyword argument.
+      KeyIdents.push_back(selIdent);
+
+      if (Tok.isNot(tok::colon)) {
+        Diag(Tok, diag::err_expected_colon);
+        // We must manually skip to a ']', otherwise the expression skipper will
+        // stop at the ']' when it skips to the ';'.  We want it to skip beyond
+        // the enclosing expression.
+        SkipUntil(tok::r_square);
+        return ExprError();
+      }
+
+      ConsumeToken(); // Eat the ':'.
+      ///  Parse the expression after ':'
+      OwningExprResult Res(ParseAssignmentExpression());
+      if (Res.isInvalid()) {
+        // We must manually skip to a ']', otherwise the expression skipper will
+        // stop at the ']' when it skips to the ';'.  We want it to skip beyond
+        // the enclosing expression.
+        SkipUntil(tok::r_square);
+        return move(Res);
+      }
+
+      // We have a valid expression.
+      KeyExprs.push_back(Res.release());
+
+      // Code completion after each argument.
+      if (Tok.is(tok::code_completion)) {
+        if (ReceiverName)
+          Actions.CodeCompleteObjCClassMessage(CurScope, ReceiverName, NameLoc,
+                                               KeyIdents.data(), 
+                                               KeyIdents.size());
+        else
+          Actions.CodeCompleteObjCInstanceMessage(CurScope, ReceiverExpr.get(),
+                                                  KeyIdents.data(), 
+                                                  KeyIdents.size());
+        ConsumeToken();
+      }
+            
+      // Check for another keyword selector.
+      selIdent = ParseObjCSelectorPiece(Loc);
+      if (!selIdent && Tok.isNot(tok::colon))
+        break;
+      // We have a selector or a colon, continue parsing.
+    }
+    // Parse the, optional, argument list, comma separated.
+    while (Tok.is(tok::comma)) {
+      ConsumeToken(); // Eat the ','.
+      ///  Parse the expression after ','
+      OwningExprResult Res(ParseAssignmentExpression());
+      if (Res.isInvalid()) {
+        // We must manually skip to a ']', otherwise the expression skipper will
+        // stop at the ']' when it skips to the ';'.  We want it to skip beyond
+        // the enclosing expression.
+        SkipUntil(tok::r_square);
+        return move(Res);
+      }
+
+      // We have a valid expression.
+      KeyExprs.push_back(Res.release());
+    }
+  } else if (!selIdent) {
+    Diag(Tok, diag::err_expected_ident); // missing selector name.
+
+    // We must manually skip to a ']', otherwise the expression skipper will
+    // stop at the ']' when it skips to the ';'.  We want it to skip beyond
+    // the enclosing expression.
+    SkipUntil(tok::r_square);
+    return ExprError();
+  }
+
+  if (Tok.isNot(tok::r_square)) {
+    Diag(Tok, diag::err_expected_rsquare);
+    // We must manually skip to a ']', otherwise the expression skipper will
+    // stop at the ']' when it skips to the ';'.  We want it to skip beyond
+    // the enclosing expression.
+    SkipUntil(tok::r_square);
+    return ExprError();
+  }
+
+  SourceLocation RBracLoc = ConsumeBracket(); // consume ']'
+
+  unsigned nKeys = KeyIdents.size();
+  if (nKeys == 0)
+    KeyIdents.push_back(selIdent);
+  Selector Sel = PP.getSelectorTable().getSelector(nKeys, &KeyIdents[0]);
+
+  // We've just parsed a keyword message.
+  if (ReceiverName)
+    return Owned(Actions.ActOnClassMessage(CurScope, ReceiverName, Sel,
+                                           LBracLoc, NameLoc, SelectorLoc,
+                                           RBracLoc,
+                                           KeyExprs.take(), KeyExprs.size()));
+  return Owned(Actions.ActOnInstanceMessage(ReceiverExpr.release(), Sel,
+                                            LBracLoc, SelectorLoc, RBracLoc,
+                                            KeyExprs.take(), KeyExprs.size()));
+}
+
+Parser::OwningExprResult Parser::ParseObjCStringLiteral(SourceLocation AtLoc) {
+  OwningExprResult Res(ParseStringLiteralExpression());
+  if (Res.isInvalid()) return move(Res);
+
+  // @"foo" @"bar" is a valid concatenated string.  Eat any subsequent string
+  // expressions.  At this point, we know that the only valid thing that starts
+  // with '@' is an @"".
+  llvm::SmallVector<SourceLocation, 4> AtLocs;
+  ExprVector AtStrings(Actions);
+  AtLocs.push_back(AtLoc);
+  AtStrings.push_back(Res.release());
+
+  while (Tok.is(tok::at)) {
+    AtLocs.push_back(ConsumeToken()); // eat the @.
+
+    // Invalid unless there is a string literal.
+    if (!isTokenStringLiteral())
+      return ExprError(Diag(Tok, diag::err_objc_concat_string));
+
+    OwningExprResult Lit(ParseStringLiteralExpression());
+    if (Lit.isInvalid())
+      return move(Lit);
+
+    AtStrings.push_back(Lit.release());
+  }
+
+  return Owned(Actions.ParseObjCStringLiteral(&AtLocs[0], AtStrings.take(),
+                                              AtStrings.size()));
+}
+
+///    objc-encode-expression:
+///      @encode ( type-name )
+Parser::OwningExprResult
+Parser::ParseObjCEncodeExpression(SourceLocation AtLoc) {
+  assert(Tok.isObjCAtKeyword(tok::objc_encode) && "Not an @encode expression!");
+
+  SourceLocation EncLoc = ConsumeToken();
+
+  if (Tok.isNot(tok::l_paren))
+    return ExprError(Diag(Tok, diag::err_expected_lparen_after) << "@encode");
+
+  SourceLocation LParenLoc = ConsumeParen();
+
+  TypeResult Ty = ParseTypeName();
+
+  SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc);
+
+  if (Ty.isInvalid())
+    return ExprError();
+
+  return Owned(Actions.ParseObjCEncodeExpression(AtLoc, EncLoc, LParenLoc,
+                                                 Ty.get(), RParenLoc));
+}
+
+///     objc-protocol-expression
+///       @protocol ( protocol-name )
+Parser::OwningExprResult
+Parser::ParseObjCProtocolExpression(SourceLocation AtLoc) {
+  SourceLocation ProtoLoc = ConsumeToken();
+
+  if (Tok.isNot(tok::l_paren))
+    return ExprError(Diag(Tok, diag::err_expected_lparen_after) << "@protocol");
+
+  SourceLocation LParenLoc = ConsumeParen();
+
+  if (Tok.isNot(tok::identifier))
+    return ExprError(Diag(Tok, diag::err_expected_ident));
+
+  IdentifierInfo *protocolId = Tok.getIdentifierInfo();
+  ConsumeToken();
+
+  SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc);
+
+  return Owned(Actions.ParseObjCProtocolExpression(protocolId, AtLoc, ProtoLoc,
+                                                   LParenLoc, RParenLoc));
+}
+
+///     objc-selector-expression
+///       @selector '(' objc-keyword-selector ')'
+Parser::OwningExprResult
+Parser::ParseObjCSelectorExpression(SourceLocation AtLoc) {
+  SourceLocation SelectorLoc = ConsumeToken();
+
+  if (Tok.isNot(tok::l_paren))
+    return ExprError(Diag(Tok, diag::err_expected_lparen_after) << "@selector");
+
+  llvm::SmallVector<IdentifierInfo *, 12> KeyIdents;
+  SourceLocation LParenLoc = ConsumeParen();
+  SourceLocation sLoc;
+  IdentifierInfo *SelIdent = ParseObjCSelectorPiece(sLoc);
+  if (!SelIdent && Tok.isNot(tok::colon)) // missing selector name.
+    return ExprError(Diag(Tok, diag::err_expected_ident));
+
+  KeyIdents.push_back(SelIdent);
+  unsigned nColons = 0;
+  if (Tok.isNot(tok::r_paren)) {
+    while (1) {
+      if (Tok.isNot(tok::colon))
+        return ExprError(Diag(Tok, diag::err_expected_colon));
+
+      nColons++;
+      ConsumeToken(); // Eat the ':'.
+      if (Tok.is(tok::r_paren))
+        break;
+      // Check for another keyword selector.
+      SourceLocation Loc;
+      SelIdent = ParseObjCSelectorPiece(Loc);
+      KeyIdents.push_back(SelIdent);
+      if (!SelIdent && Tok.isNot(tok::colon))
+        break;
+    }
+  }
+  SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc);
+  Selector Sel = PP.getSelectorTable().getSelector(nColons, &KeyIdents[0]);
+  return Owned(Actions.ParseObjCSelectorExpression(Sel, AtLoc, SelectorLoc,
+                                                   LParenLoc, RParenLoc));
+ }
diff --git a/lib/Parse/ParsePragma.cpp b/lib/Parse/ParsePragma.cpp
new file mode 100644
index 0000000..812d8e2
--- /dev/null
+++ b/lib/Parse/ParsePragma.cpp
@@ -0,0 +1,220 @@
+//===--- ParsePragma.cpp - Language specific pragma parsing ---------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the language specific #pragma handlers.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ParsePragma.h"
+#include "clang/Parse/ParseDiagnostic.h"
+#include "clang/Lex/Preprocessor.h"
+#include "clang/Parse/Action.h"
+#include "clang/Parse/Parser.h"
+using namespace clang;
+
+// #pragma pack(...) comes in the following delicious flavors:
+//   pack '(' [integer] ')'
+//   pack '(' 'show' ')'
+//   pack '(' ('push' | 'pop') [',' identifier] [, integer] ')'
+void PragmaPackHandler::HandlePragma(Preprocessor &PP, Token &PackTok) {
+  // FIXME: Should we be expanding macros here? My guess is no.
+  SourceLocation PackLoc = PackTok.getLocation();
+
+  Token Tok;
+  PP.Lex(Tok);
+  if (Tok.isNot(tok::l_paren)) {
+    PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) << "pack";
+    return;
+  }
+
+  Action::PragmaPackKind Kind = Action::PPK_Default;
+  IdentifierInfo *Name = 0;
+  Action::OwningExprResult Alignment(Actions);
+  SourceLocation LParenLoc = Tok.getLocation();
+  PP.Lex(Tok);
+  if (Tok.is(tok::numeric_constant)) {
+    Alignment = Actions.ActOnNumericConstant(Tok);
+    if (Alignment.isInvalid())
+      return;
+
+    PP.Lex(Tok);
+  } else if (Tok.is(tok::identifier)) {
+    const IdentifierInfo *II = Tok.getIdentifierInfo();
+    if (II->isStr("show")) {
+      Kind = Action::PPK_Show;
+      PP.Lex(Tok);
+    } else {
+      if (II->isStr("push")) {
+        Kind = Action::PPK_Push;
+      } else if (II->isStr("pop")) {
+        Kind = Action::PPK_Pop;
+      } else {
+        PP.Diag(Tok.getLocation(), diag::warn_pragma_pack_invalid_action);
+        return;
+      }
+      PP.Lex(Tok);
+
+      if (Tok.is(tok::comma)) {
+        PP.Lex(Tok);
+
+        if (Tok.is(tok::numeric_constant)) {
+          Alignment = Actions.ActOnNumericConstant(Tok);
+          if (Alignment.isInvalid())
+            return;
+
+          PP.Lex(Tok);
+        } else if (Tok.is(tok::identifier)) {
+          Name = Tok.getIdentifierInfo();
+          PP.Lex(Tok);
+
+          if (Tok.is(tok::comma)) {
+            PP.Lex(Tok);
+
+            if (Tok.isNot(tok::numeric_constant)) {
+              PP.Diag(Tok.getLocation(), diag::warn_pragma_pack_malformed);
+              return;
+            }
+
+            Alignment = Actions.ActOnNumericConstant(Tok);
+            if (Alignment.isInvalid())
+              return;
+
+            PP.Lex(Tok);
+          }
+        } else {
+          PP.Diag(Tok.getLocation(), diag::warn_pragma_pack_malformed);
+          return;
+        }
+      }
+    }
+  }
+
+  if (Tok.isNot(tok::r_paren)) {
+    PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen) << "pack";
+    return;
+  }
+
+  PP.Lex(Tok);
+  if (Tok.isNot(tok::eom)) {
+    PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) << "pack";
+    return;
+  }
+
+  SourceLocation RParenLoc = Tok.getLocation();
+  Actions.ActOnPragmaPack(Kind, Name, Alignment.release(), PackLoc,
+                          LParenLoc, RParenLoc);
+}
+
+// #pragma unused(identifier)
+void PragmaUnusedHandler::HandlePragma(Preprocessor &PP, Token &UnusedTok) {
+  // FIXME: Should we be expanding macros here? My guess is no.
+  SourceLocation UnusedLoc = UnusedTok.getLocation();
+
+  // Lex the left '('.
+  Token Tok;
+  PP.Lex(Tok);
+  if (Tok.isNot(tok::l_paren)) {
+    PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) << "unused";
+    return;
+  }
+  SourceLocation LParenLoc = Tok.getLocation();
+
+  // Lex the declaration reference(s).
+  llvm::SmallVector<Token, 5> Identifiers;
+  SourceLocation RParenLoc;
+  bool LexID = true;
+
+  while (true) {
+    PP.Lex(Tok);
+
+    if (LexID) {
+      if (Tok.is(tok::identifier)) {
+        Identifiers.push_back(Tok);
+        LexID = false;
+        continue;
+      }
+
+      // Illegal token!
+      PP.Diag(Tok.getLocation(), diag::warn_pragma_unused_expected_var);
+      return;
+    }
+
+    // We are execting a ')' or a ','.
+    if (Tok.is(tok::comma)) {
+      LexID = true;
+      continue;
+    }
+
+    if (Tok.is(tok::r_paren)) {
+      RParenLoc = Tok.getLocation();
+      break;
+    }
+
+    // Illegal token!
+    PP.Diag(Tok.getLocation(), diag::warn_pragma_unused_expected_punc);
+    return;
+  }
+
+  PP.Lex(Tok);
+  if (Tok.isNot(tok::eom)) {
+    PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) <<
+        "unused";
+    return;
+  }
+
+  // Verify that we have a location for the right parenthesis.
+  assert(RParenLoc.isValid() && "Valid '#pragma unused' must have ')'");
+  assert(!Identifiers.empty() && "Valid '#pragma unused' must have arguments");
+
+  // Perform the action to handle the pragma.
+  Actions.ActOnPragmaUnused(Identifiers.data(), Identifiers.size(),
+                            parser.CurScope, UnusedLoc, LParenLoc, RParenLoc);
+}
+
+// #pragma weak identifier
+// #pragma weak identifier '=' identifier
+void PragmaWeakHandler::HandlePragma(Preprocessor &PP, Token &WeakTok) {
+  // FIXME: Should we be expanding macros here? My guess is no.
+  SourceLocation WeakLoc = WeakTok.getLocation();
+
+  Token Tok;
+  PP.Lex(Tok);
+  if (Tok.isNot(tok::identifier)) {
+    PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) << "weak";
+    return;
+  }
+
+  IdentifierInfo *WeakName = Tok.getIdentifierInfo(), *AliasName = 0;
+  SourceLocation WeakNameLoc = Tok.getLocation(), AliasNameLoc;
+
+  PP.Lex(Tok);
+  if (Tok.is(tok::equal)) {
+    PP.Lex(Tok);
+    if (Tok.isNot(tok::identifier)) {
+      PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
+          << "weak";
+      return;
+    }
+    AliasName = Tok.getIdentifierInfo();
+    AliasNameLoc = Tok.getLocation();
+    PP.Lex(Tok);
+  }
+
+  if (Tok.isNot(tok::eom)) {
+    PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) << "weak";
+    return;
+  }
+
+  if (AliasName) {
+    Actions.ActOnPragmaWeakAlias(WeakName, AliasName, WeakLoc, WeakNameLoc,
+                                 AliasNameLoc);
+  } else {
+    Actions.ActOnPragmaWeakID(WeakName, WeakLoc, WeakNameLoc);
+  }
+}
diff --git a/lib/Parse/ParsePragma.h b/lib/Parse/ParsePragma.h
new file mode 100644
index 0000000..db385c6
--- /dev/null
+++ b/lib/Parse/ParsePragma.h
@@ -0,0 +1,53 @@
+//===---- ParserPragmas.h - Language specific pragmas -----------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines #pragma handlers for language specific pragmas.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_PARSE_PARSEPRAGMA_H
+#define LLVM_CLANG_PARSE_PARSEPRAGMA_H
+
+#include "clang/Lex/Pragma.h"
+
+namespace clang {
+  class Action;
+  class Parser;
+
+class PragmaPackHandler : public PragmaHandler {
+  Action &Actions;
+public:
+  PragmaPackHandler(const IdentifierInfo *N, Action &A) : PragmaHandler(N),
+                                                          Actions(A) {}
+
+  virtual void HandlePragma(Preprocessor &PP, Token &FirstToken);
+};
+
+class PragmaUnusedHandler : public PragmaHandler {
+  Action &Actions;
+  Parser &parser;
+public:
+  PragmaUnusedHandler(const IdentifierInfo *N, Action &A, Parser& p)
+    : PragmaHandler(N), Actions(A), parser(p) {}
+
+  virtual void HandlePragma(Preprocessor &PP, Token &FirstToken);
+};
+
+class PragmaWeakHandler : public PragmaHandler {
+  Action &Actions;
+public:
+  PragmaWeakHandler(const IdentifierInfo *N, Action &A)
+    : PragmaHandler(N), Actions(A) {}
+
+  virtual void HandlePragma(Preprocessor &PP, Token &FirstToken);
+};
+
+}  // end namespace clang
+
+#endif
diff --git a/lib/Parse/ParseStmt.cpp b/lib/Parse/ParseStmt.cpp
new file mode 100644
index 0000000..157e8b1
--- /dev/null
+++ b/lib/Parse/ParseStmt.cpp
@@ -0,0 +1,1547 @@
+//===--- ParseStmt.cpp - Statement and Block Parser -----------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the Statement and Block portions of the Parser
+// interface.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Parse/Parser.h"
+#include "RAIIObjectsForParser.h"
+#include "clang/Parse/DeclSpec.h"
+#include "clang/Parse/Scope.h"
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/PrettyStackTrace.h"
+#include "clang/Basic/SourceManager.h"
+using namespace clang;
+
+//===----------------------------------------------------------------------===//
+// C99 6.8: Statements and Blocks.
+//===----------------------------------------------------------------------===//
+
+/// ParseStatementOrDeclaration - Read 'statement' or 'declaration'.
+///       StatementOrDeclaration:
+///         statement
+///         declaration
+///
+///       statement:
+///         labeled-statement
+///         compound-statement
+///         expression-statement
+///         selection-statement
+///         iteration-statement
+///         jump-statement
+/// [C++]   declaration-statement
+/// [C++]   try-block
+/// [OBC]   objc-throw-statement
+/// [OBC]   objc-try-catch-statement
+/// [OBC]   objc-synchronized-statement
+/// [GNU]   asm-statement
+/// [OMP]   openmp-construct             [TODO]
+///
+///       labeled-statement:
+///         identifier ':' statement
+///         'case' constant-expression ':' statement
+///         'default' ':' statement
+///
+///       selection-statement:
+///         if-statement
+///         switch-statement
+///
+///       iteration-statement:
+///         while-statement
+///         do-statement
+///         for-statement
+///
+///       expression-statement:
+///         expression[opt] ';'
+///
+///       jump-statement:
+///         'goto' identifier ';'
+///         'continue' ';'
+///         'break' ';'
+///         'return' expression[opt] ';'
+/// [GNU]   'goto' '*' expression ';'
+///
+/// [OBC] objc-throw-statement:
+/// [OBC]   '@' 'throw' expression ';'
+/// [OBC]   '@' 'throw' ';'
+///
+Parser::OwningStmtResult
+Parser::ParseStatementOrDeclaration(bool OnlyStatement) {
+  const char *SemiError = 0;
+  OwningStmtResult Res(Actions);
+
+  CXX0XAttributeList Attr;
+  if (getLang().CPlusPlus0x && isCXX0XAttributeSpecifier())
+    Attr = ParseCXX0XAttributes();
+
+  // Cases in this switch statement should fall through if the parser expects
+  // the token to end in a semicolon (in which case SemiError should be set),
+  // or they directly 'return;' if not.
+  tok::TokenKind Kind  = Tok.getKind();
+  SourceLocation AtLoc;
+  switch (Kind) {
+  case tok::at: // May be a @try or @throw statement
+    {
+      AtLoc = ConsumeToken();  // consume @
+      return ParseObjCAtStatement(AtLoc);
+    }
+
+  case tok::code_completion:
+    Actions.CodeCompleteOrdinaryName(CurScope, Action::CCC_Statement);
+    ConsumeToken();
+    return ParseStatementOrDeclaration(OnlyStatement);
+      
+  case tok::identifier:
+    if (NextToken().is(tok::colon)) { // C99 6.8.1: labeled-statement
+      // identifier ':' statement
+      return ParseLabeledStatement(Attr.AttrList);
+    }
+    // PASS THROUGH.
+
+  default: {
+    if ((getLang().CPlusPlus || !OnlyStatement) && isDeclarationStatement()) {
+      SourceLocation DeclStart = Tok.getLocation(), DeclEnd;
+      DeclGroupPtrTy Decl = ParseDeclaration(Declarator::BlockContext, DeclEnd,
+                                             Attr);
+      return Actions.ActOnDeclStmt(Decl, DeclStart, DeclEnd);
+    }
+
+    if (Tok.is(tok::r_brace)) {
+      Diag(Tok, diag::err_expected_statement);
+      return StmtError();
+    }
+
+    // FIXME: Use the attributes
+    // expression[opt] ';'
+    OwningExprResult Expr(ParseExpression());
+    if (Expr.isInvalid()) {
+      // If the expression is invalid, skip ahead to the next semicolon.  Not
+      // doing this opens us up to the possibility of infinite loops if
+      // ParseExpression does not consume any tokens.
+      SkipUntil(tok::semi);
+      return StmtError();
+    }
+    // Otherwise, eat the semicolon.
+    ExpectAndConsume(tok::semi, diag::err_expected_semi_after_expr);
+    return Actions.ActOnExprStmt(Actions.MakeFullExpr(Expr));
+  }
+
+  case tok::kw_case:                // C99 6.8.1: labeled-statement
+    return ParseCaseStatement(Attr.AttrList);
+  case tok::kw_default:             // C99 6.8.1: labeled-statement
+    return ParseDefaultStatement(Attr.AttrList);
+
+  case tok::l_brace:                // C99 6.8.2: compound-statement
+    return ParseCompoundStatement(Attr.AttrList);
+  case tok::semi:                   // C99 6.8.3p3: expression[opt] ';'
+    return Actions.ActOnNullStmt(ConsumeToken());
+
+  case tok::kw_if:                  // C99 6.8.4.1: if-statement
+    return ParseIfStatement(Attr.AttrList);
+  case tok::kw_switch:              // C99 6.8.4.2: switch-statement
+    return ParseSwitchStatement(Attr.AttrList);
+
+  case tok::kw_while:               // C99 6.8.5.1: while-statement
+    return ParseWhileStatement(Attr.AttrList);
+  case tok::kw_do:                  // C99 6.8.5.2: do-statement
+    Res = ParseDoStatement(Attr.AttrList);
+    SemiError = "do/while";
+    break;
+  case tok::kw_for:                 // C99 6.8.5.3: for-statement
+    return ParseForStatement(Attr.AttrList);
+
+  case tok::kw_goto:                // C99 6.8.6.1: goto-statement
+    Res = ParseGotoStatement(Attr.AttrList);
+    SemiError = "goto";
+    break;
+  case tok::kw_continue:            // C99 6.8.6.2: continue-statement
+    Res = ParseContinueStatement(Attr.AttrList);
+    SemiError = "continue";
+    break;
+  case tok::kw_break:               // C99 6.8.6.3: break-statement
+    Res = ParseBreakStatement(Attr.AttrList);
+    SemiError = "break";
+    break;
+  case tok::kw_return:              // C99 6.8.6.4: return-statement
+    Res = ParseReturnStatement(Attr.AttrList);
+    SemiError = "return";
+    break;
+
+  case tok::kw_asm: {
+    if (Attr.HasAttr)
+      Diag(Attr.Range.getBegin(), diag::err_attributes_not_allowed)
+        << Attr.Range;
+    bool msAsm = false;
+    Res = ParseAsmStatement(msAsm);
+    if (msAsm) return move(Res);
+    SemiError = "asm";
+    break;
+  }
+
+  case tok::kw_try:                 // C++ 15: try-block
+    return ParseCXXTryBlock(Attr.AttrList);
+  }
+
+  // If we reached this code, the statement must end in a semicolon.
+  if (Tok.is(tok::semi)) {
+    ConsumeToken();
+  } else if (!Res.isInvalid()) {
+    // If the result was valid, then we do want to diagnose this.  Use
+    // ExpectAndConsume to emit the diagnostic, even though we know it won't
+    // succeed.
+    ExpectAndConsume(tok::semi, diag::err_expected_semi_after_stmt, SemiError);
+    // Skip until we see a } or ;, but don't eat it.
+    SkipUntil(tok::r_brace, true, true);
+  }
+
+  return move(Res);
+}
+
+/// ParseLabeledStatement - We have an identifier and a ':' after it.
+///
+///       labeled-statement:
+///         identifier ':' statement
+/// [GNU]   identifier ':' attributes[opt] statement
+///
+Parser::OwningStmtResult Parser::ParseLabeledStatement(AttributeList *Attr) {
+  assert(Tok.is(tok::identifier) && Tok.getIdentifierInfo() &&
+         "Not an identifier!");
+
+  Token IdentTok = Tok;  // Save the whole token.
+  ConsumeToken();  // eat the identifier.
+
+  assert(Tok.is(tok::colon) && "Not a label!");
+
+  // identifier ':' statement
+  SourceLocation ColonLoc = ConsumeToken();
+
+  // Read label attributes, if present.
+  if (Tok.is(tok::kw___attribute))
+    Attr = addAttributeLists(Attr, ParseGNUAttributes());
+
+  OwningStmtResult SubStmt(ParseStatement());
+
+  // Broken substmt shouldn't prevent the label from being added to the AST.
+  if (SubStmt.isInvalid())
+    SubStmt = Actions.ActOnNullStmt(ColonLoc);
+
+  return Actions.ActOnLabelStmt(IdentTok.getLocation(),
+                                IdentTok.getIdentifierInfo(),
+                                ColonLoc, move(SubStmt));
+}
+
+/// ParseCaseStatement
+///       labeled-statement:
+///         'case' constant-expression ':' statement
+/// [GNU]   'case' constant-expression '...' constant-expression ':' statement
+///
+Parser::OwningStmtResult Parser::ParseCaseStatement(AttributeList *Attr) {
+  assert(Tok.is(tok::kw_case) && "Not a case stmt!");
+  // FIXME: Use attributes?
+
+  // It is very very common for code to contain many case statements recursively
+  // nested, as in (but usually without indentation):
+  //  case 1:
+  //    case 2:
+  //      case 3:
+  //         case 4:
+  //           case 5: etc.
+  //
+  // Parsing this naively works, but is both inefficient and can cause us to run
+  // out of stack space in our recursive descent parser.  As a special case,
+  // flatten this recursion into an iterative loop.  This is complex and gross,
+  // but all the grossness is constrained to ParseCaseStatement (and some
+  // wierdness in the actions), so this is just local grossness :).
+
+  // TopLevelCase - This is the highest level we have parsed.  'case 1' in the
+  // example above.
+  OwningStmtResult TopLevelCase(Actions, true);
+
+  // DeepestParsedCaseStmt - This is the deepest statement we have parsed, which
+  // gets updated each time a new case is parsed, and whose body is unset so
+  // far.  When parsing 'case 4', this is the 'case 3' node.
+  StmtTy *DeepestParsedCaseStmt = 0;
+
+  // While we have case statements, eat and stack them.
+  do {
+    SourceLocation CaseLoc = ConsumeToken();  // eat the 'case'.
+
+    if (Tok.is(tok::code_completion)) {
+      Actions.CodeCompleteCase(CurScope);
+      ConsumeToken();
+    }
+    
+    /// We don't want to treat 'case x : y' as a potential typo for 'case x::y'.
+    /// Disable this form of error recovery while we're parsing the case
+    /// expression.
+    ColonProtectionRAIIObject ColonProtection(*this);
+    
+    OwningExprResult LHS(ParseConstantExpression());
+    if (LHS.isInvalid()) {
+      SkipUntil(tok::colon);
+      return StmtError();
+    }
+
+    // GNU case range extension.
+    SourceLocation DotDotDotLoc;
+    OwningExprResult RHS(Actions);
+    if (Tok.is(tok::ellipsis)) {
+      Diag(Tok, diag::ext_gnu_case_range);
+      DotDotDotLoc = ConsumeToken();
+
+      RHS = ParseConstantExpression();
+      if (RHS.isInvalid()) {
+        SkipUntil(tok::colon);
+        return StmtError();
+      }
+    }
+    
+    ColonProtection.restore();
+
+    if (Tok.isNot(tok::colon)) {
+      Diag(Tok, diag::err_expected_colon_after) << "'case'";
+      SkipUntil(tok::colon);
+      return StmtError();
+    }
+
+    SourceLocation ColonLoc = ConsumeToken();
+
+    OwningStmtResult Case =
+      Actions.ActOnCaseStmt(CaseLoc, move(LHS), DotDotDotLoc,
+                            move(RHS), ColonLoc);
+
+    // If we had a sema error parsing this case, then just ignore it and
+    // continue parsing the sub-stmt.
+    if (Case.isInvalid()) {
+      if (TopLevelCase.isInvalid())  // No parsed case stmts.
+        return ParseStatement();
+      // Otherwise, just don't add it as a nested case.
+    } else {
+      // If this is the first case statement we parsed, it becomes TopLevelCase.
+      // Otherwise we link it into the current chain.
+      StmtTy *NextDeepest = Case.get();
+      if (TopLevelCase.isInvalid())
+        TopLevelCase = move(Case);
+      else
+        Actions.ActOnCaseStmtBody(DeepestParsedCaseStmt, move(Case));
+      DeepestParsedCaseStmt = NextDeepest;
+    }
+
+    // Handle all case statements.
+  } while (Tok.is(tok::kw_case));
+
+  assert(!TopLevelCase.isInvalid() && "Should have parsed at least one case!");
+
+  // If we found a non-case statement, start by parsing it.
+  OwningStmtResult SubStmt(Actions);
+
+  if (Tok.isNot(tok::r_brace)) {
+    SubStmt = ParseStatement();
+  } else {
+    // Nicely diagnose the common error "switch (X) { case 4: }", which is
+    // not valid.
+    // FIXME: add insertion hint.
+    Diag(Tok, diag::err_label_end_of_compound_statement);
+    SubStmt = true;
+  }
+
+  // Broken sub-stmt shouldn't prevent forming the case statement properly.
+  if (SubStmt.isInvalid())
+    SubStmt = Actions.ActOnNullStmt(SourceLocation());
+
+  // Install the body into the most deeply-nested case.
+  Actions.ActOnCaseStmtBody(DeepestParsedCaseStmt, move(SubStmt));
+
+  // Return the top level parsed statement tree.
+  return move(TopLevelCase);
+}
+
+/// ParseDefaultStatement
+///       labeled-statement:
+///         'default' ':' statement
+/// Note that this does not parse the 'statement' at the end.
+///
+Parser::OwningStmtResult Parser::ParseDefaultStatement(AttributeList *Attr) {
+  //FIXME: Use attributes?
+  assert(Tok.is(tok::kw_default) && "Not a default stmt!");
+  SourceLocation DefaultLoc = ConsumeToken();  // eat the 'default'.
+
+  if (Tok.isNot(tok::colon)) {
+    Diag(Tok, diag::err_expected_colon_after) << "'default'";
+    SkipUntil(tok::colon);
+    return StmtError();
+  }
+
+  SourceLocation ColonLoc = ConsumeToken();
+
+  // Diagnose the common error "switch (X) {... default: }", which is not valid.
+  if (Tok.is(tok::r_brace)) {
+    Diag(Tok, diag::err_label_end_of_compound_statement);
+    return StmtError();
+  }
+
+  OwningStmtResult SubStmt(ParseStatement());
+  if (SubStmt.isInvalid())
+    return StmtError();
+
+  return Actions.ActOnDefaultStmt(DefaultLoc, ColonLoc,
+                                  move(SubStmt), CurScope);
+}
+
+
+/// ParseCompoundStatement - Parse a "{}" block.
+///
+///       compound-statement: [C99 6.8.2]
+///         { block-item-list[opt] }
+/// [GNU]   { label-declarations block-item-list } [TODO]
+///
+///       block-item-list:
+///         block-item
+///         block-item-list block-item
+///
+///       block-item:
+///         declaration
+/// [GNU]   '__extension__' declaration
+///         statement
+/// [OMP]   openmp-directive            [TODO]
+///
+/// [GNU] label-declarations:
+/// [GNU]   label-declaration
+/// [GNU]   label-declarations label-declaration
+///
+/// [GNU] label-declaration:
+/// [GNU]   '__label__' identifier-list ';'
+///
+/// [OMP] openmp-directive:             [TODO]
+/// [OMP]   barrier-directive
+/// [OMP]   flush-directive
+///
+Parser::OwningStmtResult Parser::ParseCompoundStatement(AttributeList *Attr,
+                                                        bool isStmtExpr) {
+  //FIXME: Use attributes?
+  assert(Tok.is(tok::l_brace) && "Not a compount stmt!");
+
+  // Enter a scope to hold everything within the compound stmt.  Compound
+  // statements can always hold declarations.
+  ParseScope CompoundScope(this, Scope::DeclScope);
+
+  // Parse the statements in the body.
+  return ParseCompoundStatementBody(isStmtExpr);
+}
+
+
+/// ParseCompoundStatementBody - Parse a sequence of statements and invoke the
+/// ActOnCompoundStmt action.  This expects the '{' to be the current token, and
+/// consume the '}' at the end of the block.  It does not manipulate the scope
+/// stack.
+Parser::OwningStmtResult Parser::ParseCompoundStatementBody(bool isStmtExpr) {
+  PrettyStackTraceLoc CrashInfo(PP.getSourceManager(),
+                                Tok.getLocation(),
+                                "in compound statement ('{}')");
+
+  SourceLocation LBraceLoc = ConsumeBrace();  // eat the '{'.
+
+  // TODO: "__label__ X, Y, Z;" is the GNU "Local Label" extension.  These are
+  // only allowed at the start of a compound stmt regardless of the language.
+
+  typedef StmtVector StmtsTy;
+  StmtsTy Stmts(Actions);
+  while (Tok.isNot(tok::r_brace) && Tok.isNot(tok::eof)) {
+    OwningStmtResult R(Actions);
+    if (Tok.isNot(tok::kw___extension__)) {
+      R = ParseStatementOrDeclaration(false);
+    } else {
+      // __extension__ can start declarations and it can also be a unary
+      // operator for expressions.  Consume multiple __extension__ markers here
+      // until we can determine which is which.
+      // FIXME: This loses extension expressions in the AST!
+      SourceLocation ExtLoc = ConsumeToken();
+      while (Tok.is(tok::kw___extension__))
+        ConsumeToken();
+
+      CXX0XAttributeList Attr;
+      if (getLang().CPlusPlus0x && isCXX0XAttributeSpecifier())
+        Attr = ParseCXX0XAttributes();
+
+      // If this is the start of a declaration, parse it as such.
+      if (isDeclarationStatement()) {
+        // __extension__ silences extension warnings in the subdeclaration.
+        // FIXME: Save the __extension__ on the decl as a node somehow?
+        ExtensionRAIIObject O(Diags);
+
+        SourceLocation DeclStart = Tok.getLocation(), DeclEnd;
+        DeclGroupPtrTy Res = ParseDeclaration(Declarator::BlockContext, DeclEnd,
+                                              Attr);
+        R = Actions.ActOnDeclStmt(Res, DeclStart, DeclEnd);
+      } else {
+        // Otherwise this was a unary __extension__ marker.
+        OwningExprResult Res(ParseExpressionWithLeadingExtension(ExtLoc));
+
+        if (Res.isInvalid()) {
+          SkipUntil(tok::semi);
+          continue;
+        }
+
+        // FIXME: Use attributes?
+        // Eat the semicolon at the end of stmt and convert the expr into a
+        // statement.
+        ExpectAndConsume(tok::semi, diag::err_expected_semi_after_expr);
+        R = Actions.ActOnExprStmt(Actions.MakeFullExpr(Res));
+      }
+    }
+
+    if (R.isUsable())
+      Stmts.push_back(R.release());
+  }
+
+  // We broke out of the while loop because we found a '}' or EOF.
+  if (Tok.isNot(tok::r_brace)) {
+    Diag(Tok, diag::err_expected_rbrace);
+    return StmtError();
+  }
+
+  SourceLocation RBraceLoc = ConsumeBrace();
+  return Actions.ActOnCompoundStmt(LBraceLoc, RBraceLoc, move_arg(Stmts),
+                                   isStmtExpr);
+}
+
+/// ParseParenExprOrCondition:
+/// [C  ]     '(' expression ')'
+/// [C++]     '(' condition ')'       [not allowed if OnlyAllowCondition=true]
+///
+/// This function parses and performs error recovery on the specified condition
+/// or expression (depending on whether we're in C++ or C mode).  This function
+/// goes out of its way to recover well.  It returns true if there was a parser
+/// error (the right paren couldn't be found), which indicates that the caller
+/// should try to recover harder.  It returns false if the condition is
+/// successfully parsed.  Note that a successful parse can still have semantic
+/// errors in the condition.
+bool Parser::ParseParenExprOrCondition(OwningExprResult &ExprResult,
+                                       DeclPtrTy &DeclResult) {
+  bool ParseError = false;
+  
+  SourceLocation LParenLoc = ConsumeParen();
+  if (getLang().CPlusPlus) 
+    ParseError = ParseCXXCondition(ExprResult, DeclResult);
+  else {
+    ExprResult = ParseExpression();
+    DeclResult = DeclPtrTy();
+  }
+
+  // If the parser was confused by the condition and we don't have a ')', try to
+  // recover by skipping ahead to a semi and bailing out.  If condexp is
+  // semantically invalid but we have well formed code, keep going.
+  if (ExprResult.isInvalid() && !DeclResult.get() && Tok.isNot(tok::r_paren)) {
+    SkipUntil(tok::semi);
+    // Skipping may have stopped if it found the containing ')'.  If so, we can
+    // continue parsing the if statement.
+    if (Tok.isNot(tok::r_paren))
+      return true;
+  }
+
+  // Otherwise the condition is valid or the rparen is present.
+  MatchRHSPunctuation(tok::r_paren, LParenLoc);
+  return false;
+}
+
+
+/// ParseIfStatement
+///       if-statement: [C99 6.8.4.1]
+///         'if' '(' expression ')' statement
+///         'if' '(' expression ')' statement 'else' statement
+/// [C++]   'if' '(' condition ')' statement
+/// [C++]   'if' '(' condition ')' statement 'else' statement
+///
+Parser::OwningStmtResult Parser::ParseIfStatement(AttributeList *Attr) {
+  // FIXME: Use attributes?
+  assert(Tok.is(tok::kw_if) && "Not an if stmt!");
+  SourceLocation IfLoc = ConsumeToken();  // eat the 'if'.
+
+  if (Tok.isNot(tok::l_paren)) {
+    Diag(Tok, diag::err_expected_lparen_after) << "if";
+    SkipUntil(tok::semi);
+    return StmtError();
+  }
+
+  bool C99orCXX = getLang().C99 || getLang().CPlusPlus;
+
+  // C99 6.8.4p3 - In C99, the if statement is a block.  This is not
+  // the case for C90.
+  //
+  // C++ 6.4p3:
+  // A name introduced by a declaration in a condition is in scope from its
+  // point of declaration until the end of the substatements controlled by the
+  // condition.
+  // C++ 3.3.2p4:
+  // Names declared in the for-init-statement, and in the condition of if,
+  // while, for, and switch statements are local to the if, while, for, or
+  // switch statement (including the controlled statement).
+  //
+  ParseScope IfScope(this, Scope::DeclScope | Scope::ControlScope, C99orCXX);
+
+  // Parse the condition.
+  OwningExprResult CondExp(Actions);
+  DeclPtrTy CondVar;
+  if (ParseParenExprOrCondition(CondExp, CondVar))
+    return StmtError();
+
+  FullExprArg FullCondExp(Actions.MakeFullExpr(CondExp));
+
+  // C99 6.8.4p3 - In C99, the body of the if statement is a scope, even if
+  // there is no compound stmt.  C90 does not have this clause.  We only do this
+  // if the body isn't a compound statement to avoid push/pop in common cases.
+  //
+  // C++ 6.4p1:
+  // The substatement in a selection-statement (each substatement, in the else
+  // form of the if statement) implicitly defines a local scope.
+  //
+  // For C++ we create a scope for the condition and a new scope for
+  // substatements because:
+  // -When the 'then' scope exits, we want the condition declaration to still be
+  //    active for the 'else' scope too.
+  // -Sema will detect name clashes by considering declarations of a
+  //    'ControlScope' as part of its direct subscope.
+  // -If we wanted the condition and substatement to be in the same scope, we
+  //    would have to notify ParseStatement not to create a new scope. It's
+  //    simpler to let it create a new scope.
+  //
+  ParseScope InnerScope(this, Scope::DeclScope,
+                        C99orCXX && Tok.isNot(tok::l_brace));
+
+  // Read the 'then' stmt.
+  SourceLocation ThenStmtLoc = Tok.getLocation();
+  OwningStmtResult ThenStmt(ParseStatement());
+
+  // Pop the 'if' scope if needed.
+  InnerScope.Exit();
+
+  // If it has an else, parse it.
+  SourceLocation ElseLoc;
+  SourceLocation ElseStmtLoc;
+  OwningStmtResult ElseStmt(Actions);
+
+  if (Tok.is(tok::kw_else)) {
+    ElseLoc = ConsumeToken();
+
+    // C99 6.8.4p3 - In C99, the body of the if statement is a scope, even if
+    // there is no compound stmt.  C90 does not have this clause.  We only do
+    // this if the body isn't a compound statement to avoid push/pop in common
+    // cases.
+    //
+    // C++ 6.4p1:
+    // The substatement in a selection-statement (each substatement, in the else
+    // form of the if statement) implicitly defines a local scope.
+    //
+    ParseScope InnerScope(this, Scope::DeclScope,
+                          C99orCXX && Tok.isNot(tok::l_brace));
+
+    bool WithinElse = CurScope->isWithinElse();
+    CurScope->setWithinElse(true);
+    ElseStmtLoc = Tok.getLocation();
+    ElseStmt = ParseStatement();
+    CurScope->setWithinElse(WithinElse);
+
+    // Pop the 'else' scope if needed.
+    InnerScope.Exit();
+  }
+
+  IfScope.Exit();
+
+  // If the condition was invalid, discard the if statement.  We could recover
+  // better by replacing it with a valid expr, but don't do that yet.
+  if (CondExp.isInvalid() && !CondVar.get())
+    return StmtError();
+
+  // If the then or else stmt is invalid and the other is valid (and present),
+  // make turn the invalid one into a null stmt to avoid dropping the other
+  // part.  If both are invalid, return error.
+  if ((ThenStmt.isInvalid() && ElseStmt.isInvalid()) ||
+      (ThenStmt.isInvalid() && ElseStmt.get() == 0) ||
+      (ThenStmt.get() == 0  && ElseStmt.isInvalid())) {
+    // Both invalid, or one is invalid and other is non-present: return error.
+    return StmtError();
+  }
+
+  // Now if either are invalid, replace with a ';'.
+  if (ThenStmt.isInvalid())
+    ThenStmt = Actions.ActOnNullStmt(ThenStmtLoc);
+  if (ElseStmt.isInvalid())
+    ElseStmt = Actions.ActOnNullStmt(ElseStmtLoc);
+
+  return Actions.ActOnIfStmt(IfLoc, FullCondExp, CondVar, move(ThenStmt),
+                             ElseLoc, move(ElseStmt));
+}
+
+/// ParseSwitchStatement
+///       switch-statement:
+///         'switch' '(' expression ')' statement
+/// [C++]   'switch' '(' condition ')' statement
+Parser::OwningStmtResult Parser::ParseSwitchStatement(AttributeList *Attr) {
+  // FIXME: Use attributes?
+  assert(Tok.is(tok::kw_switch) && "Not a switch stmt!");
+  SourceLocation SwitchLoc = ConsumeToken();  // eat the 'switch'.
+
+  if (Tok.isNot(tok::l_paren)) {
+    Diag(Tok, diag::err_expected_lparen_after) << "switch";
+    SkipUntil(tok::semi);
+    return StmtError();
+  }
+
+  bool C99orCXX = getLang().C99 || getLang().CPlusPlus;
+
+  // C99 6.8.4p3 - In C99, the switch statement is a block.  This is
+  // not the case for C90.  Start the switch scope.
+  //
+  // C++ 6.4p3:
+  // A name introduced by a declaration in a condition is in scope from its
+  // point of declaration until the end of the substatements controlled by the
+  // condition.
+  // C++ 3.3.2p4:
+  // Names declared in the for-init-statement, and in the condition of if,
+  // while, for, and switch statements are local to the if, while, for, or
+  // switch statement (including the controlled statement).
+  //
+  unsigned ScopeFlags = Scope::BreakScope;
+  if (C99orCXX)
+    ScopeFlags |= Scope::DeclScope | Scope::ControlScope;
+  ParseScope SwitchScope(this, ScopeFlags);
+
+  // Parse the condition.
+  OwningExprResult Cond(Actions);
+  DeclPtrTy CondVar;
+  if (ParseParenExprOrCondition(Cond, CondVar))
+    return StmtError();
+
+  FullExprArg FullCond(Actions.MakeFullExpr(Cond));
+  
+  OwningStmtResult Switch = Actions.ActOnStartOfSwitchStmt(FullCond, CondVar);
+
+  // C99 6.8.4p3 - In C99, the body of the switch statement is a scope, even if
+  // there is no compound stmt.  C90 does not have this clause.  We only do this
+  // if the body isn't a compound statement to avoid push/pop in common cases.
+  //
+  // C++ 6.4p1:
+  // The substatement in a selection-statement (each substatement, in the else
+  // form of the if statement) implicitly defines a local scope.
+  //
+  // See comments in ParseIfStatement for why we create a scope for the
+  // condition and a new scope for substatement in C++.
+  //
+  ParseScope InnerScope(this, Scope::DeclScope,
+                        C99orCXX && Tok.isNot(tok::l_brace));
+
+  // Read the body statement.
+  OwningStmtResult Body(ParseStatement());
+
+  // Pop the scopes.
+  InnerScope.Exit();
+  SwitchScope.Exit();
+
+  if (Cond.isInvalid() && !CondVar.get()) {
+    Actions.ActOnSwitchBodyError(SwitchLoc, move(Switch), move(Body));
+    return StmtError();
+  }
+
+  if (Body.isInvalid())
+    // FIXME: Remove the case statement list from the Switch statement.
+    Body = Actions.ActOnNullStmt(Tok.getLocation());
+  
+  return Actions.ActOnFinishSwitchStmt(SwitchLoc, move(Switch), move(Body));
+}
+
+/// ParseWhileStatement
+///       while-statement: [C99 6.8.5.1]
+///         'while' '(' expression ')' statement
+/// [C++]   'while' '(' condition ')' statement
+Parser::OwningStmtResult Parser::ParseWhileStatement(AttributeList *Attr) {
+  // FIXME: Use attributes?
+  assert(Tok.is(tok::kw_while) && "Not a while stmt!");
+  SourceLocation WhileLoc = Tok.getLocation();
+  ConsumeToken();  // eat the 'while'.
+
+  if (Tok.isNot(tok::l_paren)) {
+    Diag(Tok, diag::err_expected_lparen_after) << "while";
+    SkipUntil(tok::semi);
+    return StmtError();
+  }
+
+  bool C99orCXX = getLang().C99 || getLang().CPlusPlus;
+
+  // C99 6.8.5p5 - In C99, the while statement is a block.  This is not
+  // the case for C90.  Start the loop scope.
+  //
+  // C++ 6.4p3:
+  // A name introduced by a declaration in a condition is in scope from its
+  // point of declaration until the end of the substatements controlled by the
+  // condition.
+  // C++ 3.3.2p4:
+  // Names declared in the for-init-statement, and in the condition of if,
+  // while, for, and switch statements are local to the if, while, for, or
+  // switch statement (including the controlled statement).
+  //
+  unsigned ScopeFlags;
+  if (C99orCXX)
+    ScopeFlags = Scope::BreakScope | Scope::ContinueScope |
+                 Scope::DeclScope  | Scope::ControlScope;
+  else
+    ScopeFlags = Scope::BreakScope | Scope::ContinueScope;
+  ParseScope WhileScope(this, ScopeFlags);
+
+  // Parse the condition.
+  OwningExprResult Cond(Actions);
+  DeclPtrTy CondVar;
+  if (ParseParenExprOrCondition(Cond, CondVar))
+    return StmtError();
+
+  FullExprArg FullCond(Actions.MakeFullExpr(Cond));
+
+  // C99 6.8.5p5 - In C99, the body of the if statement is a scope, even if
+  // there is no compound stmt.  C90 does not have this clause.  We only do this
+  // if the body isn't a compound statement to avoid push/pop in common cases.
+  //
+  // C++ 6.5p2:
+  // The substatement in an iteration-statement implicitly defines a local scope
+  // which is entered and exited each time through the loop.
+  //
+  // See comments in ParseIfStatement for why we create a scope for the
+  // condition and a new scope for substatement in C++.
+  //
+  ParseScope InnerScope(this, Scope::DeclScope,
+                        C99orCXX && Tok.isNot(tok::l_brace));
+
+  // Read the body statement.
+  OwningStmtResult Body(ParseStatement());
+
+  // Pop the body scope if needed.
+  InnerScope.Exit();
+  WhileScope.Exit();
+
+  if ((Cond.isInvalid() && !CondVar.get()) || Body.isInvalid())
+    return StmtError();
+
+  return Actions.ActOnWhileStmt(WhileLoc, FullCond, CondVar, move(Body));
+}
+
+/// ParseDoStatement
+///       do-statement: [C99 6.8.5.2]
+///         'do' statement 'while' '(' expression ')' ';'
+/// Note: this lets the caller parse the end ';'.
+Parser::OwningStmtResult Parser::ParseDoStatement(AttributeList *Attr) {
+  // FIXME: Use attributes?
+  assert(Tok.is(tok::kw_do) && "Not a do stmt!");
+  SourceLocation DoLoc = ConsumeToken();  // eat the 'do'.
+
+  // C99 6.8.5p5 - In C99, the do statement is a block.  This is not
+  // the case for C90.  Start the loop scope.
+  unsigned ScopeFlags;
+  if (getLang().C99)
+    ScopeFlags = Scope::BreakScope | Scope::ContinueScope | Scope::DeclScope;
+  else
+    ScopeFlags = Scope::BreakScope | Scope::ContinueScope;
+
+  ParseScope DoScope(this, ScopeFlags);
+
+  // C99 6.8.5p5 - In C99, the body of the if statement is a scope, even if
+  // there is no compound stmt.  C90 does not have this clause. We only do this
+  // if the body isn't a compound statement to avoid push/pop in common cases.
+  //
+  // C++ 6.5p2:
+  // The substatement in an iteration-statement implicitly defines a local scope
+  // which is entered and exited each time through the loop.
+  //
+  ParseScope InnerScope(this, Scope::DeclScope,
+                        (getLang().C99 || getLang().CPlusPlus) &&
+                        Tok.isNot(tok::l_brace));
+
+  // Read the body statement.
+  OwningStmtResult Body(ParseStatement());
+
+  // Pop the body scope if needed.
+  InnerScope.Exit();
+
+  if (Tok.isNot(tok::kw_while)) {
+    if (!Body.isInvalid()) {
+      Diag(Tok, diag::err_expected_while);
+      Diag(DoLoc, diag::note_matching) << "do";
+      SkipUntil(tok::semi, false, true);
+    }
+    return StmtError();
+  }
+  SourceLocation WhileLoc = ConsumeToken();
+
+  if (Tok.isNot(tok::l_paren)) {
+    Diag(Tok, diag::err_expected_lparen_after) << "do/while";
+    SkipUntil(tok::semi, false, true);
+    return StmtError();
+  }
+
+  // Parse the parenthesized condition.
+  SourceLocation LPLoc = ConsumeParen();
+  OwningExprResult Cond = ParseExpression();
+  SourceLocation RPLoc = MatchRHSPunctuation(tok::r_paren, LPLoc);
+  DoScope.Exit();
+
+  if (Cond.isInvalid() || Body.isInvalid())
+    return StmtError();
+
+  return Actions.ActOnDoStmt(DoLoc, move(Body), WhileLoc, LPLoc,
+                             move(Cond), RPLoc);
+}
+
+/// ParseForStatement
+///       for-statement: [C99 6.8.5.3]
+///         'for' '(' expr[opt] ';' expr[opt] ';' expr[opt] ')' statement
+///         'for' '(' declaration expr[opt] ';' expr[opt] ')' statement
+/// [C++]   'for' '(' for-init-statement condition[opt] ';' expression[opt] ')'
+/// [C++]       statement
+/// [OBJC2] 'for' '(' declaration 'in' expr ')' statement
+/// [OBJC2] 'for' '(' expr 'in' expr ')' statement
+///
+/// [C++] for-init-statement:
+/// [C++]   expression-statement
+/// [C++]   simple-declaration
+///
+Parser::OwningStmtResult Parser::ParseForStatement(AttributeList *Attr) {
+  // FIXME: Use attributes?
+  assert(Tok.is(tok::kw_for) && "Not a for stmt!");
+  SourceLocation ForLoc = ConsumeToken();  // eat the 'for'.
+
+  if (Tok.isNot(tok::l_paren)) {
+    Diag(Tok, diag::err_expected_lparen_after) << "for";
+    SkipUntil(tok::semi);
+    return StmtError();
+  }
+
+  bool C99orCXXorObjC = getLang().C99 || getLang().CPlusPlus || getLang().ObjC1;
+
+  // C99 6.8.5p5 - In C99, the for statement is a block.  This is not
+  // the case for C90.  Start the loop scope.
+  //
+  // C++ 6.4p3:
+  // A name introduced by a declaration in a condition is in scope from its
+  // point of declaration until the end of the substatements controlled by the
+  // condition.
+  // C++ 3.3.2p4:
+  // Names declared in the for-init-statement, and in the condition of if,
+  // while, for, and switch statements are local to the if, while, for, or
+  // switch statement (including the controlled statement).
+  // C++ 6.5.3p1:
+  // Names declared in the for-init-statement are in the same declarative-region
+  // as those declared in the condition.
+  //
+  unsigned ScopeFlags;
+  if (C99orCXXorObjC)
+    ScopeFlags = Scope::BreakScope | Scope::ContinueScope |
+                 Scope::DeclScope  | Scope::ControlScope;
+  else
+    ScopeFlags = Scope::BreakScope | Scope::ContinueScope;
+
+  ParseScope ForScope(this, ScopeFlags);
+
+  SourceLocation LParenLoc = ConsumeParen();
+  OwningExprResult Value(Actions);
+
+  bool ForEach = false;
+  OwningStmtResult FirstPart(Actions);
+  OwningExprResult SecondPart(Actions), ThirdPart(Actions);
+  DeclPtrTy SecondVar;
+  
+  if (Tok.is(tok::code_completion)) {
+    Actions.CodeCompleteOrdinaryName(CurScope, 
+                                     C99orCXXorObjC? Action::CCC_ForInit
+                                                   : Action::CCC_Expression);
+    ConsumeToken();
+  }
+  
+  // Parse the first part of the for specifier.
+  if (Tok.is(tok::semi)) {  // for (;
+    // no first part, eat the ';'.
+    ConsumeToken();
+  } else if (isSimpleDeclaration()) {  // for (int X = 4;
+    // Parse declaration, which eats the ';'.
+    if (!C99orCXXorObjC)   // Use of C99-style for loops in C90 mode?
+      Diag(Tok, diag::ext_c99_variable_decl_in_for_loop);
+
+    AttributeList *AttrList = 0;
+    if (getLang().CPlusPlus0x && isCXX0XAttributeSpecifier())
+      AttrList = ParseCXX0XAttributes().AttrList;
+
+    SourceLocation DeclStart = Tok.getLocation(), DeclEnd;
+    DeclGroupPtrTy DG = ParseSimpleDeclaration(Declarator::ForContext, DeclEnd,
+                                               AttrList);
+    FirstPart = Actions.ActOnDeclStmt(DG, DeclStart, Tok.getLocation());
+
+    if (Tok.is(tok::semi)) {  // for (int x = 4;
+      ConsumeToken();
+    } else if ((ForEach = isTokIdentifier_in())) {
+      Actions.ActOnForEachDeclStmt(DG);
+      // ObjC: for (id x in expr)
+      ConsumeToken(); // consume 'in'
+      SecondPart = ParseExpression();
+    } else {
+      Diag(Tok, diag::err_expected_semi_for);
+      SkipUntil(tok::semi);
+    }
+  } else {
+    Value = ParseExpression();
+
+    // Turn the expression into a stmt.
+    if (!Value.isInvalid())
+      FirstPart = Actions.ActOnExprStmt(Actions.MakeFullExpr(Value));
+
+    if (Tok.is(tok::semi)) {
+      ConsumeToken();
+    } else if ((ForEach = isTokIdentifier_in())) {
+      ConsumeToken(); // consume 'in'
+      SecondPart = ParseExpression();
+    } else {
+      if (!Value.isInvalid()) Diag(Tok, diag::err_expected_semi_for);
+      SkipUntil(tok::semi);
+    }
+  }
+  if (!ForEach) {
+    assert(!SecondPart.get() && "Shouldn't have a second expression yet.");
+    // Parse the second part of the for specifier.
+    if (Tok.is(tok::semi)) {  // for (...;;
+      // no second part.
+    } else {
+      if (getLang().CPlusPlus)
+        ParseCXXCondition(SecondPart, SecondVar);
+      else
+        SecondPart = ParseExpression();
+    }
+
+    if (Tok.is(tok::semi)) {
+      ConsumeToken();
+    } else {
+      if (!SecondPart.isInvalid() || SecondVar.get()) 
+        Diag(Tok, diag::err_expected_semi_for);
+      SkipUntil(tok::semi);
+    }
+
+    // Parse the third part of the for specifier.
+    if (Tok.isNot(tok::r_paren))    // for (...;...;)
+      ThirdPart = ParseExpression();
+  }
+  // Match the ')'.
+  SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc);
+
+  // C99 6.8.5p5 - In C99, the body of the if statement is a scope, even if
+  // there is no compound stmt.  C90 does not have this clause.  We only do this
+  // if the body isn't a compound statement to avoid push/pop in common cases.
+  //
+  // C++ 6.5p2:
+  // The substatement in an iteration-statement implicitly defines a local scope
+  // which is entered and exited each time through the loop.
+  //
+  // See comments in ParseIfStatement for why we create a scope for
+  // for-init-statement/condition and a new scope for substatement in C++.
+  //
+  ParseScope InnerScope(this, Scope::DeclScope,
+                        C99orCXXorObjC && Tok.isNot(tok::l_brace));
+
+  // Read the body statement.
+  OwningStmtResult Body(ParseStatement());
+
+  // Pop the body scope if needed.
+  InnerScope.Exit();
+
+  // Leave the for-scope.
+  ForScope.Exit();
+
+  if (Body.isInvalid())
+    return StmtError();
+
+  if (!ForEach)
+    return Actions.ActOnForStmt(ForLoc, LParenLoc, move(FirstPart),
+                                Actions.MakeFullExpr(SecondPart), SecondVar,
+                                Actions.MakeFullExpr(ThirdPart), RParenLoc, 
+                                move(Body));
+
+  return Actions.ActOnObjCForCollectionStmt(ForLoc, LParenLoc,
+                                            move(FirstPart),
+                                            move(SecondPart),
+                                            RParenLoc, move(Body));
+}
+
+/// ParseGotoStatement
+///       jump-statement:
+///         'goto' identifier ';'
+/// [GNU]   'goto' '*' expression ';'
+///
+/// Note: this lets the caller parse the end ';'.
+///
+Parser::OwningStmtResult Parser::ParseGotoStatement(AttributeList *Attr) {
+  // FIXME: Use attributes?
+  assert(Tok.is(tok::kw_goto) && "Not a goto stmt!");
+  SourceLocation GotoLoc = ConsumeToken();  // eat the 'goto'.
+
+  OwningStmtResult Res(Actions);
+  if (Tok.is(tok::identifier)) {
+    Res = Actions.ActOnGotoStmt(GotoLoc, Tok.getLocation(),
+                                Tok.getIdentifierInfo());
+    ConsumeToken();
+  } else if (Tok.is(tok::star)) {
+    // GNU indirect goto extension.
+    Diag(Tok, diag::ext_gnu_indirect_goto);
+    SourceLocation StarLoc = ConsumeToken();
+    OwningExprResult R(ParseExpression());
+    if (R.isInvalid()) {  // Skip to the semicolon, but don't consume it.
+      SkipUntil(tok::semi, false, true);
+      return StmtError();
+    }
+    Res = Actions.ActOnIndirectGotoStmt(GotoLoc, StarLoc, move(R));
+  } else {
+    Diag(Tok, diag::err_expected_ident);
+    return StmtError();
+  }
+
+  return move(Res);
+}
+
+/// ParseContinueStatement
+///       jump-statement:
+///         'continue' ';'
+///
+/// Note: this lets the caller parse the end ';'.
+///
+Parser::OwningStmtResult Parser::ParseContinueStatement(AttributeList *Attr) {
+  // FIXME: Use attributes?
+  SourceLocation ContinueLoc = ConsumeToken();  // eat the 'continue'.
+  return Actions.ActOnContinueStmt(ContinueLoc, CurScope);
+}
+
+/// ParseBreakStatement
+///       jump-statement:
+///         'break' ';'
+///
+/// Note: this lets the caller parse the end ';'.
+///
+Parser::OwningStmtResult Parser::ParseBreakStatement(AttributeList *Attr) {
+  // FIXME: Use attributes?
+  SourceLocation BreakLoc = ConsumeToken();  // eat the 'break'.
+  return Actions.ActOnBreakStmt(BreakLoc, CurScope);
+}
+
+/// ParseReturnStatement
+///       jump-statement:
+///         'return' expression[opt] ';'
+Parser::OwningStmtResult Parser::ParseReturnStatement(AttributeList *Attr) {
+  // FIXME: Use attributes?
+  assert(Tok.is(tok::kw_return) && "Not a return stmt!");
+  SourceLocation ReturnLoc = ConsumeToken();  // eat the 'return'.
+
+  OwningExprResult R(Actions);
+  if (Tok.isNot(tok::semi)) {
+    R = ParseExpression();
+    if (R.isInvalid()) {  // Skip to the semicolon, but don't consume it.
+      SkipUntil(tok::semi, false, true);
+      return StmtError();
+    }
+  }
+  return Actions.ActOnReturnStmt(ReturnLoc, move(R));
+}
+
+/// FuzzyParseMicrosoftAsmStatement. When -fms-extensions is enabled, this
+/// routine is called to skip/ignore tokens that comprise the MS asm statement.
+Parser::OwningStmtResult Parser::FuzzyParseMicrosoftAsmStatement() {
+  if (Tok.is(tok::l_brace)) {
+    unsigned short savedBraceCount = BraceCount;
+    do {
+      ConsumeAnyToken();
+    } while (BraceCount > savedBraceCount && Tok.isNot(tok::eof));
+  } else {
+    // From the MS website: If used without braces, the __asm keyword means
+    // that the rest of the line is an assembly-language statement.
+    SourceManager &SrcMgr = PP.getSourceManager();
+    SourceLocation TokLoc = Tok.getLocation();
+    unsigned LineNo = SrcMgr.getInstantiationLineNumber(TokLoc);
+    do {
+      ConsumeAnyToken();
+      TokLoc = Tok.getLocation();
+    } while ((SrcMgr.getInstantiationLineNumber(TokLoc) == LineNo) &&
+             Tok.isNot(tok::r_brace) && Tok.isNot(tok::semi) &&
+             Tok.isNot(tok::eof));
+  }
+  Token t;
+  t.setKind(tok::string_literal);
+  t.setLiteralData("\"FIXME: not done\"");
+  t.clearFlag(Token::NeedsCleaning);
+  t.setLength(17);
+  OwningExprResult AsmString(Actions.ActOnStringLiteral(&t, 1));
+  ExprVector Constraints(Actions);
+  ExprVector Exprs(Actions);
+  ExprVector Clobbers(Actions);
+  return Actions.ActOnAsmStmt(Tok.getLocation(), true, true, 0, 0, 0,
+                              move_arg(Constraints), move_arg(Exprs),
+                              move(AsmString), move_arg(Clobbers),
+                              Tok.getLocation(), true);
+}
+
+/// ParseAsmStatement - Parse a GNU extended asm statement.
+///       asm-statement:
+///         gnu-asm-statement
+///         ms-asm-statement
+///
+/// [GNU] gnu-asm-statement:
+///         'asm' type-qualifier[opt] '(' asm-argument ')' ';'
+///
+/// [GNU] asm-argument:
+///         asm-string-literal
+///         asm-string-literal ':' asm-operands[opt]
+///         asm-string-literal ':' asm-operands[opt] ':' asm-operands[opt]
+///         asm-string-literal ':' asm-operands[opt] ':' asm-operands[opt]
+///                 ':' asm-clobbers
+///
+/// [GNU] asm-clobbers:
+///         asm-string-literal
+///         asm-clobbers ',' asm-string-literal
+///
+/// [MS]  ms-asm-statement:
+///         '__asm' assembly-instruction ';'[opt]
+///         '__asm' '{' assembly-instruction-list '}' ';'[opt]
+///
+/// [MS]  assembly-instruction-list:
+///         assembly-instruction ';'[opt]
+///         assembly-instruction-list ';' assembly-instruction ';'[opt]
+///
+Parser::OwningStmtResult Parser::ParseAsmStatement(bool &msAsm) {
+  assert(Tok.is(tok::kw_asm) && "Not an asm stmt");
+  SourceLocation AsmLoc = ConsumeToken();
+
+  if (getLang().Microsoft && Tok.isNot(tok::l_paren) && !isTypeQualifier()) {
+    msAsm = true;
+    return FuzzyParseMicrosoftAsmStatement();
+  }
+  DeclSpec DS;
+  SourceLocation Loc = Tok.getLocation();
+  ParseTypeQualifierListOpt(DS, true, false);
+
+  // GNU asms accept, but warn, about type-qualifiers other than volatile.
+  if (DS.getTypeQualifiers() & DeclSpec::TQ_const)
+    Diag(Loc, diag::w_asm_qualifier_ignored) << "const";
+  if (DS.getTypeQualifiers() & DeclSpec::TQ_restrict)
+    Diag(Loc, diag::w_asm_qualifier_ignored) << "restrict";
+
+  // Remember if this was a volatile asm.
+  bool isVolatile = DS.getTypeQualifiers() & DeclSpec::TQ_volatile;
+  if (Tok.isNot(tok::l_paren)) {
+    Diag(Tok, diag::err_expected_lparen_after) << "asm";
+    SkipUntil(tok::r_paren);
+    return StmtError();
+  }
+  Loc = ConsumeParen();
+
+  OwningExprResult AsmString(ParseAsmStringLiteral());
+  if (AsmString.isInvalid())
+    return StmtError();
+
+  llvm::SmallVector<IdentifierInfo *, 4> Names;
+  ExprVector Constraints(Actions);
+  ExprVector Exprs(Actions);
+  ExprVector Clobbers(Actions);
+
+  if (Tok.is(tok::r_paren)) {
+    // We have a simple asm expression like 'asm("foo")'.
+    SourceLocation RParenLoc = ConsumeParen();
+    return Actions.ActOnAsmStmt(AsmLoc, /*isSimple*/ true, isVolatile,
+                                /*NumOutputs*/ 0, /*NumInputs*/ 0, 0, 
+                                move_arg(Constraints), move_arg(Exprs),
+                                move(AsmString), move_arg(Clobbers),
+                                RParenLoc);
+  }
+
+  // Parse Outputs, if present.
+  bool AteExtraColon = false;
+  if (Tok.is(tok::colon) || Tok.is(tok::coloncolon)) {
+    // In C++ mode, parse "::" like ": :".
+    AteExtraColon = Tok.is(tok::coloncolon);
+    ConsumeToken();
+  
+    if (!AteExtraColon &&
+        ParseAsmOperandsOpt(Names, Constraints, Exprs))
+      return StmtError();
+  }
+  
+  unsigned NumOutputs = Names.size();
+
+  // Parse Inputs, if present.
+  if (AteExtraColon ||
+      Tok.is(tok::colon) || Tok.is(tok::coloncolon)) {
+    // In C++ mode, parse "::" like ": :".
+    if (AteExtraColon)
+      AteExtraColon = false;
+    else {
+      AteExtraColon = Tok.is(tok::coloncolon);
+      ConsumeToken();
+    }
+    
+    if (!AteExtraColon &&
+        ParseAsmOperandsOpt(Names, Constraints, Exprs))
+      return StmtError();
+  }
+
+  assert(Names.size() == Constraints.size() &&
+         Constraints.size() == Exprs.size() &&
+         "Input operand size mismatch!");
+
+  unsigned NumInputs = Names.size() - NumOutputs;
+
+  // Parse the clobbers, if present.
+  if (AteExtraColon || Tok.is(tok::colon)) {
+    if (!AteExtraColon)
+      ConsumeToken();
+
+    // Parse the asm-string list for clobbers.
+    while (1) {
+      OwningExprResult Clobber(ParseAsmStringLiteral());
+
+      if (Clobber.isInvalid())
+        break;
+
+      Clobbers.push_back(Clobber.release());
+
+      if (Tok.isNot(tok::comma)) break;
+      ConsumeToken();
+    }
+  }
+
+  SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, Loc);
+  return Actions.ActOnAsmStmt(AsmLoc, false, isVolatile,
+                              NumOutputs, NumInputs, Names.data(),
+                              move_arg(Constraints), move_arg(Exprs),
+                              move(AsmString), move_arg(Clobbers),
+                              RParenLoc);
+}
+
+/// ParseAsmOperands - Parse the asm-operands production as used by
+/// asm-statement, assuming the leading ':' token was eaten.
+///
+/// [GNU] asm-operands:
+///         asm-operand
+///         asm-operands ',' asm-operand
+///
+/// [GNU] asm-operand:
+///         asm-string-literal '(' expression ')'
+///         '[' identifier ']' asm-string-literal '(' expression ')'
+///
+//
+// FIXME: Avoid unnecessary std::string trashing.
+bool Parser::ParseAsmOperandsOpt(llvm::SmallVectorImpl<IdentifierInfo *> &Names,
+                                 llvm::SmallVectorImpl<ExprTy *> &Constraints,
+                                 llvm::SmallVectorImpl<ExprTy *> &Exprs) {
+  // 'asm-operands' isn't present?
+  if (!isTokenStringLiteral() && Tok.isNot(tok::l_square))
+    return false;
+
+  while (1) {
+    // Read the [id] if present.
+    if (Tok.is(tok::l_square)) {
+      SourceLocation Loc = ConsumeBracket();
+
+      if (Tok.isNot(tok::identifier)) {
+        Diag(Tok, diag::err_expected_ident);
+        SkipUntil(tok::r_paren);
+        return true;
+      }
+
+      IdentifierInfo *II = Tok.getIdentifierInfo();
+      ConsumeToken();
+
+      Names.push_back(II);
+      MatchRHSPunctuation(tok::r_square, Loc);
+    } else
+      Names.push_back(0);
+
+    OwningExprResult Constraint(ParseAsmStringLiteral());
+    if (Constraint.isInvalid()) {
+        SkipUntil(tok::r_paren);
+        return true;
+    }
+    Constraints.push_back(Constraint.release());
+
+    if (Tok.isNot(tok::l_paren)) {
+      Diag(Tok, diag::err_expected_lparen_after) << "asm operand";
+      SkipUntil(tok::r_paren);
+      return true;
+    }
+
+    // Read the parenthesized expression.
+    SourceLocation OpenLoc = ConsumeParen();
+    OwningExprResult Res(ParseExpression());
+    MatchRHSPunctuation(tok::r_paren, OpenLoc);
+    if (Res.isInvalid()) {
+      SkipUntil(tok::r_paren);
+      return true;
+    }
+    Exprs.push_back(Res.release());
+    // Eat the comma and continue parsing if it exists.
+    if (Tok.isNot(tok::comma)) return false;
+    ConsumeToken();
+  }
+
+  return true;
+}
+
+Parser::DeclPtrTy Parser::ParseFunctionStatementBody(DeclPtrTy Decl) {
+  assert(Tok.is(tok::l_brace));
+  SourceLocation LBraceLoc = Tok.getLocation();
+
+  PrettyStackTraceActionsDecl CrashInfo(Decl, LBraceLoc, Actions,
+                                        PP.getSourceManager(),
+                                        "parsing function body");
+
+  // Do not enter a scope for the brace, as the arguments are in the same scope
+  // (the function body) as the body itself.  Instead, just read the statement
+  // list and put it into a CompoundStmt for safe keeping.
+  OwningStmtResult FnBody(ParseCompoundStatementBody());
+
+  // If the function body could not be parsed, make a bogus compoundstmt.
+  if (FnBody.isInvalid())
+    FnBody = Actions.ActOnCompoundStmt(LBraceLoc, LBraceLoc,
+                                       MultiStmtArg(Actions), false);
+
+  return Actions.ActOnFinishFunctionBody(Decl, move(FnBody));
+}
+
+/// ParseFunctionTryBlock - Parse a C++ function-try-block.
+///
+///       function-try-block:
+///         'try' ctor-initializer[opt] compound-statement handler-seq
+///
+Parser::DeclPtrTy Parser::ParseFunctionTryBlock(DeclPtrTy Decl) {
+  assert(Tok.is(tok::kw_try) && "Expected 'try'");
+  SourceLocation TryLoc = ConsumeToken();
+
+  PrettyStackTraceActionsDecl CrashInfo(Decl, TryLoc, Actions,
+                                        PP.getSourceManager(),
+                                        "parsing function try block");
+
+  // Constructor initializer list?
+  if (Tok.is(tok::colon))
+    ParseConstructorInitializer(Decl);
+
+  SourceLocation LBraceLoc = Tok.getLocation();
+  OwningStmtResult FnBody(ParseCXXTryBlockCommon(TryLoc));
+  // If we failed to parse the try-catch, we just give the function an empty
+  // compound statement as the body.
+  if (FnBody.isInvalid())
+    FnBody = Actions.ActOnCompoundStmt(LBraceLoc, LBraceLoc,
+                                       MultiStmtArg(Actions), false);
+
+  return Actions.ActOnFinishFunctionBody(Decl, move(FnBody));
+}
+
+/// ParseCXXTryBlock - Parse a C++ try-block.
+///
+///       try-block:
+///         'try' compound-statement handler-seq
+///
+Parser::OwningStmtResult Parser::ParseCXXTryBlock(AttributeList* Attr) {
+  // FIXME: Add attributes?
+  assert(Tok.is(tok::kw_try) && "Expected 'try'");
+
+  SourceLocation TryLoc = ConsumeToken();
+  return ParseCXXTryBlockCommon(TryLoc);
+}
+
+/// ParseCXXTryBlockCommon - Parse the common part of try-block and
+/// function-try-block.
+///
+///       try-block:
+///         'try' compound-statement handler-seq
+///
+///       function-try-block:
+///         'try' ctor-initializer[opt] compound-statement handler-seq
+///
+///       handler-seq:
+///         handler handler-seq[opt]
+///
+Parser::OwningStmtResult Parser::ParseCXXTryBlockCommon(SourceLocation TryLoc) {
+  if (Tok.isNot(tok::l_brace))
+    return StmtError(Diag(Tok, diag::err_expected_lbrace));
+  // FIXME: Possible draft standard bug: attribute-specifier should be allowed?
+  OwningStmtResult TryBlock(ParseCompoundStatement(0));
+  if (TryBlock.isInvalid())
+    return move(TryBlock);
+
+  StmtVector Handlers(Actions);
+  if (getLang().CPlusPlus0x && isCXX0XAttributeSpecifier()) {
+    CXX0XAttributeList Attr = ParseCXX0XAttributes();
+    Diag(Attr.Range.getBegin(), diag::err_attributes_not_allowed)
+      << Attr.Range;
+  }
+  if (Tok.isNot(tok::kw_catch))
+    return StmtError(Diag(Tok, diag::err_expected_catch));
+  while (Tok.is(tok::kw_catch)) {
+    OwningStmtResult Handler(ParseCXXCatchBlock());
+    if (!Handler.isInvalid())
+      Handlers.push_back(Handler.release());
+  }
+  // Don't bother creating the full statement if we don't have any usable
+  // handlers.
+  if (Handlers.empty())
+    return StmtError();
+
+  return Actions.ActOnCXXTryBlock(TryLoc, move(TryBlock), move_arg(Handlers));
+}
+
+/// ParseCXXCatchBlock - Parse a C++ catch block, called handler in the standard
+///
+///       handler:
+///         'catch' '(' exception-declaration ')' compound-statement
+///
+///       exception-declaration:
+///         type-specifier-seq declarator
+///         type-specifier-seq abstract-declarator
+///         type-specifier-seq
+///         '...'
+///
+Parser::OwningStmtResult Parser::ParseCXXCatchBlock() {
+  assert(Tok.is(tok::kw_catch) && "Expected 'catch'");
+
+  SourceLocation CatchLoc = ConsumeToken();
+
+  SourceLocation LParenLoc = Tok.getLocation();
+  if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen))
+    return StmtError();
+
+  // C++ 3.3.2p3:
+  // The name in a catch exception-declaration is local to the handler and
+  // shall not be redeclared in the outermost block of the handler.
+  ParseScope CatchScope(this, Scope::DeclScope | Scope::ControlScope);
+
+  // exception-declaration is equivalent to '...' or a parameter-declaration
+  // without default arguments.
+  DeclPtrTy ExceptionDecl;
+  if (Tok.isNot(tok::ellipsis)) {
+    DeclSpec DS;
+    if (ParseCXXTypeSpecifierSeq(DS))
+      return StmtError();
+    Declarator ExDecl(DS, Declarator::CXXCatchContext);
+    ParseDeclarator(ExDecl);
+    ExceptionDecl = Actions.ActOnExceptionDeclarator(CurScope, ExDecl);
+  } else
+    ConsumeToken();
+
+  if (MatchRHSPunctuation(tok::r_paren, LParenLoc).isInvalid())
+    return StmtError();
+
+  if (Tok.isNot(tok::l_brace))
+    return StmtError(Diag(Tok, diag::err_expected_lbrace));
+
+  // FIXME: Possible draft standard bug: attribute-specifier should be allowed?
+  OwningStmtResult Block(ParseCompoundStatement(0));
+  if (Block.isInvalid())
+    return move(Block);
+
+  return Actions.ActOnCXXCatchBlock(CatchLoc, ExceptionDecl, move(Block));
+}
diff --git a/lib/Parse/ParseTemplate.cpp b/lib/Parse/ParseTemplate.cpp
new file mode 100644
index 0000000..12f26bf
--- /dev/null
+++ b/lib/Parse/ParseTemplate.cpp
@@ -0,0 +1,1013 @@
+//===--- ParseTemplate.cpp - Template Parsing -----------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+//  This file implements parsing of C++ templates.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Parse/Parser.h"
+#include "clang/Parse/ParseDiagnostic.h"
+#include "clang/Parse/DeclSpec.h"
+#include "clang/Parse/Scope.h"
+#include "clang/Parse/Template.h"
+#include "RAIIObjectsForParser.h"
+using namespace clang;
+
+/// \brief Parse a template declaration, explicit instantiation, or
+/// explicit specialization.
+Parser::DeclPtrTy
+Parser::ParseDeclarationStartingWithTemplate(unsigned Context,
+                                             SourceLocation &DeclEnd,
+                                             AccessSpecifier AS) {
+  if (Tok.is(tok::kw_template) && NextToken().isNot(tok::less))
+    return ParseExplicitInstantiation(SourceLocation(), ConsumeToken(),
+                                      DeclEnd);
+
+  return ParseTemplateDeclarationOrSpecialization(Context, DeclEnd, AS);
+}
+
+/// \brief RAII class that manages the template parameter depth.
+namespace {
+  class TemplateParameterDepthCounter {
+    unsigned &Depth;
+    unsigned AddedLevels;
+
+  public:
+    explicit TemplateParameterDepthCounter(unsigned &Depth)
+      : Depth(Depth), AddedLevels(0) { }
+
+    ~TemplateParameterDepthCounter() {
+      Depth -= AddedLevels;
+    }
+
+    void operator++() {
+      ++Depth;
+      ++AddedLevels;
+    }
+
+    operator unsigned() const { return Depth; }
+  };
+}
+
+/// \brief Parse a template declaration or an explicit specialization.
+///
+/// Template declarations include one or more template parameter lists
+/// and either the function or class template declaration. Explicit
+/// specializations contain one or more 'template < >' prefixes
+/// followed by a (possibly templated) declaration. Since the
+/// syntactic form of both features is nearly identical, we parse all
+/// of the template headers together and let semantic analysis sort
+/// the declarations from the explicit specializations.
+///
+///       template-declaration: [C++ temp]
+///         'export'[opt] 'template' '<' template-parameter-list '>' declaration
+///
+///       explicit-specialization: [ C++ temp.expl.spec]
+///         'template' '<' '>' declaration
+Parser::DeclPtrTy
+Parser::ParseTemplateDeclarationOrSpecialization(unsigned Context,
+                                                 SourceLocation &DeclEnd,
+                                                 AccessSpecifier AS) {
+  assert((Tok.is(tok::kw_export) || Tok.is(tok::kw_template)) &&
+         "Token does not start a template declaration.");
+
+  // Enter template-parameter scope.
+  ParseScope TemplateParmScope(this, Scope::TemplateParamScope);
+
+  // Parse multiple levels of template headers within this template
+  // parameter scope, e.g.,
+  //
+  //   template<typename T>
+  //     template<typename U>
+  //       class A<T>::B { ... };
+  //
+  // We parse multiple levels non-recursively so that we can build a
+  // single data structure containing all of the template parameter
+  // lists to easily differentiate between the case above and:
+  //
+  //   template<typename T>
+  //   class A {
+  //     template<typename U> class B;
+  //   };
+  //
+  // In the first case, the action for declaring A<T>::B receives
+  // both template parameter lists. In the second case, the action for
+  // defining A<T>::B receives just the inner template parameter list
+  // (and retrieves the outer template parameter list from its
+  // context).
+  bool isSpecialization = true;
+  bool LastParamListWasEmpty = false;
+  TemplateParameterLists ParamLists;
+  TemplateParameterDepthCounter Depth(TemplateParameterDepth);
+  do {
+    // Consume the 'export', if any.
+    SourceLocation ExportLoc;
+    if (Tok.is(tok::kw_export)) {
+      ExportLoc = ConsumeToken();
+    }
+
+    // Consume the 'template', which should be here.
+    SourceLocation TemplateLoc;
+    if (Tok.is(tok::kw_template)) {
+      TemplateLoc = ConsumeToken();
+    } else {
+      Diag(Tok.getLocation(), diag::err_expected_template);
+      return DeclPtrTy();
+    }
+
+    // Parse the '<' template-parameter-list '>'
+    SourceLocation LAngleLoc, RAngleLoc;
+    TemplateParameterList TemplateParams;
+    if (ParseTemplateParameters(Depth, TemplateParams, LAngleLoc,
+                                RAngleLoc)) {
+      // Skip until the semi-colon or a }.
+      SkipUntil(tok::r_brace, true, true);
+      if (Tok.is(tok::semi))
+        ConsumeToken();
+      return DeclPtrTy();
+    }
+
+    ParamLists.push_back(
+      Actions.ActOnTemplateParameterList(Depth, ExportLoc,
+                                         TemplateLoc, LAngleLoc,
+                                         TemplateParams.data(),
+                                         TemplateParams.size(), RAngleLoc));
+
+    if (!TemplateParams.empty()) {
+      isSpecialization = false;
+      ++Depth;
+    } else {
+      LastParamListWasEmpty = true;
+    }
+  } while (Tok.is(tok::kw_export) || Tok.is(tok::kw_template));
+
+  // Parse the actual template declaration.
+  return ParseSingleDeclarationAfterTemplate(Context,
+                                             ParsedTemplateInfo(&ParamLists,
+                                                             isSpecialization,
+                                                         LastParamListWasEmpty),
+                                             DeclEnd, AS);
+}
+
+/// \brief Parse a single declaration that declares a template,
+/// template specialization, or explicit instantiation of a template.
+///
+/// \param TemplateParams if non-NULL, the template parameter lists
+/// that preceded this declaration. In this case, the declaration is a
+/// template declaration, out-of-line definition of a template, or an
+/// explicit template specialization. When NULL, the declaration is an
+/// explicit template instantiation.
+///
+/// \param TemplateLoc when TemplateParams is NULL, the location of
+/// the 'template' keyword that indicates that we have an explicit
+/// template instantiation.
+///
+/// \param DeclEnd will receive the source location of the last token
+/// within this declaration.
+///
+/// \param AS the access specifier associated with this
+/// declaration. Will be AS_none for namespace-scope declarations.
+///
+/// \returns the new declaration.
+Parser::DeclPtrTy
+Parser::ParseSingleDeclarationAfterTemplate(
+                                       unsigned Context,
+                                       const ParsedTemplateInfo &TemplateInfo,
+                                       SourceLocation &DeclEnd,
+                                       AccessSpecifier AS) {
+  assert(TemplateInfo.Kind != ParsedTemplateInfo::NonTemplate &&
+         "Template information required");
+
+  if (Context == Declarator::MemberContext) {
+    // We are parsing a member template.
+    ParseCXXClassMemberDeclaration(AS, TemplateInfo);
+    return DeclPtrTy::make((void*)0);
+  }
+
+  // Parse the declaration specifiers.
+  ParsingDeclSpec DS(*this);
+
+  if (getLang().CPlusPlus0x && isCXX0XAttributeSpecifier())
+    DS.AddAttributes(ParseCXX0XAttributes().AttrList);
+
+  ParseDeclarationSpecifiers(DS, TemplateInfo, AS,
+                             getDeclSpecContextFromDeclaratorContext(Context));
+
+  if (Tok.is(tok::semi)) {
+    DeclEnd = ConsumeToken();
+    DeclPtrTy Decl = Actions.ParsedFreeStandingDeclSpec(CurScope, DS);
+    DS.complete(Decl);
+    return Decl;
+  }
+
+  // Parse the declarator.
+  ParsingDeclarator DeclaratorInfo(*this, DS, (Declarator::TheContext)Context);
+  ParseDeclarator(DeclaratorInfo);
+  // Error parsing the declarator?
+  if (!DeclaratorInfo.hasName()) {
+    // If so, skip until the semi-colon or a }.
+    SkipUntil(tok::r_brace, true, true);
+    if (Tok.is(tok::semi))
+      ConsumeToken();
+    return DeclPtrTy();
+  }
+
+  // If we have a declaration or declarator list, handle it.
+  if (isDeclarationAfterDeclarator()) {
+    // Parse this declaration.
+    DeclPtrTy ThisDecl = ParseDeclarationAfterDeclarator(DeclaratorInfo,
+                                                         TemplateInfo);
+
+    if (Tok.is(tok::comma)) {
+      Diag(Tok, diag::err_multiple_template_declarators)
+        << (int)TemplateInfo.Kind;
+      SkipUntil(tok::semi, true, false);
+      return ThisDecl;
+    }
+
+    // Eat the semi colon after the declaration.
+    ExpectAndConsume(tok::semi, diag::err_expected_semi_declaration);
+    DS.complete(ThisDecl);
+    return ThisDecl;
+  }
+
+  if (DeclaratorInfo.isFunctionDeclarator() &&
+      isStartOfFunctionDefinition()) {
+    if (DS.getStorageClassSpec() == DeclSpec::SCS_typedef) {
+      Diag(Tok, diag::err_function_declared_typedef);
+
+      if (Tok.is(tok::l_brace)) {
+        // This recovery skips the entire function body. It would be nice
+        // to simply call ParseFunctionDefinition() below, however Sema
+        // assumes the declarator represents a function, not a typedef.
+        ConsumeBrace();
+        SkipUntil(tok::r_brace, true);
+      } else {
+        SkipUntil(tok::semi);
+      }
+      return DeclPtrTy();
+    }
+    return ParseFunctionDefinition(DeclaratorInfo, TemplateInfo);
+  }
+
+  if (DeclaratorInfo.isFunctionDeclarator())
+    Diag(Tok, diag::err_expected_fn_body);
+  else
+    Diag(Tok, diag::err_invalid_token_after_toplevel_declarator);
+  SkipUntil(tok::semi);
+  return DeclPtrTy();
+}
+
+/// ParseTemplateParameters - Parses a template-parameter-list enclosed in
+/// angle brackets. Depth is the depth of this template-parameter-list, which
+/// is the number of template headers directly enclosing this template header.
+/// TemplateParams is the current list of template parameters we're building.
+/// The template parameter we parse will be added to this list. LAngleLoc and
+/// RAngleLoc will receive the positions of the '<' and '>', respectively,
+/// that enclose this template parameter list.
+///
+/// \returns true if an error occurred, false otherwise.
+bool Parser::ParseTemplateParameters(unsigned Depth,
+                                     TemplateParameterList &TemplateParams,
+                                     SourceLocation &LAngleLoc,
+                                     SourceLocation &RAngleLoc) {
+  // Get the template parameter list.
+  if (!Tok.is(tok::less)) {
+    Diag(Tok.getLocation(), diag::err_expected_less_after) << "template";
+    return true;
+  }
+  LAngleLoc = ConsumeToken();
+
+  // Try to parse the template parameter list.
+  if (Tok.is(tok::greater))
+    RAngleLoc = ConsumeToken();
+  else if (ParseTemplateParameterList(Depth, TemplateParams)) {
+    if (!Tok.is(tok::greater)) {
+      Diag(Tok.getLocation(), diag::err_expected_greater);
+      return true;
+    }
+    RAngleLoc = ConsumeToken();
+  }
+  return false;
+}
+
+/// ParseTemplateParameterList - Parse a template parameter list. If
+/// the parsing fails badly (i.e., closing bracket was left out), this
+/// will try to put the token stream in a reasonable position (closing
+/// a statement, etc.) and return false.
+///
+///       template-parameter-list:    [C++ temp]
+///         template-parameter
+///         template-parameter-list ',' template-parameter
+bool
+Parser::ParseTemplateParameterList(unsigned Depth,
+                                   TemplateParameterList &TemplateParams) {
+  while (1) {
+    if (DeclPtrTy TmpParam
+          = ParseTemplateParameter(Depth, TemplateParams.size())) {
+      TemplateParams.push_back(TmpParam);
+    } else {
+      // If we failed to parse a template parameter, skip until we find
+      // a comma or closing brace.
+      SkipUntil(tok::comma, tok::greater, true, true);
+    }
+
+    // Did we find a comma or the end of the template parmeter list?
+    if (Tok.is(tok::comma)) {
+      ConsumeToken();
+    } else if (Tok.is(tok::greater)) {
+      // Don't consume this... that's done by template parser.
+      break;
+    } else {
+      // Somebody probably forgot to close the template. Skip ahead and
+      // try to get out of the expression. This error is currently
+      // subsumed by whatever goes on in ParseTemplateParameter.
+      // TODO: This could match >>, and it would be nice to avoid those
+      // silly errors with template <vec<T>>.
+      // Diag(Tok.getLocation(), diag::err_expected_comma_greater);
+      SkipUntil(tok::greater, true, true);
+      return false;
+    }
+  }
+  return true;
+}
+
+/// \brief Determine whether the parser is at the start of a template
+/// type parameter.
+bool Parser::isStartOfTemplateTypeParameter() {
+  if (Tok.is(tok::kw_class))
+    return true;
+
+  if (Tok.isNot(tok::kw_typename))
+    return false;
+
+  // C++ [temp.param]p2:
+  //   There is no semantic difference between class and typename in a
+  //   template-parameter. typename followed by an unqualified-id
+  //   names a template type parameter. typename followed by a
+  //   qualified-id denotes the type in a non-type
+  //   parameter-declaration.
+  Token Next = NextToken();
+
+  // If we have an identifier, skip over it.
+  if (Next.getKind() == tok::identifier)
+    Next = GetLookAheadToken(2);
+
+  switch (Next.getKind()) {
+  case tok::equal:
+  case tok::comma:
+  case tok::greater:
+  case tok::greatergreater:
+  case tok::ellipsis:
+    return true;
+
+  default:
+    return false;
+  }
+}
+
+/// ParseTemplateParameter - Parse a template-parameter (C++ [temp.param]).
+///
+///       template-parameter: [C++ temp.param]
+///         type-parameter
+///         parameter-declaration
+///
+///       type-parameter: (see below)
+///         'class' ...[opt][C++0x] identifier[opt]
+///         'class' identifier[opt] '=' type-id
+///         'typename' ...[opt][C++0x] identifier[opt]
+///         'typename' identifier[opt] '=' type-id
+///         'template' ...[opt][C++0x] '<' template-parameter-list '>' 'class' identifier[opt]
+///         'template' '<' template-parameter-list '>' 'class' identifier[opt] = id-expression
+Parser::DeclPtrTy
+Parser::ParseTemplateParameter(unsigned Depth, unsigned Position) {
+  if (isStartOfTemplateTypeParameter())
+    return ParseTypeParameter(Depth, Position);
+
+  if (Tok.is(tok::kw_template))
+    return ParseTemplateTemplateParameter(Depth, Position);
+
+  // If it's none of the above, then it must be a parameter declaration.
+  // NOTE: This will pick up errors in the closure of the template parameter
+  // list (e.g., template < ; Check here to implement >> style closures.
+  return ParseNonTypeTemplateParameter(Depth, Position);
+}
+
+/// ParseTypeParameter - Parse a template type parameter (C++ [temp.param]).
+/// Other kinds of template parameters are parsed in
+/// ParseTemplateTemplateParameter and ParseNonTypeTemplateParameter.
+///
+///       type-parameter:     [C++ temp.param]
+///         'class' ...[opt][C++0x] identifier[opt]
+///         'class' identifier[opt] '=' type-id
+///         'typename' ...[opt][C++0x] identifier[opt]
+///         'typename' identifier[opt] '=' type-id
+Parser::DeclPtrTy Parser::ParseTypeParameter(unsigned Depth, unsigned Position){
+  assert((Tok.is(tok::kw_class) || Tok.is(tok::kw_typename)) &&
+         "A type-parameter starts with 'class' or 'typename'");
+
+  // Consume the 'class' or 'typename' keyword.
+  bool TypenameKeyword = Tok.is(tok::kw_typename);
+  SourceLocation KeyLoc = ConsumeToken();
+
+  // Grab the ellipsis (if given).
+  bool Ellipsis = false;
+  SourceLocation EllipsisLoc;
+  if (Tok.is(tok::ellipsis)) {
+    Ellipsis = true;
+    EllipsisLoc = ConsumeToken();
+
+    if (!getLang().CPlusPlus0x)
+      Diag(EllipsisLoc, diag::err_variadic_templates);
+  }
+
+  // Grab the template parameter name (if given)
+  SourceLocation NameLoc;
+  IdentifierInfo* ParamName = 0;
+  if (Tok.is(tok::identifier)) {
+    ParamName = Tok.getIdentifierInfo();
+    NameLoc = ConsumeToken();
+  } else if (Tok.is(tok::equal) || Tok.is(tok::comma) ||
+            Tok.is(tok::greater)) {
+    // Unnamed template parameter. Don't have to do anything here, just
+    // don't consume this token.
+  } else {
+    Diag(Tok.getLocation(), diag::err_expected_ident);
+    return DeclPtrTy();
+  }
+
+  DeclPtrTy TypeParam = Actions.ActOnTypeParameter(CurScope, TypenameKeyword,
+                                                   Ellipsis, EllipsisLoc,
+                                                   KeyLoc, ParamName, NameLoc,
+                                                   Depth, Position);
+
+  // Grab a default type id (if given).
+  if (Tok.is(tok::equal)) {
+    SourceLocation EqualLoc = ConsumeToken();
+    SourceLocation DefaultLoc = Tok.getLocation();
+    TypeResult DefaultType = ParseTypeName();
+    if (!DefaultType.isInvalid())
+      Actions.ActOnTypeParameterDefault(TypeParam, EqualLoc, DefaultLoc,
+                                        DefaultType.get());
+  }
+
+  return TypeParam;
+}
+
+/// ParseTemplateTemplateParameter - Handle the parsing of template
+/// template parameters.
+///
+///       type-parameter:    [C++ temp.param]
+///         'template' '<' template-parameter-list '>' 'class' identifier[opt]
+///         'template' '<' template-parameter-list '>' 'class' identifier[opt] = id-expression
+Parser::DeclPtrTy
+Parser::ParseTemplateTemplateParameter(unsigned Depth, unsigned Position) {
+  assert(Tok.is(tok::kw_template) && "Expected 'template' keyword");
+
+  // Handle the template <...> part.
+  SourceLocation TemplateLoc = ConsumeToken();
+  TemplateParameterList TemplateParams;
+  SourceLocation LAngleLoc, RAngleLoc;
+  {
+    ParseScope TemplateParmScope(this, Scope::TemplateParamScope);
+    if (ParseTemplateParameters(Depth + 1, TemplateParams, LAngleLoc,
+                               RAngleLoc)) {
+      return DeclPtrTy();
+    }
+  }
+
+  // Generate a meaningful error if the user forgot to put class before the
+  // identifier, comma, or greater.
+  if (!Tok.is(tok::kw_class)) {
+    Diag(Tok.getLocation(), diag::err_expected_class_before)
+      << PP.getSpelling(Tok);
+    return DeclPtrTy();
+  }
+  SourceLocation ClassLoc = ConsumeToken();
+
+  // Get the identifier, if given.
+  SourceLocation NameLoc;
+  IdentifierInfo* ParamName = 0;
+  if (Tok.is(tok::identifier)) {
+    ParamName = Tok.getIdentifierInfo();
+    NameLoc = ConsumeToken();
+  } else if (Tok.is(tok::equal) || Tok.is(tok::comma) || Tok.is(tok::greater)) {
+    // Unnamed template parameter. Don't have to do anything here, just
+    // don't consume this token.
+  } else {
+    Diag(Tok.getLocation(), diag::err_expected_ident);
+    return DeclPtrTy();
+  }
+
+  TemplateParamsTy *ParamList =
+    Actions.ActOnTemplateParameterList(Depth, SourceLocation(),
+                                       TemplateLoc, LAngleLoc,
+                                       &TemplateParams[0],
+                                       TemplateParams.size(),
+                                       RAngleLoc);
+
+  Parser::DeclPtrTy Param
+    = Actions.ActOnTemplateTemplateParameter(CurScope, TemplateLoc,
+                                             ParamList, ParamName,
+                                             NameLoc, Depth, Position);
+
+  // Get the a default value, if given.
+  if (Tok.is(tok::equal)) {
+    SourceLocation EqualLoc = ConsumeToken();
+    ParsedTemplateArgument Default = ParseTemplateTemplateArgument();
+    if (Default.isInvalid()) {
+      Diag(Tok.getLocation(), 
+           diag::err_default_template_template_parameter_not_template);
+      static const tok::TokenKind EndToks[] = { 
+        tok::comma, tok::greater, tok::greatergreater
+      };
+      SkipUntil(EndToks, 3, true, true);
+      return Param;
+    } else if (Param)
+      Actions.ActOnTemplateTemplateParameterDefault(Param, EqualLoc, Default);
+  }
+
+  return Param;
+}
+
+/// ParseNonTypeTemplateParameter - Handle the parsing of non-type
+/// template parameters (e.g., in "template<int Size> class array;").
+///
+///       template-parameter:
+///         ...
+///         parameter-declaration
+///
+/// NOTE: It would be ideal to simply call out to ParseParameterDeclaration(),
+/// but that didn't work out to well. Instead, this tries to recrate the basic
+/// parsing of parameter declarations, but tries to constrain it for template
+/// parameters.
+/// FIXME: We need to make a ParseParameterDeclaration that works for
+/// non-type template parameters and normal function parameters.
+Parser::DeclPtrTy
+Parser::ParseNonTypeTemplateParameter(unsigned Depth, unsigned Position) {
+  SourceLocation StartLoc = Tok.getLocation();
+
+  // Parse the declaration-specifiers (i.e., the type).
+  // FIXME: The type should probably be restricted in some way... Not all
+  // declarators (parts of declarators?) are accepted for parameters.
+  DeclSpec DS;
+  ParseDeclarationSpecifiers(DS);
+
+  // Parse this as a typename.
+  Declarator ParamDecl(DS, Declarator::TemplateParamContext);
+  ParseDeclarator(ParamDecl);
+  if (DS.getTypeSpecType() == DeclSpec::TST_unspecified && !DS.getTypeRep()) {
+    // This probably shouldn't happen - and it's more of a Sema thing, but
+    // basically we didn't parse the type name because we couldn't associate
+    // it with an AST node. we should just skip to the comma or greater.
+    // TODO: This is currently a placeholder for some kind of Sema Error.
+    Diag(Tok.getLocation(), diag::err_parse_error);
+    SkipUntil(tok::comma, tok::greater, true, true);
+    return DeclPtrTy();
+  }
+
+  // Create the parameter.
+  DeclPtrTy Param = Actions.ActOnNonTypeTemplateParameter(CurScope, ParamDecl,
+                                                          Depth, Position);
+
+  // If there is a default value, parse it.
+  if (Tok.is(tok::equal)) {
+    SourceLocation EqualLoc = ConsumeToken();
+
+    // C++ [temp.param]p15:
+    //   When parsing a default template-argument for a non-type
+    //   template-parameter, the first non-nested > is taken as the
+    //   end of the template-parameter-list rather than a greater-than
+    //   operator.
+    GreaterThanIsOperatorScope G(GreaterThanIsOperator, false);
+
+    OwningExprResult DefaultArg = ParseAssignmentExpression();
+    if (DefaultArg.isInvalid())
+      SkipUntil(tok::comma, tok::greater, true, true);
+    else if (Param)
+      Actions.ActOnNonTypeTemplateParameterDefault(Param, EqualLoc,
+                                                   move(DefaultArg));
+  }
+
+  return Param;
+}
+
+/// \brief Parses a template-id that after the template name has
+/// already been parsed.
+///
+/// This routine takes care of parsing the enclosed template argument
+/// list ('<' template-parameter-list [opt] '>') and placing the
+/// results into a form that can be transferred to semantic analysis.
+///
+/// \param Template the template declaration produced by isTemplateName
+///
+/// \param TemplateNameLoc the source location of the template name
+///
+/// \param SS if non-NULL, the nested-name-specifier preceding the
+/// template name.
+///
+/// \param ConsumeLastToken if true, then we will consume the last
+/// token that forms the template-id. Otherwise, we will leave the
+/// last token in the stream (e.g., so that it can be replaced with an
+/// annotation token).
+bool
+Parser::ParseTemplateIdAfterTemplateName(TemplateTy Template,
+                                         SourceLocation TemplateNameLoc,
+                                         const CXXScopeSpec *SS,
+                                         bool ConsumeLastToken,
+                                         SourceLocation &LAngleLoc,
+                                         TemplateArgList &TemplateArgs,
+                                         SourceLocation &RAngleLoc) {
+  assert(Tok.is(tok::less) && "Must have already parsed the template-name");
+
+  // Consume the '<'.
+  LAngleLoc = ConsumeToken();
+
+  // Parse the optional template-argument-list.
+  bool Invalid = false;
+  {
+    GreaterThanIsOperatorScope G(GreaterThanIsOperator, false);
+    if (Tok.isNot(tok::greater))
+      Invalid = ParseTemplateArgumentList(TemplateArgs);
+
+    if (Invalid) {
+      // Try to find the closing '>'.
+      SkipUntil(tok::greater, true, !ConsumeLastToken);
+
+      return true;
+    }
+  }
+
+  if (Tok.isNot(tok::greater) && Tok.isNot(tok::greatergreater)) {
+    Diag(Tok.getLocation(), diag::err_expected_greater);
+    return true;
+  }
+
+  // Determine the location of the '>' or '>>'. Only consume this
+  // token if the caller asked us to.
+  RAngleLoc = Tok.getLocation();
+
+  if (Tok.is(tok::greatergreater)) {
+    if (!getLang().CPlusPlus0x) {
+      const char *ReplaceStr = "> >";
+      if (NextToken().is(tok::greater) || NextToken().is(tok::greatergreater))
+        ReplaceStr = "> > ";
+
+      Diag(Tok.getLocation(), diag::err_two_right_angle_brackets_need_space)
+        << CodeModificationHint::CreateReplacement(
+                                 SourceRange(Tok.getLocation()), ReplaceStr);
+    }
+
+    Tok.setKind(tok::greater);
+    if (!ConsumeLastToken) {
+      // Since we're not supposed to consume the '>>' token, we need
+      // to insert a second '>' token after the first.
+      PP.EnterToken(Tok);
+    }
+  } else if (ConsumeLastToken)
+    ConsumeToken();
+
+  return false;
+}
+
+/// \brief Replace the tokens that form a simple-template-id with an
+/// annotation token containing the complete template-id.
+///
+/// The first token in the stream must be the name of a template that
+/// is followed by a '<'. This routine will parse the complete
+/// simple-template-id and replace the tokens with a single annotation
+/// token with one of two different kinds: if the template-id names a
+/// type (and \p AllowTypeAnnotation is true), the annotation token is
+/// a type annotation that includes the optional nested-name-specifier
+/// (\p SS). Otherwise, the annotation token is a template-id
+/// annotation that does not include the optional
+/// nested-name-specifier.
+///
+/// \param Template  the declaration of the template named by the first
+/// token (an identifier), as returned from \c Action::isTemplateName().
+///
+/// \param TemplateNameKind the kind of template that \p Template
+/// refers to, as returned from \c Action::isTemplateName().
+///
+/// \param SS if non-NULL, the nested-name-specifier that precedes
+/// this template name.
+///
+/// \param TemplateKWLoc if valid, specifies that this template-id
+/// annotation was preceded by the 'template' keyword and gives the
+/// location of that keyword. If invalid (the default), then this
+/// template-id was not preceded by a 'template' keyword.
+///
+/// \param AllowTypeAnnotation if true (the default), then a
+/// simple-template-id that refers to a class template, template
+/// template parameter, or other template that produces a type will be
+/// replaced with a type annotation token. Otherwise, the
+/// simple-template-id is always replaced with a template-id
+/// annotation token.
+///
+/// If an unrecoverable parse error occurs and no annotation token can be
+/// formed, this function returns true.
+///
+bool Parser::AnnotateTemplateIdToken(TemplateTy Template, TemplateNameKind TNK,
+                                     const CXXScopeSpec *SS,
+                                     UnqualifiedId &TemplateName,
+                                     SourceLocation TemplateKWLoc,
+                                     bool AllowTypeAnnotation) {
+  assert(getLang().CPlusPlus && "Can only annotate template-ids in C++");
+  assert(Template && Tok.is(tok::less) &&
+         "Parser isn't at the beginning of a template-id");
+
+  // Consume the template-name.
+  SourceLocation TemplateNameLoc = TemplateName.getSourceRange().getBegin();
+
+  // Parse the enclosed template argument list.
+  SourceLocation LAngleLoc, RAngleLoc;
+  TemplateArgList TemplateArgs;
+  bool Invalid = ParseTemplateIdAfterTemplateName(Template, 
+                                                  TemplateNameLoc,
+                                                  SS, false, LAngleLoc,
+                                                  TemplateArgs,
+                                                  RAngleLoc);
+
+  if (Invalid) {
+    // If we failed to parse the template ID but skipped ahead to a >, we're not
+    // going to be able to form a token annotation.  Eat the '>' if present.
+    if (Tok.is(tok::greater))
+      ConsumeToken();
+    return true;
+  }
+
+  ASTTemplateArgsPtr TemplateArgsPtr(Actions, TemplateArgs.data(),
+                                     TemplateArgs.size());
+
+  // Build the annotation token.
+  if (TNK == TNK_Type_template && AllowTypeAnnotation) {
+    Action::TypeResult Type
+      = Actions.ActOnTemplateIdType(Template, TemplateNameLoc,
+                                    LAngleLoc, TemplateArgsPtr,
+                                    RAngleLoc);
+    if (Type.isInvalid()) {
+      // If we failed to parse the template ID but skipped ahead to a >, we're not
+      // going to be able to form a token annotation.  Eat the '>' if present.
+      if (Tok.is(tok::greater))
+        ConsumeToken();
+      return true;
+    }
+
+    Tok.setKind(tok::annot_typename);
+    Tok.setAnnotationValue(Type.get());
+    if (SS && SS->isNotEmpty())
+      Tok.setLocation(SS->getBeginLoc());
+    else if (TemplateKWLoc.isValid())
+      Tok.setLocation(TemplateKWLoc);
+    else
+      Tok.setLocation(TemplateNameLoc);
+  } else {
+    // Build a template-id annotation token that can be processed
+    // later.
+    Tok.setKind(tok::annot_template_id);
+    TemplateIdAnnotation *TemplateId
+      = TemplateIdAnnotation::Allocate(TemplateArgs.size());
+    TemplateId->TemplateNameLoc = TemplateNameLoc;
+    if (TemplateName.getKind() == UnqualifiedId::IK_Identifier) {
+      TemplateId->Name = TemplateName.Identifier;
+      TemplateId->Operator = OO_None;
+    } else {
+      TemplateId->Name = 0;
+      TemplateId->Operator = TemplateName.OperatorFunctionId.Operator;
+    }
+    TemplateId->Template = Template.getAs<void*>();
+    TemplateId->Kind = TNK;
+    TemplateId->LAngleLoc = LAngleLoc;
+    TemplateId->RAngleLoc = RAngleLoc;
+    ParsedTemplateArgument *Args = TemplateId->getTemplateArgs();
+    for (unsigned Arg = 0, ArgEnd = TemplateArgs.size(); Arg != ArgEnd; ++Arg)
+      Args[Arg] = TemplateArgs[Arg];
+    Tok.setAnnotationValue(TemplateId);
+    if (TemplateKWLoc.isValid())
+      Tok.setLocation(TemplateKWLoc);
+    else
+      Tok.setLocation(TemplateNameLoc);
+
+    TemplateArgsPtr.release();
+  }
+
+  // Common fields for the annotation token
+  Tok.setAnnotationEndLoc(RAngleLoc);
+
+  // In case the tokens were cached, have Preprocessor replace them with the
+  // annotation token.
+  PP.AnnotateCachedTokens(Tok);
+  return false;
+}
+
+/// \brief Replaces a template-id annotation token with a type
+/// annotation token.
+///
+/// If there was a failure when forming the type from the template-id,
+/// a type annotation token will still be created, but will have a
+/// NULL type pointer to signify an error.
+void Parser::AnnotateTemplateIdTokenAsType(const CXXScopeSpec *SS) {
+  assert(Tok.is(tok::annot_template_id) && "Requires template-id tokens");
+
+  TemplateIdAnnotation *TemplateId
+    = static_cast<TemplateIdAnnotation *>(Tok.getAnnotationValue());
+  assert((TemplateId->Kind == TNK_Type_template ||
+          TemplateId->Kind == TNK_Dependent_template_name) &&
+         "Only works for type and dependent templates");
+
+  ASTTemplateArgsPtr TemplateArgsPtr(Actions,
+                                     TemplateId->getTemplateArgs(),
+                                     TemplateId->NumArgs);
+
+  Action::TypeResult Type
+    = Actions.ActOnTemplateIdType(TemplateTy::make(TemplateId->Template),
+                                  TemplateId->TemplateNameLoc,
+                                  TemplateId->LAngleLoc,
+                                  TemplateArgsPtr,
+                                  TemplateId->RAngleLoc);
+  // Create the new "type" annotation token.
+  Tok.setKind(tok::annot_typename);
+  Tok.setAnnotationValue(Type.isInvalid()? 0 : Type.get());
+  if (SS && SS->isNotEmpty()) // it was a C++ qualified type name.
+    Tok.setLocation(SS->getBeginLoc());
+  // End location stays the same
+
+  // Replace the template-id annotation token, and possible the scope-specifier
+  // that precedes it, with the typename annotation token.
+  PP.AnnotateCachedTokens(Tok);
+  TemplateId->Destroy();
+}
+
+/// \brief Determine whether the given token can end a template argument.
+static bool isEndOfTemplateArgument(Token Tok) {
+  return Tok.is(tok::comma) || Tok.is(tok::greater) || 
+         Tok.is(tok::greatergreater);
+}
+
+/// \brief Parse a C++ template template argument.
+ParsedTemplateArgument Parser::ParseTemplateTemplateArgument() {
+  if (!Tok.is(tok::identifier) && !Tok.is(tok::coloncolon) &&
+      !Tok.is(tok::annot_cxxscope))
+    return ParsedTemplateArgument();
+
+  // C++0x [temp.arg.template]p1:
+  //   A template-argument for a template template-parameter shall be the name
+  //   of a class template or a template alias, expressed as id-expression.
+  //   
+  // We parse an id-expression that refers to a class template or template
+  // alias. The grammar we parse is:
+  //
+  //   nested-name-specifier[opt] template[opt] identifier
+  //
+  // followed by a token that terminates a template argument, such as ',', 
+  // '>', or (in some cases) '>>'.
+  CXXScopeSpec SS; // nested-name-specifier, if present
+  ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/0, 
+                                 /*EnteringContext=*/false);
+  
+  if (SS.isSet() && Tok.is(tok::kw_template)) {
+    // Parse the optional 'template' keyword following the 
+    // nested-name-specifier.
+    SourceLocation TemplateLoc = ConsumeToken();
+    
+    if (Tok.is(tok::identifier)) {
+      // We appear to have a dependent template name.
+      UnqualifiedId Name;
+      Name.setIdentifier(Tok.getIdentifierInfo(), Tok.getLocation());
+      ConsumeToken(); // the identifier
+      
+      // If the next token signals the end of a template argument,
+      // then we have a dependent template name that could be a template
+      // template argument.
+      if (isEndOfTemplateArgument(Tok)) {
+        TemplateTy Template
+        = Actions.ActOnDependentTemplateName(TemplateLoc, SS, Name, 
+                                             /*ObjectType=*/0,
+                                             /*EnteringContext=*/false);
+        if (Template.get())
+          return ParsedTemplateArgument(SS, Template, Name.StartLocation);
+      }
+    } 
+  } else if (Tok.is(tok::identifier)) {
+    // We may have a (non-dependent) template name.
+    TemplateTy Template;
+    UnqualifiedId Name;
+    Name.setIdentifier(Tok.getIdentifierInfo(), Tok.getLocation());
+    ConsumeToken(); // the identifier
+    
+    if (isEndOfTemplateArgument(Tok)) {
+      TemplateNameKind TNK = Actions.isTemplateName(CurScope, SS, Name, 
+                                                    /*ObjectType=*/0, 
+                                                    /*EnteringContext=*/false, 
+                                                    Template);
+      if (TNK == TNK_Dependent_template_name || TNK == TNK_Type_template) {
+        // We have an id-expression that refers to a class template or
+        // (C++0x) template alias. 
+        return ParsedTemplateArgument(SS, Template, Name.StartLocation);
+      }
+    }
+  }
+  
+  // We don't have a template template argument.  
+  return ParsedTemplateArgument();
+}
+
+/// ParseTemplateArgument - Parse a C++ template argument (C++ [temp.names]).
+///
+///       template-argument: [C++ 14.2]
+///         constant-expression
+///         type-id
+///         id-expression
+ParsedTemplateArgument Parser::ParseTemplateArgument() {
+  // C++ [temp.arg]p2:
+  //   In a template-argument, an ambiguity between a type-id and an
+  //   expression is resolved to a type-id, regardless of the form of
+  //   the corresponding template-parameter.
+  //
+  // Therefore, we initially try to parse a type-id.  
+  if (isCXXTypeId(TypeIdAsTemplateArgument)) {
+    SourceLocation Loc = Tok.getLocation();
+    TypeResult TypeArg = ParseTypeName();
+    if (TypeArg.isInvalid())
+      return ParsedTemplateArgument();
+    
+    return ParsedTemplateArgument(ParsedTemplateArgument::Type, TypeArg.get(), 
+                                  Loc);
+  }
+  
+  // Try to parse a template template argument.
+  {
+    TentativeParsingAction TPA(*this);
+
+    ParsedTemplateArgument TemplateTemplateArgument
+      = ParseTemplateTemplateArgument();
+    if (!TemplateTemplateArgument.isInvalid()) {
+      TPA.Commit();
+      return TemplateTemplateArgument;
+    }
+    
+    // Revert this tentative parse to parse a non-type template argument.
+    TPA.Revert();
+  }
+  
+  // Parse a non-type template argument. 
+  SourceLocation Loc = Tok.getLocation();
+  OwningExprResult ExprArg = ParseConstantExpression();
+  if (ExprArg.isInvalid() || !ExprArg.get())
+    return ParsedTemplateArgument();
+
+  return ParsedTemplateArgument(ParsedTemplateArgument::NonType, 
+                                ExprArg.release(), Loc);
+}
+
+/// ParseTemplateArgumentList - Parse a C++ template-argument-list
+/// (C++ [temp.names]). Returns true if there was an error.
+///
+///       template-argument-list: [C++ 14.2]
+///         template-argument
+///         template-argument-list ',' template-argument
+bool
+Parser::ParseTemplateArgumentList(TemplateArgList &TemplateArgs) {
+  while (true) {
+    ParsedTemplateArgument Arg = ParseTemplateArgument();
+    if (Arg.isInvalid()) {
+      SkipUntil(tok::comma, tok::greater, true, true);
+      return true;
+    }
+
+    // Save this template argument.
+    TemplateArgs.push_back(Arg);
+      
+    // If the next token is a comma, consume it and keep reading
+    // arguments.
+    if (Tok.isNot(tok::comma)) break;
+
+    // Consume the comma.
+    ConsumeToken();
+  }
+
+  return false;
+}
+
+/// \brief Parse a C++ explicit template instantiation
+/// (C++ [temp.explicit]).
+///
+///       explicit-instantiation:
+///         'extern' [opt] 'template' declaration
+///
+/// Note that the 'extern' is a GNU extension and C++0x feature.
+Parser::DeclPtrTy
+Parser::ParseExplicitInstantiation(SourceLocation ExternLoc,
+                                   SourceLocation TemplateLoc,
+                                   SourceLocation &DeclEnd) {
+  return ParseSingleDeclarationAfterTemplate(Declarator::FileContext,
+                                             ParsedTemplateInfo(ExternLoc,
+                                                                TemplateLoc),
+                                             DeclEnd, AS_none);
+}
diff --git a/lib/Parse/ParseTentative.cpp b/lib/Parse/ParseTentative.cpp
new file mode 100644
index 0000000..6251a2f
--- /dev/null
+++ b/lib/Parse/ParseTentative.cpp
@@ -0,0 +1,1035 @@
+//===--- ParseTentative.cpp - Ambiguity Resolution Parsing ----------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+//  This file implements the tentative parsing portions of the Parser
+//  interfaces, for ambiguity resolution.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Parse/Parser.h"
+#include "clang/Parse/ParseDiagnostic.h"
+using namespace clang;
+
+/// isCXXDeclarationStatement - C++-specialized function that disambiguates
+/// between a declaration or an expression statement, when parsing function
+/// bodies. Returns true for declaration, false for expression.
+///
+///         declaration-statement:
+///           block-declaration
+///
+///         block-declaration:
+///           simple-declaration
+///           asm-definition
+///           namespace-alias-definition
+///           using-declaration
+///           using-directive
+/// [C++0x]   static_assert-declaration
+///
+///         asm-definition:
+///           'asm' '(' string-literal ')' ';'
+///
+///         namespace-alias-definition:
+///           'namespace' identifier = qualified-namespace-specifier ';'
+///
+///         using-declaration:
+///           'using' typename[opt] '::'[opt] nested-name-specifier
+///                 unqualified-id ';'
+///           'using' '::' unqualified-id ;
+///
+///         using-directive:
+///           'using' 'namespace' '::'[opt] nested-name-specifier[opt]
+///                 namespace-name ';'
+///
+bool Parser::isCXXDeclarationStatement() {
+  switch (Tok.getKind()) {
+    // asm-definition
+  case tok::kw_asm:
+    // namespace-alias-definition
+  case tok::kw_namespace:
+    // using-declaration
+    // using-directive
+  case tok::kw_using:
+    // static_assert-declaration
+  case tok::kw_static_assert:
+    return true;
+    // simple-declaration
+  default:
+    return isCXXSimpleDeclaration();
+  }
+}
+
+/// isCXXSimpleDeclaration - C++-specialized function that disambiguates
+/// between a simple-declaration or an expression-statement.
+/// If during the disambiguation process a parsing error is encountered,
+/// the function returns true to let the declaration parsing code handle it.
+/// Returns false if the statement is disambiguated as expression.
+///
+/// simple-declaration:
+///   decl-specifier-seq init-declarator-list[opt] ';'
+///
+bool Parser::isCXXSimpleDeclaration() {
+  // C++ 6.8p1:
+  // There is an ambiguity in the grammar involving expression-statements and
+  // declarations: An expression-statement with a function-style explicit type
+  // conversion (5.2.3) as its leftmost subexpression can be indistinguishable
+  // from a declaration where the first declarator starts with a '('. In those
+  // cases the statement is a declaration. [Note: To disambiguate, the whole
+  // statement might have to be examined to determine if it is an
+  // expression-statement or a declaration].
+
+  // C++ 6.8p3:
+  // The disambiguation is purely syntactic; that is, the meaning of the names
+  // occurring in such a statement, beyond whether they are type-names or not,
+  // is not generally used in or changed by the disambiguation. Class
+  // templates are instantiated as necessary to determine if a qualified name
+  // is a type-name. Disambiguation precedes parsing, and a statement
+  // disambiguated as a declaration may be an ill-formed declaration.
+
+  // We don't have to parse all of the decl-specifier-seq part. There's only
+  // an ambiguity if the first decl-specifier is
+  // simple-type-specifier/typename-specifier followed by a '(', which may
+  // indicate a function-style cast expression.
+  // isCXXDeclarationSpecifier will return TPResult::Ambiguous() only in such
+  // a case.
+
+  TPResult TPR = isCXXDeclarationSpecifier();
+  if (TPR != TPResult::Ambiguous())
+    return TPR != TPResult::False(); // Returns true for TPResult::True() or
+                                     // TPResult::Error().
+
+  // FIXME: Add statistics about the number of ambiguous statements encountered
+  // and how they were resolved (number of declarations+number of expressions).
+
+  // Ok, we have a simple-type-specifier/typename-specifier followed by a '('.
+  // We need tentative parsing...
+
+  TentativeParsingAction PA(*this);
+
+  TPR = TryParseSimpleDeclaration();
+  SourceLocation TentativeParseLoc = Tok.getLocation();
+
+  PA.Revert();
+
+  // In case of an error, let the declaration parsing code handle it.
+  if (TPR == TPResult::Error())
+    return true;
+
+  // Declarations take precedence over expressions.
+  if (TPR == TPResult::Ambiguous())
+    TPR = TPResult::True();
+
+  assert(TPR == TPResult::True() || TPR == TPResult::False());
+  return TPR == TPResult::True();
+}
+
+/// simple-declaration:
+///   decl-specifier-seq init-declarator-list[opt] ';'
+///
+Parser::TPResult Parser::TryParseSimpleDeclaration() {
+  // We know that we have a simple-type-specifier/typename-specifier followed
+  // by a '('.
+  assert(isCXXDeclarationSpecifier() == TPResult::Ambiguous());
+
+  if (Tok.is(tok::kw_typeof))
+    TryParseTypeofSpecifier();
+  else
+    ConsumeToken();
+
+  assert(Tok.is(tok::l_paren) && "Expected '('");
+
+  TPResult TPR = TryParseInitDeclaratorList();
+  if (TPR != TPResult::Ambiguous())
+    return TPR;
+
+  if (Tok.isNot(tok::semi))
+    return TPResult::False();
+
+  return TPResult::Ambiguous();
+}
+
+///       init-declarator-list:
+///         init-declarator
+///         init-declarator-list ',' init-declarator
+///
+///       init-declarator:
+///         declarator initializer[opt]
+/// [GNU]   declarator simple-asm-expr[opt] attributes[opt] initializer[opt]
+///
+/// initializer:
+///   '=' initializer-clause
+///   '(' expression-list ')'
+///
+/// initializer-clause:
+///   assignment-expression
+///   '{' initializer-list ','[opt] '}'
+///   '{' '}'
+///
+Parser::TPResult Parser::TryParseInitDeclaratorList() {
+  // GCC only examines the first declarator for disambiguation:
+  // i.e:
+  // int(x), ++x; // GCC regards it as ill-formed declaration.
+  //
+  // Comeau and MSVC will regard the above statement as correct expression.
+  // Clang examines all of the declarators and also regards the above statement
+  // as correct expression.
+
+  while (1) {
+    // declarator
+    TPResult TPR = TryParseDeclarator(false/*mayBeAbstract*/);
+    if (TPR != TPResult::Ambiguous())
+      return TPR;
+
+    // [GNU] simple-asm-expr[opt] attributes[opt]
+    if (Tok.is(tok::kw_asm) || Tok.is(tok::kw___attribute))
+      return TPResult::True();
+
+    // initializer[opt]
+    if (Tok.is(tok::l_paren)) {
+      // Parse through the parens.
+      ConsumeParen();
+      if (!SkipUntil(tok::r_paren))
+        return TPResult::Error();
+    } else if (Tok.is(tok::equal)) {
+      // MSVC won't examine the rest of declarators if '=' is encountered, it
+      // will conclude that it is a declaration.
+      // Comeau and Clang will examine the rest of declarators.
+      // Note that "int(x) = {0}, ++x;" will be interpreted as ill-formed
+      // expression.
+      //
+      // Parse through the initializer-clause.
+      SkipUntil(tok::comma, true/*StopAtSemi*/, true/*DontConsume*/);
+    }
+
+    if (Tok.isNot(tok::comma))
+      break;
+    ConsumeToken(); // the comma.
+  }
+
+  return TPResult::Ambiguous();
+}
+
+/// isCXXConditionDeclaration - Disambiguates between a declaration or an
+/// expression for a condition of a if/switch/while/for statement.
+/// If during the disambiguation process a parsing error is encountered,
+/// the function returns true to let the declaration parsing code handle it.
+///
+///       condition:
+///         expression
+///         type-specifier-seq declarator '=' assignment-expression
+/// [GNU]   type-specifier-seq declarator simple-asm-expr[opt] attributes[opt]
+///             '=' assignment-expression
+///
+bool Parser::isCXXConditionDeclaration() {
+  TPResult TPR = isCXXDeclarationSpecifier();
+  if (TPR != TPResult::Ambiguous())
+    return TPR != TPResult::False(); // Returns true for TPResult::True() or
+                                     // TPResult::Error().
+
+  // FIXME: Add statistics about the number of ambiguous statements encountered
+  // and how they were resolved (number of declarations+number of expressions).
+
+  // Ok, we have a simple-type-specifier/typename-specifier followed by a '('.
+  // We need tentative parsing...
+
+  TentativeParsingAction PA(*this);
+
+  // type-specifier-seq
+  if (Tok.is(tok::kw_typeof))
+    TryParseTypeofSpecifier();
+  else
+    ConsumeToken();
+  assert(Tok.is(tok::l_paren) && "Expected '('");
+
+  // declarator
+  TPR = TryParseDeclarator(false/*mayBeAbstract*/);
+
+  // In case of an error, let the declaration parsing code handle it.
+  if (TPR == TPResult::Error())
+    TPR = TPResult::True();
+
+  if (TPR == TPResult::Ambiguous()) {
+    // '='
+    // [GNU] simple-asm-expr[opt] attributes[opt]
+    if (Tok.is(tok::equal)  ||
+        Tok.is(tok::kw_asm) || Tok.is(tok::kw___attribute))
+      TPR = TPResult::True();
+    else
+      TPR = TPResult::False();
+  }
+
+  PA.Revert();
+
+  assert(TPR == TPResult::True() || TPR == TPResult::False());
+  return TPR == TPResult::True();
+}
+
+  /// \brief Determine whether the next set of tokens contains a type-id.
+  ///
+  /// The context parameter states what context we're parsing right
+  /// now, which affects how this routine copes with the token
+  /// following the type-id. If the context is TypeIdInParens, we have
+  /// already parsed the '(' and we will cease lookahead when we hit
+  /// the corresponding ')'. If the context is
+  /// TypeIdAsTemplateArgument, we've already parsed the '<' or ','
+  /// before this template argument, and will cease lookahead when we
+  /// hit a '>', '>>' (in C++0x), or ','. Returns true for a type-id
+  /// and false for an expression.  If during the disambiguation
+  /// process a parsing error is encountered, the function returns
+  /// true to let the declaration parsing code handle it.
+  ///
+  /// type-id:
+  ///   type-specifier-seq abstract-declarator[opt]
+  ///
+bool Parser::isCXXTypeId(TentativeCXXTypeIdContext Context, bool &isAmbiguous) {
+
+  isAmbiguous = false;
+
+  // C++ 8.2p2:
+  // The ambiguity arising from the similarity between a function-style cast and
+  // a type-id can occur in different contexts. The ambiguity appears as a
+  // choice between a function-style cast expression and a declaration of a
+  // type. The resolution is that any construct that could possibly be a type-id
+  // in its syntactic context shall be considered a type-id.
+
+  TPResult TPR = isCXXDeclarationSpecifier();
+  if (TPR != TPResult::Ambiguous())
+    return TPR != TPResult::False(); // Returns true for TPResult::True() or
+                                     // TPResult::Error().
+
+  // FIXME: Add statistics about the number of ambiguous statements encountered
+  // and how they were resolved (number of declarations+number of expressions).
+
+  // Ok, we have a simple-type-specifier/typename-specifier followed by a '('.
+  // We need tentative parsing...
+
+  TentativeParsingAction PA(*this);
+
+  // type-specifier-seq
+  if (Tok.is(tok::kw_typeof))
+    TryParseTypeofSpecifier();
+  else
+    ConsumeToken();
+  assert(Tok.is(tok::l_paren) && "Expected '('");
+
+  // declarator
+  TPR = TryParseDeclarator(true/*mayBeAbstract*/, false/*mayHaveIdentifier*/);
+
+  // In case of an error, let the declaration parsing code handle it.
+  if (TPR == TPResult::Error())
+    TPR = TPResult::True();
+
+  if (TPR == TPResult::Ambiguous()) {
+    // We are supposed to be inside parens, so if after the abstract declarator
+    // we encounter a ')' this is a type-id, otherwise it's an expression.
+    if (Context == TypeIdInParens && Tok.is(tok::r_paren)) {
+      TPR = TPResult::True();
+      isAmbiguous = true;
+
+    // We are supposed to be inside a template argument, so if after
+    // the abstract declarator we encounter a '>', '>>' (in C++0x), or
+    // ',', this is a type-id. Otherwise, it's an expression.
+    } else if (Context == TypeIdAsTemplateArgument &&
+               (Tok.is(tok::greater) || Tok.is(tok::comma) ||
+                (getLang().CPlusPlus0x && Tok.is(tok::greatergreater)))) {
+      TPR = TPResult::True();
+      isAmbiguous = true;
+
+    } else
+      TPR = TPResult::False();
+  }
+
+  PA.Revert();
+
+  assert(TPR == TPResult::True() || TPR == TPResult::False());
+  return TPR == TPResult::True();
+}
+
+/// isCXX0XAttributeSpecifier - returns true if this is a C++0x
+/// attribute-specifier. By default, unless in Obj-C++, only a cursory check is
+/// performed that will simply return true if a [[ is seen. Currently C++ has no
+/// syntactical ambiguities from this check, but it may inhibit error recovery.
+/// If CheckClosing is true, a check is made for closing ]] brackets.
+///
+/// If given, After is set to the token after the attribute-specifier so that
+/// appropriate parsing decisions can be made; it is left untouched if false is
+/// returned.
+///
+/// FIXME: If an error is in the closing ]] brackets, the program assumes
+/// the absence of an attribute-specifier, which can cause very yucky errors
+/// to occur.
+///
+/// [C++0x] attribute-specifier:
+///         '[' '[' attribute-list ']' ']'
+///
+/// [C++0x] attribute-list:
+///         attribute[opt]
+///         attribute-list ',' attribute[opt]
+///
+/// [C++0x] attribute:
+///         attribute-token attribute-argument-clause[opt]
+///
+/// [C++0x] attribute-token:
+///         identifier
+///         attribute-scoped-token
+///
+/// [C++0x] attribute-scoped-token:
+///         attribute-namespace '::' identifier
+///
+/// [C++0x] attribute-namespace:
+///         identifier
+///
+/// [C++0x] attribute-argument-clause:
+///         '(' balanced-token-seq ')'
+///
+/// [C++0x] balanced-token-seq:
+///         balanced-token
+///         balanced-token-seq balanced-token
+///
+/// [C++0x] balanced-token:
+///         '(' balanced-token-seq ')'
+///         '[' balanced-token-seq ']'
+///         '{' balanced-token-seq '}'
+///         any token but '(', ')', '[', ']', '{', or '}'
+bool Parser::isCXX0XAttributeSpecifier (bool CheckClosing,
+                                        tok::TokenKind *After) {
+  if (Tok.isNot(tok::l_square) || NextToken().isNot(tok::l_square))
+    return false;
+  
+  // No tentative parsing if we don't need to look for ]]
+  if (!CheckClosing && !getLang().ObjC1)
+    return true;
+  
+  struct TentativeReverter {
+    TentativeParsingAction PA;
+
+    TentativeReverter (Parser& P)
+      : PA(P)
+    {}
+    ~TentativeReverter () {
+      PA.Revert();
+    }
+  } R(*this);
+
+  // Opening brackets were checked for above.
+  ConsumeBracket();
+  ConsumeBracket();
+
+  // SkipUntil will handle balanced tokens, which are guaranteed in attributes.
+  SkipUntil(tok::r_square, false);
+
+  if (Tok.isNot(tok::r_square))
+    return false;
+  ConsumeBracket();
+
+  if (After)
+    *After = Tok.getKind();
+
+  return true;
+}
+
+///         declarator:
+///           direct-declarator
+///           ptr-operator declarator
+///
+///         direct-declarator:
+///           declarator-id
+///           direct-declarator '(' parameter-declaration-clause ')'
+///                 cv-qualifier-seq[opt] exception-specification[opt]
+///           direct-declarator '[' constant-expression[opt] ']'
+///           '(' declarator ')'
+/// [GNU]     '(' attributes declarator ')'
+///
+///         abstract-declarator:
+///           ptr-operator abstract-declarator[opt]
+///           direct-abstract-declarator
+///
+///         direct-abstract-declarator:
+///           direct-abstract-declarator[opt]
+///           '(' parameter-declaration-clause ')' cv-qualifier-seq[opt]
+///                 exception-specification[opt]
+///           direct-abstract-declarator[opt] '[' constant-expression[opt] ']'
+///           '(' abstract-declarator ')'
+///
+///         ptr-operator:
+///           '*' cv-qualifier-seq[opt]
+///           '&'
+/// [C++0x]   '&&'                                                        [TODO]
+///           '::'[opt] nested-name-specifier '*' cv-qualifier-seq[opt]
+///
+///         cv-qualifier-seq:
+///           cv-qualifier cv-qualifier-seq[opt]
+///
+///         cv-qualifier:
+///           'const'
+///           'volatile'
+///
+///         declarator-id:
+///           id-expression
+///
+///         id-expression:
+///           unqualified-id
+///           qualified-id                                                [TODO]
+///
+///         unqualified-id:
+///           identifier
+///           operator-function-id                                        [TODO]
+///           conversion-function-id                                      [TODO]
+///           '~' class-name                                              [TODO]
+///           template-id                                                 [TODO]
+///
+Parser::TPResult Parser::TryParseDeclarator(bool mayBeAbstract,
+                                            bool mayHaveIdentifier) {
+  // declarator:
+  //   direct-declarator
+  //   ptr-operator declarator
+
+  while (1) {
+    if (Tok.is(tok::coloncolon) || Tok.is(tok::identifier))
+      TryAnnotateCXXScopeToken(true);
+
+    if (Tok.is(tok::star) || Tok.is(tok::amp) || Tok.is(tok::caret) ||
+        (Tok.is(tok::annot_cxxscope) && NextToken().is(tok::star))) {
+      // ptr-operator
+      ConsumeToken();
+      while (Tok.is(tok::kw_const)    ||
+             Tok.is(tok::kw_volatile) ||
+             Tok.is(tok::kw_restrict))
+        ConsumeToken();
+    } else {
+      break;
+    }
+  }
+
+  // direct-declarator:
+  // direct-abstract-declarator:
+
+  if ((Tok.is(tok::identifier) ||
+       (Tok.is(tok::annot_cxxscope) && NextToken().is(tok::identifier))) &&
+      mayHaveIdentifier) {
+    // declarator-id
+    if (Tok.is(tok::annot_cxxscope))
+      ConsumeToken();
+    ConsumeToken();
+  } else if (Tok.is(tok::l_paren)) {
+    ConsumeParen();
+    if (mayBeAbstract &&
+        (Tok.is(tok::r_paren) ||       // 'int()' is a function.
+         Tok.is(tok::ellipsis) ||      // 'int(...)' is a function.
+         isDeclarationSpecifier())) {   // 'int(int)' is a function.
+      // '(' parameter-declaration-clause ')' cv-qualifier-seq[opt]
+      //        exception-specification[opt]
+      TPResult TPR = TryParseFunctionDeclarator();
+      if (TPR != TPResult::Ambiguous())
+        return TPR;
+    } else {
+      // '(' declarator ')'
+      // '(' attributes declarator ')'
+      // '(' abstract-declarator ')'
+      if (Tok.is(tok::kw___attribute))
+        return TPResult::True(); // attributes indicate declaration
+      TPResult TPR = TryParseDeclarator(mayBeAbstract, mayHaveIdentifier);
+      if (TPR != TPResult::Ambiguous())
+        return TPR;
+      if (Tok.isNot(tok::r_paren))
+        return TPResult::False();
+      ConsumeParen();
+    }
+  } else if (!mayBeAbstract) {
+    return TPResult::False();
+  }
+
+  while (1) {
+    TPResult TPR(TPResult::Ambiguous());
+
+    if (Tok.is(tok::l_paren)) {
+      // Check whether we have a function declarator or a possible ctor-style
+      // initializer that follows the declarator. Note that ctor-style
+      // initializers are not possible in contexts where abstract declarators
+      // are allowed.
+      if (!mayBeAbstract && !isCXXFunctionDeclarator(false/*warnIfAmbiguous*/))
+        break;
+
+      // direct-declarator '(' parameter-declaration-clause ')'
+      //        cv-qualifier-seq[opt] exception-specification[opt]
+      ConsumeParen();
+      TPR = TryParseFunctionDeclarator();
+    } else if (Tok.is(tok::l_square)) {
+      // direct-declarator '[' constant-expression[opt] ']'
+      // direct-abstract-declarator[opt] '[' constant-expression[opt] ']'
+      TPR = TryParseBracketDeclarator();
+    } else {
+      break;
+    }
+
+    if (TPR != TPResult::Ambiguous())
+      return TPR;
+  }
+
+  return TPResult::Ambiguous();
+}
+
+/// isCXXDeclarationSpecifier - Returns TPResult::True() if it is a declaration
+/// specifier, TPResult::False() if it is not, TPResult::Ambiguous() if it could
+/// be either a decl-specifier or a function-style cast, and TPResult::Error()
+/// if a parsing error was found and reported.
+///
+///         decl-specifier:
+///           storage-class-specifier
+///           type-specifier
+///           function-specifier
+///           'friend'
+///           'typedef'
+/// [C++0x]   'constexpr'
+/// [GNU]     attributes declaration-specifiers[opt]
+///
+///         storage-class-specifier:
+///           'register'
+///           'static'
+///           'extern'
+///           'mutable'
+///           'auto'
+/// [GNU]     '__thread'
+///
+///         function-specifier:
+///           'inline'
+///           'virtual'
+///           'explicit'
+///
+///         typedef-name:
+///           identifier
+///
+///         type-specifier:
+///           simple-type-specifier
+///           class-specifier
+///           enum-specifier
+///           elaborated-type-specifier
+///           typename-specifier
+///           cv-qualifier
+///
+///         simple-type-specifier:
+///           '::'[opt] nested-name-specifier[opt] type-name
+///           '::'[opt] nested-name-specifier 'template'
+///                 simple-template-id                              [TODO]
+///           'char'
+///           'wchar_t'
+///           'bool'
+///           'short'
+///           'int'
+///           'long'
+///           'signed'
+///           'unsigned'
+///           'float'
+///           'double'
+///           'void'
+/// [GNU]     typeof-specifier
+/// [GNU]     '_Complex'
+/// [C++0x]   'auto'                                                [TODO]
+/// [C++0x]   'decltype' ( expression )
+///
+///         type-name:
+///           class-name
+///           enum-name
+///           typedef-name
+///
+///         elaborated-type-specifier:
+///           class-key '::'[opt] nested-name-specifier[opt] identifier
+///           class-key '::'[opt] nested-name-specifier[opt] 'template'[opt]
+///               simple-template-id
+///           'enum' '::'[opt] nested-name-specifier[opt] identifier
+///
+///         enum-name:
+///           identifier
+///
+///         enum-specifier:
+///           'enum' identifier[opt] '{' enumerator-list[opt] '}'
+///           'enum' identifier[opt] '{' enumerator-list ',' '}'
+///
+///         class-specifier:
+///           class-head '{' member-specification[opt] '}'
+///
+///         class-head:
+///           class-key identifier[opt] base-clause[opt]
+///           class-key nested-name-specifier identifier base-clause[opt]
+///           class-key nested-name-specifier[opt] simple-template-id
+///               base-clause[opt]
+///
+///         class-key:
+///           'class'
+///           'struct'
+///           'union'
+///
+///         cv-qualifier:
+///           'const'
+///           'volatile'
+/// [GNU]     restrict
+///
+Parser::TPResult Parser::isCXXDeclarationSpecifier() {
+  switch (Tok.getKind()) {
+  case tok::identifier:   // foo::bar
+    // Check for need to substitute AltiVec __vector keyword
+    // for "vector" identifier.
+    if (TryAltiVecVectorToken())
+      return TPResult::True();
+    // Fall through.
+  case tok::kw_typename:  // typename T::type
+    // Annotate typenames and C++ scope specifiers.  If we get one, just
+    // recurse to handle whatever we get.
+    if (TryAnnotateTypeOrScopeToken())
+      return isCXXDeclarationSpecifier();
+    // Otherwise, not a typename.
+    return TPResult::False();
+
+  case tok::coloncolon: {    // ::foo::bar
+    const Token &Next = NextToken();
+    if (Next.is(tok::kw_new) ||    // ::new
+        Next.is(tok::kw_delete))   // ::delete
+      return TPResult::False();
+
+    // Annotate typenames and C++ scope specifiers.  If we get one, just
+    // recurse to handle whatever we get.
+    if (TryAnnotateTypeOrScopeToken())
+      return isCXXDeclarationSpecifier();
+    // Otherwise, not a typename.
+    return TPResult::False();
+  }
+      
+    // decl-specifier:
+    //   storage-class-specifier
+    //   type-specifier
+    //   function-specifier
+    //   'friend'
+    //   'typedef'
+    //   'constexpr'
+  case tok::kw_friend:
+  case tok::kw_typedef:
+  case tok::kw_constexpr:
+    // storage-class-specifier
+  case tok::kw_register:
+  case tok::kw_static:
+  case tok::kw_extern:
+  case tok::kw_mutable:
+  case tok::kw_auto:
+  case tok::kw___thread:
+    // function-specifier
+  case tok::kw_inline:
+  case tok::kw_virtual:
+  case tok::kw_explicit:
+
+    // type-specifier:
+    //   simple-type-specifier
+    //   class-specifier
+    //   enum-specifier
+    //   elaborated-type-specifier
+    //   typename-specifier
+    //   cv-qualifier
+
+    // class-specifier
+    // elaborated-type-specifier
+  case tok::kw_class:
+  case tok::kw_struct:
+  case tok::kw_union:
+    // enum-specifier
+  case tok::kw_enum:
+    // cv-qualifier
+  case tok::kw_const:
+  case tok::kw_volatile:
+
+    // GNU
+  case tok::kw_restrict:
+  case tok::kw__Complex:
+  case tok::kw___attribute:
+    return TPResult::True();
+
+    // Microsoft
+  case tok::kw___declspec:
+  case tok::kw___cdecl:
+  case tok::kw___stdcall:
+  case tok::kw___fastcall:
+  case tok::kw___w64:
+  case tok::kw___ptr64:
+  case tok::kw___forceinline:
+    return TPResult::True();
+  
+    // AltiVec
+  case tok::kw___vector:
+    return TPResult::True();
+
+  case tok::annot_cxxscope: // foo::bar or ::foo::bar, but already parsed
+    // We've already annotated a scope; try to annotate a type.
+    if (!(TryAnnotateTypeOrScopeToken() && Tok.is(tok::annot_typename)))
+      return TPResult::False();
+    // If that succeeded, fallthrough into the generic simple-type-id case.
+
+    // The ambiguity resides in a simple-type-specifier/typename-specifier
+    // followed by a '('. The '(' could either be the start of:
+    //
+    //   direct-declarator:
+    //     '(' declarator ')'
+    //
+    //   direct-abstract-declarator:
+    //     '(' parameter-declaration-clause ')' cv-qualifier-seq[opt]
+    //              exception-specification[opt]
+    //     '(' abstract-declarator ')'
+    //
+    // or part of a function-style cast expression:
+    //
+    //     simple-type-specifier '(' expression-list[opt] ')'
+    //
+
+    // simple-type-specifier:
+
+  case tok::kw_char:
+  case tok::kw_wchar_t:
+  case tok::kw_char16_t:
+  case tok::kw_char32_t:
+  case tok::kw_bool:
+  case tok::kw_short:
+  case tok::kw_int:
+  case tok::kw_long:
+  case tok::kw_signed:
+  case tok::kw_unsigned:
+  case tok::kw_float:
+  case tok::kw_double:
+  case tok::kw_void:
+  case tok::annot_typename:
+    if (NextToken().is(tok::l_paren))
+      return TPResult::Ambiguous();
+
+    return TPResult::True();
+
+  // GNU typeof support.
+  case tok::kw_typeof: {
+    if (NextToken().isNot(tok::l_paren))
+      return TPResult::True();
+
+    TentativeParsingAction PA(*this);
+
+    TPResult TPR = TryParseTypeofSpecifier();
+    bool isFollowedByParen = Tok.is(tok::l_paren);
+
+    PA.Revert();
+
+    if (TPR == TPResult::Error())
+      return TPResult::Error();
+
+    if (isFollowedByParen)
+      return TPResult::Ambiguous();
+
+    return TPResult::True();
+  }
+
+  // C++0x decltype support.
+  case tok::kw_decltype:
+    return TPResult::True();
+
+  default:
+    return TPResult::False();
+  }
+}
+
+/// [GNU] typeof-specifier:
+///         'typeof' '(' expressions ')'
+///         'typeof' '(' type-name ')'
+///
+Parser::TPResult Parser::TryParseTypeofSpecifier() {
+  assert(Tok.is(tok::kw_typeof) && "Expected 'typeof'!");
+  ConsumeToken();
+
+  assert(Tok.is(tok::l_paren) && "Expected '('");
+  // Parse through the parens after 'typeof'.
+  ConsumeParen();
+  if (!SkipUntil(tok::r_paren))
+    return TPResult::Error();
+
+  return TPResult::Ambiguous();
+}
+
+Parser::TPResult Parser::TryParseDeclarationSpecifier() {
+  TPResult TPR = isCXXDeclarationSpecifier();
+  if (TPR != TPResult::Ambiguous())
+    return TPR;
+
+  if (Tok.is(tok::kw_typeof))
+    TryParseTypeofSpecifier();
+  else
+    ConsumeToken();
+
+  assert(Tok.is(tok::l_paren) && "Expected '('!");
+  return TPResult::Ambiguous();
+}
+
+/// isCXXFunctionDeclarator - Disambiguates between a function declarator or
+/// a constructor-style initializer, when parsing declaration statements.
+/// Returns true for function declarator and false for constructor-style
+/// initializer.
+/// If during the disambiguation process a parsing error is encountered,
+/// the function returns true to let the declaration parsing code handle it.
+///
+/// '(' parameter-declaration-clause ')' cv-qualifier-seq[opt]
+///         exception-specification[opt]
+///
+bool Parser::isCXXFunctionDeclarator(bool warnIfAmbiguous) {
+
+  // C++ 8.2p1:
+  // The ambiguity arising from the similarity between a function-style cast and
+  // a declaration mentioned in 6.8 can also occur in the context of a
+  // declaration. In that context, the choice is between a function declaration
+  // with a redundant set of parentheses around a parameter name and an object
+  // declaration with a function-style cast as the initializer. Just as for the
+  // ambiguities mentioned in 6.8, the resolution is to consider any construct
+  // that could possibly be a declaration a declaration.
+
+  TentativeParsingAction PA(*this);
+
+  ConsumeParen();
+  TPResult TPR = TryParseParameterDeclarationClause();
+  if (TPR == TPResult::Ambiguous() && Tok.isNot(tok::r_paren))
+    TPR = TPResult::False();
+
+  SourceLocation TPLoc = Tok.getLocation();
+  PA.Revert();
+
+  // In case of an error, let the declaration parsing code handle it.
+  if (TPR == TPResult::Error())
+    return true;
+
+  if (TPR == TPResult::Ambiguous()) {
+    // Function declarator has precedence over constructor-style initializer.
+    // Emit a warning just in case the author intended a variable definition.
+    if (warnIfAmbiguous)
+      Diag(Tok, diag::warn_parens_disambiguated_as_function_decl)
+        << SourceRange(Tok.getLocation(), TPLoc);
+    return true;
+  }
+
+  return TPR == TPResult::True();
+}
+
+/// parameter-declaration-clause:
+///   parameter-declaration-list[opt] '...'[opt]
+///   parameter-declaration-list ',' '...'
+///
+/// parameter-declaration-list:
+///   parameter-declaration
+///   parameter-declaration-list ',' parameter-declaration
+///
+/// parameter-declaration:
+///   decl-specifier-seq declarator
+///   decl-specifier-seq declarator '=' assignment-expression
+///   decl-specifier-seq abstract-declarator[opt]
+///   decl-specifier-seq abstract-declarator[opt] '=' assignment-expression
+///
+Parser::TPResult Parser::TryParseParameterDeclarationClause() {
+
+  if (Tok.is(tok::r_paren))
+    return TPResult::True();
+
+  //   parameter-declaration-list[opt] '...'[opt]
+  //   parameter-declaration-list ',' '...'
+  //
+  // parameter-declaration-list:
+  //   parameter-declaration
+  //   parameter-declaration-list ',' parameter-declaration
+  //
+  while (1) {
+    // '...'[opt]
+    if (Tok.is(tok::ellipsis)) {
+      ConsumeToken();
+      return TPResult::True(); // '...' is a sign of a function declarator.
+    }
+
+    // decl-specifier-seq
+    TPResult TPR = TryParseDeclarationSpecifier();
+    if (TPR != TPResult::Ambiguous())
+      return TPR;
+
+    // declarator
+    // abstract-declarator[opt]
+    TPR = TryParseDeclarator(true/*mayBeAbstract*/);
+    if (TPR != TPResult::Ambiguous())
+      return TPR;
+
+    if (Tok.is(tok::equal)) {
+      // '=' assignment-expression
+      // Parse through assignment-expression.
+      tok::TokenKind StopToks[3] ={ tok::comma, tok::ellipsis, tok::r_paren };
+      if (!SkipUntil(StopToks, 3, true/*StopAtSemi*/, true/*DontConsume*/))
+        return TPResult::Error();
+    }
+
+    if (Tok.is(tok::ellipsis)) {
+      ConsumeToken();
+      return TPResult::True(); // '...' is a sign of a function declarator.
+    }
+
+    if (Tok.isNot(tok::comma))
+      break;
+    ConsumeToken(); // the comma.
+  }
+
+  return TPResult::Ambiguous();
+}
+
+/// TryParseFunctionDeclarator - We parsed a '(' and we want to try to continue
+/// parsing as a function declarator.
+/// If TryParseFunctionDeclarator fully parsed the function declarator, it will
+/// return TPResult::Ambiguous(), otherwise it will return either False() or
+/// Error().
+///
+/// '(' parameter-declaration-clause ')' cv-qualifier-seq[opt]
+///         exception-specification[opt]
+///
+/// exception-specification:
+///   'throw' '(' type-id-list[opt] ')'
+///
+Parser::TPResult Parser::TryParseFunctionDeclarator() {
+
+  // The '(' is already parsed.
+
+  TPResult TPR = TryParseParameterDeclarationClause();
+  if (TPR == TPResult::Ambiguous() && Tok.isNot(tok::r_paren))
+    TPR = TPResult::False();
+
+  if (TPR == TPResult::False() || TPR == TPResult::Error())
+    return TPR;
+
+  // Parse through the parens.
+  if (!SkipUntil(tok::r_paren))
+    return TPResult::Error();
+
+  // cv-qualifier-seq
+  while (Tok.is(tok::kw_const)    ||
+         Tok.is(tok::kw_volatile) ||
+         Tok.is(tok::kw_restrict)   )
+    ConsumeToken();
+
+  // exception-specification
+  if (Tok.is(tok::kw_throw)) {
+    ConsumeToken();
+    if (Tok.isNot(tok::l_paren))
+      return TPResult::Error();
+
+    // Parse through the parens after 'throw'.
+    ConsumeParen();
+    if (!SkipUntil(tok::r_paren))
+      return TPResult::Error();
+  }
+
+  return TPResult::Ambiguous();
+}
+
+/// '[' constant-expression[opt] ']'
+///
+Parser::TPResult Parser::TryParseBracketDeclarator() {
+  ConsumeBracket();
+  if (!SkipUntil(tok::r_square))
+    return TPResult::Error();
+
+  return TPResult::Ambiguous();
+}
diff --git a/lib/Parse/Parser.cpp b/lib/Parse/Parser.cpp
new file mode 100644
index 0000000..e5bed30
--- /dev/null
+++ b/lib/Parse/Parser.cpp
@@ -0,0 +1,1089 @@
+//===--- Parser.cpp - C Language Family Parser ----------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+//  This file implements the Parser interfaces.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Parse/Parser.h"
+#include "clang/Parse/ParseDiagnostic.h"
+#include "clang/Parse/DeclSpec.h"
+#include "clang/Parse/Scope.h"
+#include "clang/Parse/Template.h"
+#include "llvm/Support/raw_ostream.h"
+#include "RAIIObjectsForParser.h"
+#include "ParsePragma.h"
+using namespace clang;
+
+/// \brief A comment handler that passes comments found by the preprocessor
+/// to the parser action.
+class ActionCommentHandler : public CommentHandler {
+  Action &Actions;
+
+public:
+  explicit ActionCommentHandler(Action &Actions) : Actions(Actions) { }
+
+  virtual bool HandleComment(Preprocessor &PP, SourceRange Comment) {
+    Actions.ActOnComment(Comment);
+    return false;
+  }
+};
+
+Parser::Parser(Preprocessor &pp, Action &actions)
+  : CrashInfo(*this), PP(pp), Actions(actions), Diags(PP.getDiagnostics()),
+    GreaterThanIsOperator(true), ColonIsSacred(false),
+    TemplateParameterDepth(0) {
+  Tok.setKind(tok::eof);
+  CurScope = 0;
+  NumCachedScopes = 0;
+  ParenCount = BracketCount = BraceCount = 0;
+  ObjCImpDecl = DeclPtrTy();
+
+  // Add #pragma handlers. These are removed and destroyed in the
+  // destructor.
+  PackHandler.reset(new
+          PragmaPackHandler(&PP.getIdentifierTable().get("pack"), actions));
+  PP.AddPragmaHandler(0, PackHandler.get());
+
+  UnusedHandler.reset(new
+          PragmaUnusedHandler(&PP.getIdentifierTable().get("unused"), actions,
+                              *this));
+  PP.AddPragmaHandler(0, UnusedHandler.get());
+
+  WeakHandler.reset(new
+          PragmaWeakHandler(&PP.getIdentifierTable().get("weak"), actions));
+  PP.AddPragmaHandler(0, WeakHandler.get());
+
+  CommentHandler.reset(new ActionCommentHandler(actions));
+  PP.AddCommentHandler(CommentHandler.get());
+}
+
+/// If a crash happens while the parser is active, print out a line indicating
+/// what the current token is.
+void PrettyStackTraceParserEntry::print(llvm::raw_ostream &OS) const {
+  const Token &Tok = P.getCurToken();
+  if (Tok.is(tok::eof)) {
+    OS << "<eof> parser at end of file\n";
+    return;
+  }
+
+  if (Tok.getLocation().isInvalid()) {
+    OS << "<unknown> parser at unknown location\n";
+    return;
+  }
+
+  const Preprocessor &PP = P.getPreprocessor();
+  Tok.getLocation().print(OS, PP.getSourceManager());
+  if (Tok.isAnnotation())
+    OS << ": at annotation token \n";
+  else
+    OS << ": current parser token '" << PP.getSpelling(Tok) << "'\n";
+}
+
+
+DiagnosticBuilder Parser::Diag(SourceLocation Loc, unsigned DiagID) {
+  return Diags.Report(FullSourceLoc(Loc, PP.getSourceManager()), DiagID);
+}
+
+DiagnosticBuilder Parser::Diag(const Token &Tok, unsigned DiagID) {
+  return Diag(Tok.getLocation(), DiagID);
+}
+
+/// \brief Emits a diagnostic suggesting parentheses surrounding a
+/// given range.
+///
+/// \param Loc The location where we'll emit the diagnostic.
+/// \param Loc The kind of diagnostic to emit.
+/// \param ParenRange Source range enclosing code that should be parenthesized.
+void Parser::SuggestParentheses(SourceLocation Loc, unsigned DK,
+                                SourceRange ParenRange) {
+  SourceLocation EndLoc = PP.getLocForEndOfToken(ParenRange.getEnd());
+  if (!ParenRange.getEnd().isFileID() || EndLoc.isInvalid()) {
+    // We can't display the parentheses, so just dig the
+    // warning/error and return.
+    Diag(Loc, DK);
+    return;
+  }
+
+  Diag(Loc, DK)
+    << CodeModificationHint::CreateInsertion(ParenRange.getBegin(), "(")
+    << CodeModificationHint::CreateInsertion(EndLoc, ")");
+}
+
+/// MatchRHSPunctuation - For punctuation with a LHS and RHS (e.g. '['/']'),
+/// this helper function matches and consumes the specified RHS token if
+/// present.  If not present, it emits the specified diagnostic indicating
+/// that the parser failed to match the RHS of the token at LHSLoc.  LHSName
+/// should be the name of the unmatched LHS token.
+SourceLocation Parser::MatchRHSPunctuation(tok::TokenKind RHSTok,
+                                           SourceLocation LHSLoc) {
+
+  if (Tok.is(RHSTok))
+    return ConsumeAnyToken();
+
+  SourceLocation R = Tok.getLocation();
+  const char *LHSName = "unknown";
+  diag::kind DID = diag::err_parse_error;
+  switch (RHSTok) {
+  default: break;
+  case tok::r_paren : LHSName = "("; DID = diag::err_expected_rparen; break;
+  case tok::r_brace : LHSName = "{"; DID = diag::err_expected_rbrace; break;
+  case tok::r_square: LHSName = "["; DID = diag::err_expected_rsquare; break;
+  case tok::greater:  LHSName = "<"; DID = diag::err_expected_greater; break;
+  }
+  Diag(Tok, DID);
+  Diag(LHSLoc, diag::note_matching) << LHSName;
+  SkipUntil(RHSTok);
+  return R;
+}
+
+/// ExpectAndConsume - The parser expects that 'ExpectedTok' is next in the
+/// input.  If so, it is consumed and false is returned.
+///
+/// If the input is malformed, this emits the specified diagnostic.  Next, if
+/// SkipToTok is specified, it calls SkipUntil(SkipToTok).  Finally, true is
+/// returned.
+bool Parser::ExpectAndConsume(tok::TokenKind ExpectedTok, unsigned DiagID,
+                              const char *Msg, tok::TokenKind SkipToTok) {
+  if (Tok.is(ExpectedTok)) {
+    ConsumeAnyToken();
+    return false;
+  }
+
+  const char *Spelling = 0;
+  SourceLocation EndLoc = PP.getLocForEndOfToken(PrevTokLocation);
+  if (EndLoc.isValid() &&
+      (Spelling = tok::getTokenSimpleSpelling(ExpectedTok))) {
+    // Show what code to insert to fix this problem.
+    Diag(EndLoc, DiagID)
+      << Msg
+      << CodeModificationHint::CreateInsertion(EndLoc, Spelling);
+  } else
+    Diag(Tok, DiagID) << Msg;
+
+  if (SkipToTok != tok::unknown)
+    SkipUntil(SkipToTok);
+  return true;
+}
+
+//===----------------------------------------------------------------------===//
+// Error recovery.
+//===----------------------------------------------------------------------===//
+
+/// SkipUntil - Read tokens until we get to the specified token, then consume
+/// it (unless DontConsume is true).  Because we cannot guarantee that the
+/// token will ever occur, this skips to the next token, or to some likely
+/// good stopping point.  If StopAtSemi is true, skipping will stop at a ';'
+/// character.
+///
+/// If SkipUntil finds the specified token, it returns true, otherwise it
+/// returns false.
+bool Parser::SkipUntil(const tok::TokenKind *Toks, unsigned NumToks,
+                       bool StopAtSemi, bool DontConsume) {
+  // We always want this function to skip at least one token if the first token
+  // isn't T and if not at EOF.
+  bool isFirstTokenSkipped = true;
+  while (1) {
+    // If we found one of the tokens, stop and return true.
+    for (unsigned i = 0; i != NumToks; ++i) {
+      if (Tok.is(Toks[i])) {
+        if (DontConsume) {
+          // Noop, don't consume the token.
+        } else {
+          ConsumeAnyToken();
+        }
+        return true;
+      }
+    }
+
+    switch (Tok.getKind()) {
+    case tok::eof:
+      // Ran out of tokens.
+      return false;
+
+    case tok::l_paren:
+      // Recursively skip properly-nested parens.
+      ConsumeParen();
+      SkipUntil(tok::r_paren, false);
+      break;
+    case tok::l_square:
+      // Recursively skip properly-nested square brackets.
+      ConsumeBracket();
+      SkipUntil(tok::r_square, false);
+      break;
+    case tok::l_brace:
+      // Recursively skip properly-nested braces.
+      ConsumeBrace();
+      SkipUntil(tok::r_brace, false);
+      break;
+
+    // Okay, we found a ']' or '}' or ')', which we think should be balanced.
+    // Since the user wasn't looking for this token (if they were, it would
+    // already be handled), this isn't balanced.  If there is a LHS token at a
+    // higher level, we will assume that this matches the unbalanced token
+    // and return it.  Otherwise, this is a spurious RHS token, which we skip.
+    case tok::r_paren:
+      if (ParenCount && !isFirstTokenSkipped)
+        return false;  // Matches something.
+      ConsumeParen();
+      break;
+    case tok::r_square:
+      if (BracketCount && !isFirstTokenSkipped)
+        return false;  // Matches something.
+      ConsumeBracket();
+      break;
+    case tok::r_brace:
+      if (BraceCount && !isFirstTokenSkipped)
+        return false;  // Matches something.
+      ConsumeBrace();
+      break;
+
+    case tok::string_literal:
+    case tok::wide_string_literal:
+      ConsumeStringToken();
+      break;
+    case tok::semi:
+      if (StopAtSemi)
+        return false;
+      // FALL THROUGH.
+    default:
+      // Skip this token.
+      ConsumeToken();
+      break;
+    }
+    isFirstTokenSkipped = false;
+  }
+}
+
+//===----------------------------------------------------------------------===//
+// Scope manipulation
+//===----------------------------------------------------------------------===//
+
+/// EnterScope - Start a new scope.
+void Parser::EnterScope(unsigned ScopeFlags) {
+  if (NumCachedScopes) {
+    Scope *N = ScopeCache[--NumCachedScopes];
+    N->Init(CurScope, ScopeFlags);
+    CurScope = N;
+  } else {
+    CurScope = new Scope(CurScope, ScopeFlags);
+  }
+}
+
+/// ExitScope - Pop a scope off the scope stack.
+void Parser::ExitScope() {
+  assert(CurScope && "Scope imbalance!");
+
+  // Inform the actions module that this scope is going away if there are any
+  // decls in it.
+  if (!CurScope->decl_empty())
+    Actions.ActOnPopScope(Tok.getLocation(), CurScope);
+
+  Scope *OldScope = CurScope;
+  CurScope = OldScope->getParent();
+
+  if (NumCachedScopes == ScopeCacheSize)
+    delete OldScope;
+  else
+    ScopeCache[NumCachedScopes++] = OldScope;
+}
+
+
+
+
+//===----------------------------------------------------------------------===//
+// C99 6.9: External Definitions.
+//===----------------------------------------------------------------------===//
+
+Parser::~Parser() {
+  // If we still have scopes active, delete the scope tree.
+  delete CurScope;
+
+  // Free the scope cache.
+  for (unsigned i = 0, e = NumCachedScopes; i != e; ++i)
+    delete ScopeCache[i];
+
+  // Remove the pragma handlers we installed.
+  PP.RemovePragmaHandler(0, PackHandler.get());
+  PackHandler.reset();
+  PP.RemovePragmaHandler(0, UnusedHandler.get());
+  UnusedHandler.reset();
+  PP.RemovePragmaHandler(0, WeakHandler.get());
+  WeakHandler.reset();
+  PP.RemoveCommentHandler(CommentHandler.get());
+}
+
+/// Initialize - Warm up the parser.
+///
+void Parser::Initialize() {
+  // Prime the lexer look-ahead.
+  ConsumeToken();
+
+  // Create the translation unit scope.  Install it as the current scope.
+  assert(CurScope == 0 && "A scope is already active?");
+  EnterScope(Scope::DeclScope);
+  Actions.ActOnTranslationUnitScope(Tok.getLocation(), CurScope);
+
+  if (Tok.is(tok::eof) &&
+      !getLang().CPlusPlus)  // Empty source file is an extension in C
+    Diag(Tok, diag::ext_empty_source_file);
+
+  // Initialization for Objective-C context sensitive keywords recognition.
+  // Referenced in Parser::ParseObjCTypeQualifierList.
+  if (getLang().ObjC1) {
+    ObjCTypeQuals[objc_in] = &PP.getIdentifierTable().get("in");
+    ObjCTypeQuals[objc_out] = &PP.getIdentifierTable().get("out");
+    ObjCTypeQuals[objc_inout] = &PP.getIdentifierTable().get("inout");
+    ObjCTypeQuals[objc_oneway] = &PP.getIdentifierTable().get("oneway");
+    ObjCTypeQuals[objc_bycopy] = &PP.getIdentifierTable().get("bycopy");
+    ObjCTypeQuals[objc_byref] = &PP.getIdentifierTable().get("byref");
+  }
+
+  Ident_super = &PP.getIdentifierTable().get("super");
+
+  if (getLang().AltiVec) {
+    Ident_vector = &PP.getIdentifierTable().get("vector");
+    Ident_pixel = &PP.getIdentifierTable().get("pixel");
+  }
+}
+
+/// ParseTopLevelDecl - Parse one top-level declaration, return whatever the
+/// action tells us to.  This returns true if the EOF was encountered.
+bool Parser::ParseTopLevelDecl(DeclGroupPtrTy &Result) {
+  Result = DeclGroupPtrTy();
+  if (Tok.is(tok::eof)) {
+    Actions.ActOnEndOfTranslationUnit();
+    return true;
+  }
+
+  CXX0XAttributeList Attr;
+  if (getLang().CPlusPlus0x && isCXX0XAttributeSpecifier())
+    Attr = ParseCXX0XAttributes();
+  Result = ParseExternalDeclaration(Attr);
+  return false;
+}
+
+/// ParseTranslationUnit:
+///       translation-unit: [C99 6.9]
+///         external-declaration
+///         translation-unit external-declaration
+void Parser::ParseTranslationUnit() {
+  Initialize();
+
+  DeclGroupPtrTy Res;
+  while (!ParseTopLevelDecl(Res))
+    /*parse them all*/;
+
+  ExitScope();
+  assert(CurScope == 0 && "Scope imbalance!");
+}
+
+/// ParseExternalDeclaration:
+///
+///       external-declaration: [C99 6.9], declaration: [C++ dcl.dcl]
+///         function-definition
+///         declaration
+/// [C++0x] empty-declaration
+/// [GNU]   asm-definition
+/// [GNU]   __extension__ external-declaration
+/// [OBJC]  objc-class-definition
+/// [OBJC]  objc-class-declaration
+/// [OBJC]  objc-alias-declaration
+/// [OBJC]  objc-protocol-definition
+/// [OBJC]  objc-method-definition
+/// [OBJC]  @end
+/// [C++]   linkage-specification
+/// [GNU] asm-definition:
+///         simple-asm-expr ';'
+///
+/// [C++0x] empty-declaration:
+///           ';'
+///
+/// [C++0x/GNU] 'extern' 'template' declaration
+Parser::DeclGroupPtrTy Parser::ParseExternalDeclaration(CXX0XAttributeList Attr) {
+  DeclPtrTy SingleDecl;
+  switch (Tok.getKind()) {
+  case tok::semi:
+    if (!getLang().CPlusPlus0x)
+      Diag(Tok, diag::ext_top_level_semi)
+        << CodeModificationHint::CreateRemoval(Tok.getLocation());
+
+    ConsumeToken();
+    // TODO: Invoke action for top-level semicolon.
+    return DeclGroupPtrTy();
+  case tok::r_brace:
+    Diag(Tok, diag::err_expected_external_declaration);
+    ConsumeBrace();
+    return DeclGroupPtrTy();
+  case tok::eof:
+    Diag(Tok, diag::err_expected_external_declaration);
+    return DeclGroupPtrTy();
+  case tok::kw___extension__: {
+    // __extension__ silences extension warnings in the subexpression.
+    ExtensionRAIIObject O(Diags);  // Use RAII to do this.
+    ConsumeToken();
+    return ParseExternalDeclaration(Attr);
+  }
+  case tok::kw_asm: {
+    if (Attr.HasAttr)
+      Diag(Attr.Range.getBegin(), diag::err_attributes_not_allowed)
+        << Attr.Range;
+
+    OwningExprResult Result(ParseSimpleAsm());
+
+    ExpectAndConsume(tok::semi, diag::err_expected_semi_after,
+                     "top-level asm block");
+
+    if (Result.isInvalid())
+      return DeclGroupPtrTy();
+    SingleDecl = Actions.ActOnFileScopeAsmDecl(Tok.getLocation(), move(Result));
+    break;
+  }
+  case tok::at:
+    // @ is not a legal token unless objc is enabled, no need to check for ObjC.
+    /// FIXME: ParseObjCAtDirectives should return a DeclGroup for things like
+    /// @class foo, bar;
+    SingleDecl = ParseObjCAtDirectives();
+    break;
+  case tok::minus:
+  case tok::plus:
+    if (!getLang().ObjC1) {
+      Diag(Tok, diag::err_expected_external_declaration);
+      ConsumeToken();
+      return DeclGroupPtrTy();
+    }
+    SingleDecl = ParseObjCMethodDefinition();
+    break;
+  case tok::code_completion:
+      Actions.CodeCompleteOrdinaryName(CurScope, 
+                                   ObjCImpDecl? Action::CCC_ObjCImplementation
+                                              : Action::CCC_Namespace);
+    ConsumeToken();
+    return ParseExternalDeclaration(Attr);
+  case tok::kw_using:
+  case tok::kw_namespace:
+  case tok::kw_typedef:
+  case tok::kw_template:
+  case tok::kw_export:    // As in 'export template'
+  case tok::kw_static_assert:
+    // A function definition cannot start with a these keywords.
+    {
+      SourceLocation DeclEnd;
+      return ParseDeclaration(Declarator::FileContext, DeclEnd, Attr);
+    }
+  case tok::kw_extern:
+    if (getLang().CPlusPlus && NextToken().is(tok::kw_template)) {
+      // Extern templates
+      SourceLocation ExternLoc = ConsumeToken();
+      SourceLocation TemplateLoc = ConsumeToken();
+      SourceLocation DeclEnd;
+      return Actions.ConvertDeclToDeclGroup(
+                  ParseExplicitInstantiation(ExternLoc, TemplateLoc, DeclEnd));
+    }
+
+    // FIXME: Detect C++ linkage specifications here?
+
+    // Fall through to handle other declarations or function definitions.
+
+  default:
+    // We can't tell whether this is a function-definition or declaration yet.
+    return ParseDeclarationOrFunctionDefinition(Attr.AttrList);
+  }
+
+  // This routine returns a DeclGroup, if the thing we parsed only contains a
+  // single decl, convert it now.
+  return Actions.ConvertDeclToDeclGroup(SingleDecl);
+}
+
+/// \brief Determine whether the current token, if it occurs after a
+/// declarator, continues a declaration or declaration list.
+bool Parser::isDeclarationAfterDeclarator() {
+  return Tok.is(tok::equal) ||      // int X()=  -> not a function def
+    Tok.is(tok::comma) ||           // int X(),  -> not a function def
+    Tok.is(tok::semi)  ||           // int X();  -> not a function def
+    Tok.is(tok::kw_asm) ||          // int X() __asm__ -> not a function def
+    Tok.is(tok::kw___attribute) ||  // int X() __attr__ -> not a function def
+    (getLang().CPlusPlus &&
+     Tok.is(tok::l_paren));         // int X(0) -> not a function def [C++]
+}
+
+/// \brief Determine whether the current token, if it occurs after a
+/// declarator, indicates the start of a function definition.
+bool Parser::isStartOfFunctionDefinition() {
+  if (Tok.is(tok::l_brace))   // int X() {}
+    return true;
+  
+  if (!getLang().CPlusPlus)
+    return isDeclarationSpecifier();   // int X(f) int f; {}
+  return Tok.is(tok::colon) ||         // X() : Base() {} (used for ctors)
+         Tok.is(tok::kw_try);          // X() try { ... }
+}
+
+/// ParseDeclarationOrFunctionDefinition - Parse either a function-definition or
+/// a declaration.  We can't tell which we have until we read up to the
+/// compound-statement in function-definition. TemplateParams, if
+/// non-NULL, provides the template parameters when we're parsing a
+/// C++ template-declaration.
+///
+///       function-definition: [C99 6.9.1]
+///         decl-specs      declarator declaration-list[opt] compound-statement
+/// [C90] function-definition: [C99 6.7.1] - implicit int result
+/// [C90]   decl-specs[opt] declarator declaration-list[opt] compound-statement
+///
+///       declaration: [C99 6.7]
+///         declaration-specifiers init-declarator-list[opt] ';'
+/// [!C99]  init-declarator-list ';'                   [TODO: warn in c99 mode]
+/// [OMP]   threadprivate-directive                              [TODO]
+///
+Parser::DeclGroupPtrTy
+Parser::ParseDeclarationOrFunctionDefinition(ParsingDeclSpec &DS,
+                                             AttributeList *Attr,
+                                             AccessSpecifier AS) {
+  // Parse the common declaration-specifiers piece.
+  if (Attr)
+    DS.AddAttributes(Attr);
+
+  ParseDeclarationSpecifiers(DS, ParsedTemplateInfo(), AS, DSC_top_level);
+
+  // C99 6.7.2.3p6: Handle "struct-or-union identifier;", "enum { X };"
+  // declaration-specifiers init-declarator-list[opt] ';'
+  if (Tok.is(tok::semi)) {
+    ConsumeToken();
+    DeclPtrTy TheDecl = Actions.ParsedFreeStandingDeclSpec(CurScope, DS);
+    DS.complete(TheDecl);
+    return Actions.ConvertDeclToDeclGroup(TheDecl);
+  }
+
+  // ObjC2 allows prefix attributes on class interfaces and protocols.
+  // FIXME: This still needs better diagnostics. We should only accept
+  // attributes here, no types, etc.
+  if (getLang().ObjC2 && Tok.is(tok::at)) {
+    SourceLocation AtLoc = ConsumeToken(); // the "@"
+    if (!Tok.isObjCAtKeyword(tok::objc_interface) &&
+        !Tok.isObjCAtKeyword(tok::objc_protocol)) {
+      Diag(Tok, diag::err_objc_unexpected_attr);
+      SkipUntil(tok::semi); // FIXME: better skip?
+      return DeclGroupPtrTy();
+    }
+
+    DS.abort();
+
+    const char *PrevSpec = 0;
+    unsigned DiagID;
+    if (DS.SetTypeSpecType(DeclSpec::TST_unspecified, AtLoc, PrevSpec, DiagID))
+      Diag(AtLoc, DiagID) << PrevSpec;
+
+    DeclPtrTy TheDecl;
+    if (Tok.isObjCAtKeyword(tok::objc_protocol))
+      TheDecl = ParseObjCAtProtocolDeclaration(AtLoc, DS.getAttributes());
+    else
+      TheDecl = ParseObjCAtInterfaceDeclaration(AtLoc, DS.getAttributes());
+    return Actions.ConvertDeclToDeclGroup(TheDecl);
+  }
+
+  // If the declspec consisted only of 'extern' and we have a string
+  // literal following it, this must be a C++ linkage specifier like
+  // 'extern "C"'.
+  if (Tok.is(tok::string_literal) && getLang().CPlusPlus &&
+      DS.getStorageClassSpec() == DeclSpec::SCS_extern &&
+      DS.getParsedSpecifiers() == DeclSpec::PQ_StorageClassSpecifier) {
+    DeclPtrTy TheDecl = ParseLinkage(DS, Declarator::FileContext);
+    return Actions.ConvertDeclToDeclGroup(TheDecl);
+  }
+
+  return ParseDeclGroup(DS, Declarator::FileContext, true);
+}
+
+Parser::DeclGroupPtrTy
+Parser::ParseDeclarationOrFunctionDefinition(AttributeList *Attr,
+                                             AccessSpecifier AS) {
+  ParsingDeclSpec DS(*this);
+  return ParseDeclarationOrFunctionDefinition(DS, Attr, AS);
+}
+
+/// ParseFunctionDefinition - We parsed and verified that the specified
+/// Declarator is well formed.  If this is a K&R-style function, read the
+/// parameters declaration-list, then start the compound-statement.
+///
+///       function-definition: [C99 6.9.1]
+///         decl-specs      declarator declaration-list[opt] compound-statement
+/// [C90] function-definition: [C99 6.7.1] - implicit int result
+/// [C90]   decl-specs[opt] declarator declaration-list[opt] compound-statement
+/// [C++] function-definition: [C++ 8.4]
+///         decl-specifier-seq[opt] declarator ctor-initializer[opt]
+///         function-body
+/// [C++] function-definition: [C++ 8.4]
+///         decl-specifier-seq[opt] declarator function-try-block
+///
+Parser::DeclPtrTy Parser::ParseFunctionDefinition(ParsingDeclarator &D,
+                                     const ParsedTemplateInfo &TemplateInfo) {
+  const DeclaratorChunk &FnTypeInfo = D.getTypeObject(0);
+  assert(FnTypeInfo.Kind == DeclaratorChunk::Function &&
+         "This isn't a function declarator!");
+  const DeclaratorChunk::FunctionTypeInfo &FTI = FnTypeInfo.Fun;
+
+  // If this is C90 and the declspecs were completely missing, fudge in an
+  // implicit int.  We do this here because this is the only place where
+  // declaration-specifiers are completely optional in the grammar.
+  if (getLang().ImplicitInt && D.getDeclSpec().isEmpty()) {
+    const char *PrevSpec;
+    unsigned DiagID;
+    D.getMutableDeclSpec().SetTypeSpecType(DeclSpec::TST_int,
+                                           D.getIdentifierLoc(),
+                                           PrevSpec, DiagID);
+    D.SetRangeBegin(D.getDeclSpec().getSourceRange().getBegin());
+  }
+
+  // If this declaration was formed with a K&R-style identifier list for the
+  // arguments, parse declarations for all of the args next.
+  // int foo(a,b) int a; float b; {}
+  if (!FTI.hasPrototype && FTI.NumArgs != 0)
+    ParseKNRParamDeclarations(D);
+
+  // We should have either an opening brace or, in a C++ constructor,
+  // we may have a colon.
+  if (Tok.isNot(tok::l_brace) && Tok.isNot(tok::colon) &&
+      Tok.isNot(tok::kw_try)) {
+    Diag(Tok, diag::err_expected_fn_body);
+
+    // Skip over garbage, until we get to '{'.  Don't eat the '{'.
+    SkipUntil(tok::l_brace, true, true);
+
+    // If we didn't find the '{', bail out.
+    if (Tok.isNot(tok::l_brace))
+      return DeclPtrTy();
+  }
+
+  // Enter a scope for the function body.
+  ParseScope BodyScope(this, Scope::FnScope|Scope::DeclScope);
+
+  // Tell the actions module that we have entered a function definition with the
+  // specified Declarator for the function.
+  DeclPtrTy Res = TemplateInfo.TemplateParams?
+      Actions.ActOnStartOfFunctionTemplateDef(CurScope,
+                              Action::MultiTemplateParamsArg(Actions,
+                                          TemplateInfo.TemplateParams->data(),
+                                         TemplateInfo.TemplateParams->size()),
+                                              D)
+    : Actions.ActOnStartOfFunctionDef(CurScope, D);
+
+  // Break out of the ParsingDeclarator context before we parse the body.
+  D.complete(Res);
+  
+  // Break out of the ParsingDeclSpec context, too.  This const_cast is
+  // safe because we're always the sole owner.
+  D.getMutableDeclSpec().abort();
+
+  if (Tok.is(tok::kw_try))
+    return ParseFunctionTryBlock(Res);
+
+  // If we have a colon, then we're probably parsing a C++
+  // ctor-initializer.
+  if (Tok.is(tok::colon))
+    ParseConstructorInitializer(Res);
+  else
+    Actions.ActOnDefaultCtorInitializers(Res);
+
+  return ParseFunctionStatementBody(Res);
+}
+
+/// ParseKNRParamDeclarations - Parse 'declaration-list[opt]' which provides
+/// types for a function with a K&R-style identifier list for arguments.
+void Parser::ParseKNRParamDeclarations(Declarator &D) {
+  // We know that the top-level of this declarator is a function.
+  DeclaratorChunk::FunctionTypeInfo &FTI = D.getTypeObject(0).Fun;
+
+  // Enter function-declaration scope, limiting any declarators to the
+  // function prototype scope, including parameter declarators.
+  ParseScope PrototypeScope(this, Scope::FunctionPrototypeScope|Scope::DeclScope);
+
+  // Read all the argument declarations.
+  while (isDeclarationSpecifier()) {
+    SourceLocation DSStart = Tok.getLocation();
+
+    // Parse the common declaration-specifiers piece.
+    DeclSpec DS;
+    ParseDeclarationSpecifiers(DS);
+
+    // C99 6.9.1p6: 'each declaration in the declaration list shall have at
+    // least one declarator'.
+    // NOTE: GCC just makes this an ext-warn.  It's not clear what it does with
+    // the declarations though.  It's trivial to ignore them, really hard to do
+    // anything else with them.
+    if (Tok.is(tok::semi)) {
+      Diag(DSStart, diag::err_declaration_does_not_declare_param);
+      ConsumeToken();
+      continue;
+    }
+
+    // C99 6.9.1p6: Declarations shall contain no storage-class specifiers other
+    // than register.
+    if (DS.getStorageClassSpec() != DeclSpec::SCS_unspecified &&
+        DS.getStorageClassSpec() != DeclSpec::SCS_register) {
+      Diag(DS.getStorageClassSpecLoc(),
+           diag::err_invalid_storage_class_in_func_decl);
+      DS.ClearStorageClassSpecs();
+    }
+    if (DS.isThreadSpecified()) {
+      Diag(DS.getThreadSpecLoc(),
+           diag::err_invalid_storage_class_in_func_decl);
+      DS.ClearStorageClassSpecs();
+    }
+
+    // Parse the first declarator attached to this declspec.
+    Declarator ParmDeclarator(DS, Declarator::KNRTypeListContext);
+    ParseDeclarator(ParmDeclarator);
+
+    // Handle the full declarator list.
+    while (1) {
+      Action::AttrTy *AttrList;
+      // If attributes are present, parse them.
+      if (Tok.is(tok::kw___attribute))
+        // FIXME: attach attributes too.
+        AttrList = ParseGNUAttributes();
+
+      // Ask the actions module to compute the type for this declarator.
+      Action::DeclPtrTy Param =
+        Actions.ActOnParamDeclarator(CurScope, ParmDeclarator);
+
+      if (Param &&
+          // A missing identifier has already been diagnosed.
+          ParmDeclarator.getIdentifier()) {
+
+        // Scan the argument list looking for the correct param to apply this
+        // type.
+        for (unsigned i = 0; ; ++i) {
+          // C99 6.9.1p6: those declarators shall declare only identifiers from
+          // the identifier list.
+          if (i == FTI.NumArgs) {
+            Diag(ParmDeclarator.getIdentifierLoc(), diag::err_no_matching_param)
+              << ParmDeclarator.getIdentifier();
+            break;
+          }
+
+          if (FTI.ArgInfo[i].Ident == ParmDeclarator.getIdentifier()) {
+            // Reject redefinitions of parameters.
+            if (FTI.ArgInfo[i].Param) {
+              Diag(ParmDeclarator.getIdentifierLoc(),
+                   diag::err_param_redefinition)
+                 << ParmDeclarator.getIdentifier();
+            } else {
+              FTI.ArgInfo[i].Param = Param;
+            }
+            break;
+          }
+        }
+      }
+
+      // If we don't have a comma, it is either the end of the list (a ';') or
+      // an error, bail out.
+      if (Tok.isNot(tok::comma))
+        break;
+
+      // Consume the comma.
+      ConsumeToken();
+
+      // Parse the next declarator.
+      ParmDeclarator.clear();
+      ParseDeclarator(ParmDeclarator);
+    }
+
+    if (Tok.is(tok::semi)) {
+      ConsumeToken();
+    } else {
+      Diag(Tok, diag::err_parse_error);
+      // Skip to end of block or statement
+      SkipUntil(tok::semi, true);
+      if (Tok.is(tok::semi))
+        ConsumeToken();
+    }
+  }
+
+  // The actions module must verify that all arguments were declared.
+  Actions.ActOnFinishKNRParamDeclarations(CurScope, D, Tok.getLocation());
+}
+
+
+/// ParseAsmStringLiteral - This is just a normal string-literal, but is not
+/// allowed to be a wide string, and is not subject to character translation.
+///
+/// [GNU] asm-string-literal:
+///         string-literal
+///
+Parser::OwningExprResult Parser::ParseAsmStringLiteral() {
+  if (!isTokenStringLiteral()) {
+    Diag(Tok, diag::err_expected_string_literal);
+    return ExprError();
+  }
+
+  OwningExprResult Res(ParseStringLiteralExpression());
+  if (Res.isInvalid()) return move(Res);
+
+  // TODO: Diagnose: wide string literal in 'asm'
+
+  return move(Res);
+}
+
+/// ParseSimpleAsm
+///
+/// [GNU] simple-asm-expr:
+///         'asm' '(' asm-string-literal ')'
+///
+Parser::OwningExprResult Parser::ParseSimpleAsm(SourceLocation *EndLoc) {
+  assert(Tok.is(tok::kw_asm) && "Not an asm!");
+  SourceLocation Loc = ConsumeToken();
+
+  if (Tok.is(tok::kw_volatile)) {
+    // Remove from the end of 'asm' to the end of 'volatile'.
+    SourceRange RemovalRange(PP.getLocForEndOfToken(Loc),
+                             PP.getLocForEndOfToken(Tok.getLocation()));
+
+    Diag(Tok, diag::warn_file_asm_volatile)
+      << CodeModificationHint::CreateRemoval(RemovalRange);
+    ConsumeToken();
+  }
+
+  if (Tok.isNot(tok::l_paren)) {
+    Diag(Tok, diag::err_expected_lparen_after) << "asm";
+    return ExprError();
+  }
+
+  Loc = ConsumeParen();
+
+  OwningExprResult Result(ParseAsmStringLiteral());
+
+  if (Result.isInvalid()) {
+    SkipUntil(tok::r_paren, true, true);
+    if (EndLoc)
+      *EndLoc = Tok.getLocation();
+    ConsumeAnyToken();
+  } else {
+    Loc = MatchRHSPunctuation(tok::r_paren, Loc);
+    if (EndLoc)
+      *EndLoc = Loc;
+  }
+
+  return move(Result);
+}
+
+/// TryAnnotateTypeOrScopeToken - If the current token position is on a
+/// typename (possibly qualified in C++) or a C++ scope specifier not followed
+/// by a typename, TryAnnotateTypeOrScopeToken will replace one or more tokens
+/// with a single annotation token representing the typename or C++ scope
+/// respectively.
+/// This simplifies handling of C++ scope specifiers and allows efficient
+/// backtracking without the need to re-parse and resolve nested-names and
+/// typenames.
+/// It will mainly be called when we expect to treat identifiers as typenames
+/// (if they are typenames). For example, in C we do not expect identifiers
+/// inside expressions to be treated as typenames so it will not be called
+/// for expressions in C.
+/// The benefit for C/ObjC is that a typename will be annotated and
+/// Actions.getTypeName will not be needed to be called again (e.g. getTypeName
+/// will not be called twice, once to check whether we have a declaration
+/// specifier, and another one to get the actual type inside
+/// ParseDeclarationSpecifiers).
+///
+/// This returns true if the token was annotated or an unrecoverable error
+/// occurs.
+///
+/// Note that this routine emits an error if you call it with ::new or ::delete
+/// as the current tokens, so only call it in contexts where these are invalid.
+bool Parser::TryAnnotateTypeOrScopeToken(bool EnteringContext) {
+  assert((Tok.is(tok::identifier) || Tok.is(tok::coloncolon)
+          || Tok.is(tok::kw_typename) || Tok.is(tok::annot_cxxscope)) &&
+         "Cannot be a type or scope token!");
+
+  if (Tok.is(tok::kw_typename)) {
+    // Parse a C++ typename-specifier, e.g., "typename T::type".
+    //
+    //   typename-specifier:
+    //     'typename' '::' [opt] nested-name-specifier identifier
+    //     'typename' '::' [opt] nested-name-specifier template [opt]
+    //            simple-template-id
+    SourceLocation TypenameLoc = ConsumeToken();
+    CXXScopeSpec SS;
+    bool HadNestedNameSpecifier
+      = ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/0, false);
+    if (!HadNestedNameSpecifier) {
+      Diag(Tok.getLocation(), diag::err_expected_qualified_after_typename);
+      return false;
+    }
+
+    TypeResult Ty;
+    if (Tok.is(tok::identifier)) {
+      // FIXME: check whether the next token is '<', first!
+      Ty = Actions.ActOnTypenameType(TypenameLoc, SS, *Tok.getIdentifierInfo(),
+                                     Tok.getLocation());
+    } else if (Tok.is(tok::annot_template_id)) {
+      TemplateIdAnnotation *TemplateId
+        = static_cast<TemplateIdAnnotation *>(Tok.getAnnotationValue());
+      if (TemplateId->Kind == TNK_Function_template) {
+        Diag(Tok, diag::err_typename_refers_to_non_type_template)
+          << Tok.getAnnotationRange();
+        return false;
+      }
+
+      AnnotateTemplateIdTokenAsType(0);
+      assert(Tok.is(tok::annot_typename) &&
+             "AnnotateTemplateIdTokenAsType isn't working properly");
+      if (Tok.getAnnotationValue())
+        Ty = Actions.ActOnTypenameType(TypenameLoc, SS, SourceLocation(),
+                                       Tok.getAnnotationValue());
+      else
+        Ty = true;
+    } else {
+      Diag(Tok, diag::err_expected_type_name_after_typename)
+        << SS.getRange();
+      return false;
+    }
+
+    SourceLocation EndLoc = Tok.getLastLoc();
+    Tok.setKind(tok::annot_typename);
+    Tok.setAnnotationValue(Ty.isInvalid()? 0 : Ty.get());
+    Tok.setAnnotationEndLoc(EndLoc);
+    Tok.setLocation(TypenameLoc);
+    PP.AnnotateCachedTokens(Tok);
+    return true;
+  }
+
+  // Remembers whether the token was originally a scope annotation.
+  bool wasScopeAnnotation = Tok.is(tok::annot_cxxscope);
+
+  CXXScopeSpec SS;
+  if (getLang().CPlusPlus)
+    ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/0, EnteringContext);
+
+  if (Tok.is(tok::identifier)) {
+    // Determine whether the identifier is a type name.
+    if (TypeTy *Ty = Actions.getTypeName(*Tok.getIdentifierInfo(),
+                                         Tok.getLocation(), CurScope, &SS)) {
+      // This is a typename. Replace the current token in-place with an
+      // annotation type token.
+      Tok.setKind(tok::annot_typename);
+      Tok.setAnnotationValue(Ty);
+      Tok.setAnnotationEndLoc(Tok.getLocation());
+      if (SS.isNotEmpty()) // it was a C++ qualified type name.
+        Tok.setLocation(SS.getBeginLoc());
+
+      // In case the tokens were cached, have Preprocessor replace
+      // them with the annotation token.
+      PP.AnnotateCachedTokens(Tok);
+      return true;
+    }
+
+    if (!getLang().CPlusPlus) {
+      // If we're in C, we can't have :: tokens at all (the lexer won't return
+      // them).  If the identifier is not a type, then it can't be scope either,
+      // just early exit.
+      return false;
+    }
+
+    // If this is a template-id, annotate with a template-id or type token.
+    if (NextToken().is(tok::less)) {
+      TemplateTy Template;
+      UnqualifiedId TemplateName;
+      TemplateName.setIdentifier(Tok.getIdentifierInfo(), Tok.getLocation());
+      if (TemplateNameKind TNK
+            = Actions.isTemplateName(CurScope, SS, TemplateName, 
+                                     /*ObjectType=*/0, EnteringContext,
+                                     Template)) {
+        // Consume the identifier.
+        ConsumeToken();
+        if (AnnotateTemplateIdToken(Template, TNK, &SS, TemplateName)) {
+          // If an unrecoverable error occurred, we need to return true here,
+          // because the token stream is in a damaged state.  We may not return
+          // a valid identifier.
+          return Tok.isNot(tok::identifier);
+        }
+      }
+    }
+
+    // The current token, which is either an identifier or a
+    // template-id, is not part of the annotation. Fall through to
+    // push that token back into the stream and complete the C++ scope
+    // specifier annotation.
+  }
+
+  if (Tok.is(tok::annot_template_id)) {
+    TemplateIdAnnotation *TemplateId
+      = static_cast<TemplateIdAnnotation *>(Tok.getAnnotationValue());
+    if (TemplateId->Kind == TNK_Type_template) {
+      // A template-id that refers to a type was parsed into a
+      // template-id annotation in a context where we weren't allowed
+      // to produce a type annotation token. Update the template-id
+      // annotation token to a type annotation token now.
+      AnnotateTemplateIdTokenAsType(&SS);
+      return true;
+    }
+  }
+
+  if (SS.isEmpty())
+    return Tok.isNot(tok::identifier) && Tok.isNot(tok::coloncolon);
+
+  // A C++ scope specifier that isn't followed by a typename.
+  // Push the current token back into the token stream (or revert it if it is
+  // cached) and use an annotation scope token for current token.
+  if (PP.isBacktrackEnabled())
+    PP.RevertCachedTokens(1);
+  else
+    PP.EnterToken(Tok);
+  Tok.setKind(tok::annot_cxxscope);
+  Tok.setAnnotationValue(SS.getScopeRep());
+  Tok.setAnnotationRange(SS.getRange());
+
+  // In case the tokens were cached, have Preprocessor replace them
+  // with the annotation token.  We don't need to do this if we've
+  // just reverted back to the state we were in before being called.
+  if (!wasScopeAnnotation)
+    PP.AnnotateCachedTokens(Tok);
+  return true;
+}
+
+/// TryAnnotateScopeToken - Like TryAnnotateTypeOrScopeToken but only
+/// annotates C++ scope specifiers and template-ids.  This returns
+/// true if the token was annotated or there was an error that could not be
+/// recovered from.
+///
+/// Note that this routine emits an error if you call it with ::new or ::delete
+/// as the current tokens, so only call it in contexts where these are invalid.
+bool Parser::TryAnnotateCXXScopeToken(bool EnteringContext) {
+  assert(getLang().CPlusPlus &&
+         "Call sites of this function should be guarded by checking for C++");
+  assert((Tok.is(tok::identifier) || Tok.is(tok::coloncolon)) &&
+         "Cannot be a type or scope token!");
+
+  CXXScopeSpec SS;
+  if (!ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/0, EnteringContext))
+    // If the token left behind is not an identifier, we either had an error or
+    // successfully turned it into an annotation token.
+    return Tok.isNot(tok::identifier);
+
+  // Push the current token back into the token stream (or revert it if it is
+  // cached) and use an annotation scope token for current token.
+  if (PP.isBacktrackEnabled())
+    PP.RevertCachedTokens(1);
+  else
+    PP.EnterToken(Tok);
+  Tok.setKind(tok::annot_cxxscope);
+  Tok.setAnnotationValue(SS.getScopeRep());
+  Tok.setAnnotationRange(SS.getRange());
+
+  // In case the tokens were cached, have Preprocessor replace them with the
+  // annotation token.
+  PP.AnnotateCachedTokens(Tok);
+  return true;
+}
+
+// Anchor the Parser::FieldCallback vtable to this translation unit.
+// We use a spurious method instead of the destructor because
+// destroying FieldCallbacks can actually be slightly
+// performance-sensitive.
+void Parser::FieldCallback::_anchor() {
+}
diff --git a/lib/Parse/RAIIObjectsForParser.h b/lib/Parse/RAIIObjectsForParser.h
new file mode 100644
index 0000000..06bbbc2
--- /dev/null
+++ b/lib/Parse/RAIIObjectsForParser.h
@@ -0,0 +1,85 @@
+//===--- RAIIObjectsForParser.h - RAII helpers for the parser ---*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines and implements the some simple RAII objects that are used
+// by the parser to manage bits in recursion.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_PARSE_RAII_OBJECTS_FOR_PARSER_H
+#define LLVM_CLANG_PARSE_RAII_OBJECTS_FOR_PARSER_H
+
+#include "clang/Parse/ParseDiagnostic.h"
+
+namespace clang {
+  // TODO: move ParsingDeclRAIIObject here.
+  // TODO: move ParsingClassDefinition here.
+  // TODO: move TentativeParsingAction here.
+  
+  
+  /// ExtensionRAIIObject - This saves the state of extension warnings when
+  /// constructed and disables them.  When destructed, it restores them back to
+  /// the way they used to be.  This is used to handle __extension__ in the
+  /// parser.
+  class ExtensionRAIIObject {
+    void operator=(const ExtensionRAIIObject &);     // DO NOT IMPLEMENT
+    ExtensionRAIIObject(const ExtensionRAIIObject&); // DO NOT IMPLEMENT
+    Diagnostic &Diags;
+  public:
+    ExtensionRAIIObject(Diagnostic &diags) : Diags(diags) {
+      Diags.IncrementAllExtensionsSilenced();
+    }
+
+    ~ExtensionRAIIObject() {
+      Diags.DecrementAllExtensionsSilenced();
+    }
+  };
+  
+  /// ColonProtectionRAIIObject - This sets the Parser::ColonIsSacred bool and
+  /// restores it when destroyed.  This says that "foo:" should not be
+  /// considered a possible typo for "foo::" for error recovery purposes.
+  class ColonProtectionRAIIObject {
+    Parser &P;
+    bool OldVal;
+  public:
+    ColonProtectionRAIIObject(Parser &p, bool Value = true)
+      : P(p), OldVal(P.ColonIsSacred) {
+      P.ColonIsSacred = Value;
+    }
+    
+    /// restore - This can be used to restore the state early, before the dtor
+    /// is run.
+    void restore() {
+      P.ColonIsSacred = OldVal;
+    }
+    
+    ~ColonProtectionRAIIObject() {
+      restore();
+    }
+  };
+  
+  /// \brief RAII object that makes '>' behave either as an operator
+  /// or as the closing angle bracket for a template argument list.
+  class GreaterThanIsOperatorScope {
+    bool &GreaterThanIsOperator;
+    bool OldGreaterThanIsOperator;
+  public:
+    GreaterThanIsOperatorScope(bool &GTIO, bool Val)
+    : GreaterThanIsOperator(GTIO), OldGreaterThanIsOperator(GTIO) {
+      GreaterThanIsOperator = Val;
+    }
+    
+    ~GreaterThanIsOperatorScope() {
+      GreaterThanIsOperator = OldGreaterThanIsOperator;
+    }
+  };
+  
+} // end namespace clang
+
+#endif