Stage two of getting CFE top correct.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@39734 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/Parse/AttributeList.cpp b/Parse/AttributeList.cpp
new file mode 100644
index 0000000..385dc03
--- /dev/null
+++ b/Parse/AttributeList.cpp
@@ -0,0 +1,27 @@
+//===--- AttributeList.cpp --------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file was developed by Steve Naroff and is distributed under
+// the University of Illinois Open Source License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the AttributeList class implementation
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Parse/AttributeList.h"
+#include "clang/Lex/IdentifierTable.h"
+using namespace clang;
+
+AttributeList::AttributeList(IdentifierInfo *aName, SourceLocation aLoc,
+                             IdentifierInfo *pName, SourceLocation pLoc,
+                             Action::ExprTy **elist, unsigned numargs, 
+                             AttributeList *n)
+  : AttrName(aName), AttrLoc(aLoc), ParmName(pName), ParmLoc(pLoc),
+    NumArgs(numargs), Next(n) {
+  Args = new Action::ExprTy*[numargs];
+  for (unsigned i = 0; i != numargs; ++i)
+    Args[i] = elist[i];
+}
diff --git a/Parse/DeclSpec.cpp b/Parse/DeclSpec.cpp
new file mode 100644
index 0000000..117ff12
--- /dev/null
+++ b/Parse/DeclSpec.cpp
@@ -0,0 +1,285 @@
+//===--- SemaDeclSpec.cpp - Declaration Specifier Semantic Analysis -------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file was developed by Chris Lattner and 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/Basic/LangOptions.h"
+#include "clang/Basic/SourceLocation.h"
+using namespace clang;
+
+/// getParsedSpecifiers - Return a bitmask of which flavors of specifiers this
+///
+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)
+    Res |= PQ_FunctionSpecifier;
+  return Res;
+}
+
+const char *DeclSpec::getSpecifierName(DeclSpec::SCS S) {
+  switch (S) {
+  default: assert(0 && "Unknown typespec!");
+  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";
+  }
+}
+
+static bool BadSpecifier(DeclSpec::SCS S, const char *&PrevSpec) {
+  PrevSpec = DeclSpec::getSpecifierName(S);
+  return true;
+}
+
+static bool BadSpecifier(DeclSpec::TSW W, const char *&PrevSpec) {
+  switch (W) {
+  case DeclSpec::TSW_unspecified: PrevSpec = "unspecified"; break;
+  case DeclSpec::TSW_short:       PrevSpec = "short"; break;
+  case DeclSpec::TSW_long:        PrevSpec = "long"; break;
+  case DeclSpec::TSW_longlong:    PrevSpec = "long long"; break;
+  }
+  return true;
+}
+
+static bool BadSpecifier(DeclSpec::TSC C, const char *&PrevSpec) {
+  switch (C) {
+  case DeclSpec::TSC_unspecified: PrevSpec = "unspecified"; break;
+  case DeclSpec::TSC_imaginary:   PrevSpec = "imaginary"; break;
+  case DeclSpec::TSC_complex:     PrevSpec = "complex"; break;
+  }
+  return true;
+}
+
+
+static bool BadSpecifier(DeclSpec::TSS S, const char *&PrevSpec) {
+  switch (S) {
+  case DeclSpec::TSS_unspecified: PrevSpec = "unspecified"; break;
+  case DeclSpec::TSS_signed:      PrevSpec = "signed"; break;
+  case DeclSpec::TSS_unsigned:    PrevSpec = "unsigned"; break;
+  }
+  return true;
+}
+
+const char *DeclSpec::getSpecifierName(DeclSpec::TST T) {
+  switch (T) {
+  default: assert(0 && "Unknown typespec!");
+  case DeclSpec::TST_unspecified: return "unspecified";
+  case DeclSpec::TST_void:        return "void";
+  case DeclSpec::TST_char:        return "char";
+  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_union:       return "union";
+  case DeclSpec::TST_struct:      return "struct";
+  case DeclSpec::TST_typedef:     return "typedef";
+  }
+}
+
+static bool BadSpecifier(DeclSpec::TST T, const char *&PrevSpec) {
+  PrevSpec = DeclSpec::getSpecifierName(T);
+  return true;
+}
+
+static bool BadSpecifier(DeclSpec::TQ T, const char *&PrevSpec) {
+  switch (T) {
+  case DeclSpec::TQ_unspecified: PrevSpec = "unspecified"; break;
+  case DeclSpec::TQ_const:       PrevSpec = "const"; break;
+  case DeclSpec::TQ_restrict:    PrevSpec = "restrict"; break;
+  case DeclSpec::TQ_volatile:    PrevSpec = "volatile"; break;
+  }
+  return true;
+}
+
+bool DeclSpec::SetStorageClassSpec(SCS S, SourceLocation Loc,
+                                   const char *&PrevSpec) {
+  if (StorageClassSpec != SCS_unspecified)
+    return BadSpecifier(StorageClassSpec, PrevSpec);
+  StorageClassSpec = S;
+  StorageClassSpecLoc = Loc;
+  return false;
+}
+
+bool DeclSpec::SetStorageClassSpecThread(SourceLocation Loc, 
+                                         const char *&PrevSpec) {
+  if (SCS_thread_specified) {
+    PrevSpec = "__thread";
+    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) {
+  if (TypeSpecWidth != TSW_unspecified &&
+      // Allow turning long -> long long.
+      (W != TSW_longlong || TypeSpecWidth != TSW_long))
+    return BadSpecifier(TypeSpecWidth, PrevSpec);
+  TypeSpecWidth = W;
+  TSWLoc = Loc;
+  return false;
+}
+
+bool DeclSpec::SetTypeSpecComplex(TSC C, SourceLocation Loc, 
+                                  const char *&PrevSpec) {
+  if (TypeSpecComplex != TSC_unspecified)
+    return BadSpecifier(TypeSpecComplex, PrevSpec);
+  TypeSpecComplex = C;
+  TSCLoc = Loc;
+  return false;
+}
+
+bool DeclSpec::SetTypeSpecSign(TSS S, SourceLocation Loc, 
+                               const char *&PrevSpec) {
+  if (TypeSpecSign != TSS_unspecified)
+    return BadSpecifier(TypeSpecSign, PrevSpec);
+  TypeSpecSign = S;
+  TSSLoc = Loc;
+  return false;
+}
+
+bool DeclSpec::SetTypeSpecType(TST T, SourceLocation Loc,
+                               const char *&PrevSpec, void *Rep) {
+  if (TypeSpecType != TST_unspecified)
+    return BadSpecifier(TypeSpecType, PrevSpec);
+  TypeSpecType = T;
+  TypeRep = Rep;
+  TSTLoc = Loc;
+  return false;
+}
+
+bool DeclSpec::SetTypeQual(TQ T, SourceLocation Loc, const char *&PrevSpec,
+                           const LangOptions &Lang) {
+  // Duplicates turn into warnings pre-C99.
+  if ((TypeQualifiers & T) && !Lang.C99)
+    return BadSpecifier(T, PrevSpec);
+  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){
+  // 'inline inline' is ok.
+  FS_inline_specified = true;
+  FS_inlineLoc = Loc;
+  return false;
+}
+
+
+/// 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, const LangOptions &Lang) {
+  // Check the type specifier components first.
+
+  // signed/unsigned are only valid with int/char.
+  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) {
+      Diag(D, TSSLoc, diag::err_invalid_sign_spec,
+           getSpecifierName(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,
+           TypeSpecWidth == TSW_short ? diag::err_invalid_short_spec
+                                      : diag::err_invalid_longlong_spec,
+           getSpecifierName(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, diag::err_invalid_long_spec,
+           getSpecifierName(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, diag::ext_plain_complex);
+      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, diag::ext_integer_complex);
+    } else if (TypeSpecType != TST_float && TypeSpecType != TST_double) {
+      Diag(D, TSCLoc, diag::err_invalid_complex_spec, 
+           getSpecifierName(TypeSpecType));
+      TypeSpecComplex = TSC_unspecified;
+    }
+  }
+  
+  // Verify __thread.
+  if (SCS_thread_specified) {
+    if (StorageClassSpec == SCS_unspecified) {
+      StorageClassSpec = SCS_extern; // '__thread int' -> 'extern __thread int'
+    } else if (StorageClassSpec != SCS_extern &&
+               StorageClassSpec != SCS_static) {
+      Diag(D, getStorageClassSpecLoc(), diag::err_invalid_thread_spec,
+           getSpecifierName(StorageClassSpec));
+      SCS_thread_specified = false;
+    }
+  }
+
+  // Okay, now we can infer the real type.
+  // TODO: infer real type.
+  
+  // TODO: return "auto function" and other bad things based on the real type.
+  
+  // 'data definition has no type or storage class'?
+}
diff --git a/Parse/Makefile b/Parse/Makefile
new file mode 100644
index 0000000..60e70f2
--- /dev/null
+++ b/Parse/Makefile
@@ -0,0 +1,22 @@
+##===- clang/Parse/Makefile --------------------------------*- Makefile -*-===##
+# 
+#                     The LLVM Compiler Infrastructure
+#
+# This file was developed by Chris Lattner and 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
+CXXFLAGS = -fno-rtti
+
+CPPFLAGS += -I$(PROJ_SRC_DIR)/../include
+
+include $(LEVEL)/Makefile.common
+
diff --git a/Parse/MinimalAction.cpp b/Parse/MinimalAction.cpp
new file mode 100644
index 0000000..65bdca6
--- /dev/null
+++ b/Parse/MinimalAction.cpp
@@ -0,0 +1,105 @@
+//===--- MinimalAction.cpp - Implement the MinimalAction class ------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file was developed by Chris Lattner and 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"
+using namespace clang;
+
+/// TypeNameInfo - A link exists here for each scope that an identifier is
+/// defined.
+struct TypeNameInfo {
+  TypeNameInfo *Prev;
+  bool isTypeName;
+  
+  TypeNameInfo(bool istypename, TypeNameInfo *prev) {
+    isTypeName = istypename;
+    Prev = prev;
+  }
+};
+
+/// 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.
+Action::DeclTy *
+MinimalAction::isTypeName(const IdentifierInfo &II, Scope *S) const {
+  if (TypeNameInfo *TI = II.getFETokenInfo<TypeNameInfo>())
+    if (TI->isTypeName)
+      return TI;
+  return 0;
+}
+
+/// ParseDeclarator - If this is a typedef declarator, we modify the
+/// IdentifierInfo::FETokenInfo field to keep track of this fact, until S is
+/// popped.
+Action::DeclTy *
+MinimalAction::ParseDeclarator(Scope *S, Declarator &D, ExprTy *Init,
+                               DeclTy *LastInGroup) {
+  IdentifierInfo *II = D.getIdentifier();
+  
+  // If there is no identifier associated with this declarator, bail out.
+  if (II == 0) return 0;
+  
+  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) {
+    TypeNameInfo *TI = new TypeNameInfo(isTypeName, weCurrentlyHaveTypeInfo);
+
+    II->setFETokenInfo(TI);
+  
+    // Remember that this needs to be removed when the scope is popped.
+    S->AddDecl(II);
+  } 
+  return 0;
+}
+
+/// ParsedObjcClassDeclaration - 
+/// Scope will always be top level file scope. 
+Action::DeclTy *
+MinimalAction::ParsedObjcClassDeclaration(Scope *S,
+                                          IdentifierInfo **IdentList,
+                                          unsigned NumElts) {
+  for (unsigned i = 0; i != NumElts; ++i) {
+    TypeNameInfo *TI =
+      new TypeNameInfo(1, IdentList[i]->getFETokenInfo<TypeNameInfo>());
+
+    IdentList[i]->setFETokenInfo(TI);
+  
+    // Remember that this needs to be removed when the scope is popped.
+    S->AddDecl(IdentList[i]);
+  }
+  return 0;
+}
+
+/// PopScope - When a scope is popped, if any typedefs are now out-of-scope,
+/// they are removed from the IdentifierInfo::FETokenInfo field.
+void MinimalAction::PopScope(SourceLocation Loc, Scope *S) {
+  for (Scope::decl_iterator I = S->decl_begin(), E = S->decl_end();
+       I != E; ++I) {
+    IdentifierInfo &II = *static_cast<IdentifierInfo*>(*I);
+    TypeNameInfo *TI = II.getFETokenInfo<TypeNameInfo>();
+    assert(TI && "This decl didn't get pushed??");
+    
+    if (TI) {
+      TypeNameInfo *Next = TI->Prev;
+      delete TI;
+      
+      II.setFETokenInfo(Next);
+    }
+  }
+}
diff --git a/Parse/ParseDecl.cpp b/Parse/ParseDecl.cpp
new file mode 100644
index 0000000..02a79e6
--- /dev/null
+++ b/Parse/ParseDecl.cpp
@@ -0,0 +1,1396 @@
+//===--- ParseDecl.cpp - Declaration Parsing ------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file was developed by Chris Lattner and 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/DeclSpec.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]
+Parser::TypeTy *Parser::ParseTypeName() {
+  // Parse the common declaration-specifiers piece.
+  DeclSpec DS;
+  ParseSpecifierQualifierList(DS);
+  
+  // Parse the abstract-declarator, if present.
+  Declarator DeclaratorInfo(DS, Declarator::TypeNameContext);
+  ParseDeclarator(DeclaratorInfo);
+  
+  return Actions.ParseTypeName(CurScope, DeclaratorInfo).Val;
+}
+
+/// ParseAttributes - 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::ParseAttributes() {
+  assert(Tok.getKind() == tok::kw___attribute && "Not an attribute list!");
+  
+  AttributeList *CurrAttr = 0;
+  
+  while (Tok.getKind() == 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.getKind() == tok::identifier || isDeclarationSpecifier() ||
+           Tok.getKind() == tok::comma) {
+           
+      if (Tok.getKind() == 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.getKind() == tok::l_paren) {
+        ConsumeParen(); // ignore the left paren loc for now
+        
+        if (Tok.getKind() == tok::identifier) {
+          IdentifierInfo *ParmName = Tok.getIdentifierInfo();
+          SourceLocation ParmLoc = ConsumeToken();
+          
+          if (Tok.getKind() == tok::r_paren) { 
+            // __attribute__(( mode(byte) ))
+            ConsumeParen(); // ignore the right paren loc for now
+            CurrAttr = new AttributeList(AttrName, AttrNameLoc, 
+                                         ParmName, ParmLoc, 0, 0, CurrAttr);
+          } else if (Tok.getKind() == tok::comma) {
+            ConsumeToken();
+            // __attribute__(( format(printf, 1, 2) ))
+            llvm::SmallVector<ExprTy*, 8> ArgExprs;
+            bool ArgExprsOk = true;
+            
+            // now parse the non-empty comma separated list of expressions
+            while (1) {
+              ExprResult ArgExpr = ParseAssignmentExpression();
+              if (ArgExpr.isInvalid) {
+                ArgExprsOk = false;
+                SkipUntil(tok::r_paren);
+                break;
+              } else {
+                ArgExprs.push_back(ArgExpr.Val);
+              }
+              if (Tok.getKind() != tok::comma)
+                break;
+              ConsumeToken(); // Eat the comma, move to the next argument
+            }
+            if (ArgExprsOk && Tok.getKind() == tok::r_paren) {
+              ConsumeParen(); // ignore the right paren loc for now
+              CurrAttr = new AttributeList(AttrName, AttrNameLoc, ParmName, 
+                           ParmLoc, &ArgExprs[0], ArgExprs.size(), CurrAttr);
+            }
+          }
+        } else { // not an identifier
+          // parse a possibly empty comma separated list of expressions
+          if (Tok.getKind() == tok::r_paren) { 
+            // __attribute__(( nonnull() ))
+            ConsumeParen(); // ignore the right paren loc for now
+            CurrAttr = new AttributeList(AttrName, AttrNameLoc, 
+                                         0, SourceLocation(), 0, 0, CurrAttr);
+          } else { 
+            // __attribute__(( aligned(16) ))
+            llvm::SmallVector<ExprTy*, 8> ArgExprs;
+            bool ArgExprsOk = true;
+            
+            // now parse the list of expressions
+            while (1) {
+              ExprResult ArgExpr = ParseAssignmentExpression();
+              if (ArgExpr.isInvalid) {
+                ArgExprsOk = false;
+                SkipUntil(tok::r_paren);
+                break;
+              } else {
+                ArgExprs.push_back(ArgExpr.Val);
+              }
+              if (Tok.getKind() != tok::comma)
+                break;
+              ConsumeToken(); // Eat the comma, move to the next argument
+            }
+            // Match the ')'.
+            if (ArgExprsOk && Tok.getKind() == tok::r_paren) {
+              ConsumeParen(); // ignore the right paren loc for now
+              CurrAttr = new AttributeList(AttrName, AttrNameLoc, 0, 
+                           SourceLocation(), &ArgExprs[0], ArgExprs.size(), 
+                           CurrAttr);
+            }
+          }
+        }
+      } else {
+        CurrAttr = new AttributeList(AttrName, AttrNameLoc, 
+                                     0, SourceLocation(), 0, 0, CurrAttr);
+      }
+    }
+    if (ExpectAndConsume(tok::r_paren, diag::err_expected_rparen))
+      SkipUntil(tok::r_paren, false); 
+    if (ExpectAndConsume(tok::r_paren, diag::err_expected_rparen))
+      SkipUntil(tok::r_paren, false);
+  }
+  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.
+Parser::DeclTy *Parser::ParseDeclaration(unsigned Context) {
+  // Parse the common declaration-specifiers piece.
+  DeclSpec DS;
+  ParseDeclarationSpecifiers(DS);
+  
+  // C99 6.7.2.3p6: Handle "struct-or-union identifier;", "enum { X };"
+  // declaration-specifiers init-declarator-list[opt] ';'
+  if (Tok.getKind() == tok::semi) {
+    ConsumeToken();
+    return Actions.ParsedFreeStandingDeclSpec(CurScope, DS);
+  }
+  
+  Declarator DeclaratorInfo(DS, (Declarator::TheContext)Context);
+  ParseDeclarator(DeclaratorInfo);
+  
+  return ParseInitDeclaratorListAfterFirstDeclarator(DeclaratorInfo);
+}
+
+/// ParseInitDeclaratorListAfterFirstDeclarator - Parse 'declaration' after
+/// parsing 'declaration-specifiers declarator'.  This method is split out this
+/// way to handle the ambiguity between top-level function-definitions and
+/// declarations.
+///
+///       declaration: [C99 6.7]
+///         declaration-specifiers init-declarator-list[opt] ';' [TODO]
+/// [!C99]  init-declarator-list ';'                             [TODO]
+/// [OMP]   threadprivate-directive                              [TODO]
+///
+///       init-declarator-list: [C99 6.7]
+///         init-declarator
+///         init-declarator-list ',' init-declarator
+///       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
+///
+Parser::DeclTy *Parser::
+ParseInitDeclaratorListAfterFirstDeclarator(Declarator &D) {
+  
+  // Declarators may be grouped together ("int X, *Y, Z();").  Provide info so
+  // that they can be chained properly if the actions want this.
+  Parser::DeclTy *LastDeclInGroup = 0;
+  
+  // At this point, we know that it is not a function definition.  Parse the
+  // rest of the init-declarator-list.
+  while (1) {
+    // If a simple-asm-expr is present, parse it.
+    if (Tok.getKind() == tok::kw_asm)
+      ParseSimpleAsm();
+    
+    // If attributes are present, parse them.
+    if (Tok.getKind() == tok::kw___attribute)
+      D.AddAttributes(ParseAttributes());
+    
+    // Parse declarator '=' initializer.
+    ExprResult Init;
+    if (Tok.getKind() == tok::equal) {
+      ConsumeToken();
+      Init = ParseInitializer();
+      if (Init.isInvalid) {
+        SkipUntil(tok::semi);
+        return 0;
+      }
+    }
+    
+    // Inform the current actions module that we just parsed this declarator.
+    // FIXME: pass asm & attributes.
+    LastDeclInGroup = Actions.ParseDeclarator(CurScope, D, Init.Val,
+                                              LastDeclInGroup);
+    
+    // If we don't have a comma, it is either the end of the list (a ';') or an
+    // error, bail out.
+    if (Tok.getKind() != tok::comma)
+      break;
+    
+    // Consume the comma.
+    ConsumeToken();
+    
+    // Parse the next declarator.
+    D.clear();
+    ParseDeclarator(D);
+  }
+  
+  if (Tok.getKind() == tok::semi) {
+    ConsumeToken();
+    return Actions.FinalizeDeclaratorGroup(CurScope, LastDeclInGroup);
+  }
+  
+  Diag(Tok, diag::err_parse_error);
+  // Skip to end of block or statement
+  SkipUntil(tok::r_brace, true);
+  if (Tok.getKind() == tok::semi)
+    ConsumeToken();
+  return 0;
+}
+
+/// 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.
+  SourceLocation Loc = Tok.getLocation();
+  ParseDeclarationSpecifiers(DS);
+  
+  // Validate declspec for type-name.
+  unsigned Specs = DS.getParsedSpecifiers();
+  if (Specs == DeclSpec::PQ_None)
+    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) {
+    Diag(DS.getInlineSpecLoc(), diag::err_typename_invalid_functionspec);
+    DS.ClearFunctionSpecs();
+  }
+}
+
+/// ParseDeclarationSpecifiers
+///       declaration-specifiers: [C99 6.7]
+///         storage-class-specifier declaration-specifiers[opt]
+///         type-specifier declaration-specifiers[opt]
+///         type-qualifier 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'
+/// [GNU]   '__thread'
+///       type-specifier: [C99 6.7.2]
+///         'void'
+///         'char'
+///         'short'
+///         'int'
+///         'long'
+///         'float'
+///         'double'
+///         'signed'
+///         'unsigned'
+///         struct-or-union-specifier
+///         enum-specifier
+///         typedef-name
+/// [C++]   'bool'
+/// [C99]   '_Bool'
+/// [C99]   '_Complex'
+/// [C99]   '_Imaginary'  // Removed in TC2?
+/// [GNU]   '_Decimal32'
+/// [GNU]   '_Decimal64'
+/// [GNU]   '_Decimal128'
+/// [GNU]   typeof-specifier                      [TODO]
+/// [OBJC]  class-name objc-protocol-refs[opt]    [TODO]
+/// [OBJC]  typedef-name objc-protocol-refs       [TODO]
+/// [OBJC]  objc-protocol-refs                    [TODO]
+///       type-qualifier:
+///         'const'
+///         'volatile'
+/// [C99]   'restrict'
+///       function-specifier: [C99 6.7.4]
+/// [C99]   'inline'
+///
+void Parser::ParseDeclarationSpecifiers(DeclSpec &DS) {
+  while (1) {
+    int isInvalid = false;
+    const char *PrevSpec = 0;
+    SourceLocation Loc = Tok.getLocation();
+    
+    switch (Tok.getKind()) {
+      // typedef-name
+    case tok::identifier:
+      // 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()) {
+        // It has to be available as a typedef too!
+        if (void *TypeRep = Actions.isTypeName(*Tok.getIdentifierInfo(),
+                                               CurScope)) {
+          isInvalid = DS.SetTypeSpecType(DeclSpec::TST_typedef, Loc, PrevSpec,
+                                         TypeRep);
+          break;
+        }
+      }
+      // FALL THROUGH.
+    default:
+      // If this is not a declaration specifier token, we're done reading decl
+      // specifiers.  First verify that DeclSpec's are consistent.
+      DS.Finish(Diags, getLang());
+      return;
+    
+    // GNU attributes support.
+    case tok::kw___attribute:
+      DS.AddAttributes(ParseAttributes());
+      continue;
+      
+    // storage-class-specifier
+    case tok::kw_typedef:
+      isInvalid = DS.SetStorageClassSpec(DeclSpec::SCS_typedef, Loc, PrevSpec);
+      break;
+    case tok::kw_extern:
+      if (DS.isThreadSpecified())
+        Diag(Tok, diag::ext_thread_before, "extern");
+      isInvalid = DS.SetStorageClassSpec(DeclSpec::SCS_extern, Loc, PrevSpec);
+      break;
+    case tok::kw_static:
+      if (DS.isThreadSpecified())
+        Diag(Tok, diag::ext_thread_before, "static");
+      isInvalid = DS.SetStorageClassSpec(DeclSpec::SCS_static, Loc, PrevSpec);
+      break;
+    case tok::kw_auto:
+      isInvalid = DS.SetStorageClassSpec(DeclSpec::SCS_auto, Loc, PrevSpec);
+      break;
+    case tok::kw_register:
+      isInvalid = DS.SetStorageClassSpec(DeclSpec::SCS_register, Loc, PrevSpec);
+      break;
+    case tok::kw___thread:
+      isInvalid = DS.SetStorageClassSpecThread(Loc, PrevSpec)*2;
+      break;
+      
+    // type-specifiers
+    case tok::kw_short:
+      isInvalid = DS.SetTypeSpecWidth(DeclSpec::TSW_short, Loc, PrevSpec);
+      break;
+    case tok::kw_long:
+      if (DS.getTypeSpecWidth() != DeclSpec::TSW_long)
+        isInvalid = DS.SetTypeSpecWidth(DeclSpec::TSW_long, Loc, PrevSpec);
+      else
+        isInvalid = DS.SetTypeSpecWidth(DeclSpec::TSW_longlong, Loc, PrevSpec);
+      break;
+    case tok::kw_signed:
+      isInvalid = DS.SetTypeSpecSign(DeclSpec::TSS_signed, Loc, PrevSpec);
+      break;
+    case tok::kw_unsigned:
+      isInvalid = DS.SetTypeSpecSign(DeclSpec::TSS_unsigned, Loc, PrevSpec);
+      break;
+    case tok::kw__Complex:
+      isInvalid = DS.SetTypeSpecComplex(DeclSpec::TSC_complex, Loc, PrevSpec);
+      break;
+    case tok::kw__Imaginary:
+      isInvalid = DS.SetTypeSpecComplex(DeclSpec::TSC_imaginary, Loc, PrevSpec);
+      break;
+    case tok::kw_void:
+      isInvalid = DS.SetTypeSpecType(DeclSpec::TST_void, Loc, PrevSpec);
+      break;
+    case tok::kw_char:
+      isInvalid = DS.SetTypeSpecType(DeclSpec::TST_char, Loc, PrevSpec);
+      break;
+    case tok::kw_int:
+      isInvalid = DS.SetTypeSpecType(DeclSpec::TST_int, Loc, PrevSpec);
+      break;
+    case tok::kw_float:
+      isInvalid = DS.SetTypeSpecType(DeclSpec::TST_float, Loc, PrevSpec);
+      break;
+    case tok::kw_double:
+      isInvalid = DS.SetTypeSpecType(DeclSpec::TST_double, Loc, PrevSpec);
+      break;
+    case tok::kw_bool:          // [C++ 2.11p1]
+    case tok::kw__Bool:
+      isInvalid = DS.SetTypeSpecType(DeclSpec::TST_bool, Loc, PrevSpec);
+      break;
+    case tok::kw__Decimal32:
+      isInvalid = DS.SetTypeSpecType(DeclSpec::TST_decimal32, Loc, PrevSpec);
+      break;
+    case tok::kw__Decimal64:
+      isInvalid = DS.SetTypeSpecType(DeclSpec::TST_decimal64, Loc, PrevSpec);
+      break;
+    case tok::kw__Decimal128:
+      isInvalid = DS.SetTypeSpecType(DeclSpec::TST_decimal128, Loc, PrevSpec);
+      break;
+      
+    case tok::kw_struct:
+    case tok::kw_union:
+      ParseStructUnionSpecifier(DS);
+      continue;
+    case tok::kw_enum:
+      ParseEnumSpecifier(DS);
+      continue;
+    
+    // type-qualifier
+    case tok::kw_const:
+      isInvalid = DS.SetTypeQual(DeclSpec::TQ_const   , Loc, PrevSpec,
+                                 getLang())*2;
+      break;
+    case tok::kw_volatile:
+      isInvalid = DS.SetTypeQual(DeclSpec::TQ_volatile, Loc, PrevSpec,
+                                 getLang())*2;
+      break;
+    case tok::kw_restrict:
+      isInvalid = DS.SetTypeQual(DeclSpec::TQ_restrict, Loc, PrevSpec,
+                                 getLang())*2;
+      break;
+      
+    // function-specifier
+    case tok::kw_inline:
+      isInvalid = DS.SetFunctionSpecInline(Loc, PrevSpec);
+      break;
+    }
+    // If the specifier combination wasn't legal, issue a diagnostic.
+    if (isInvalid) {
+      assert(PrevSpec && "Method did not return previous specifier!");
+      if (isInvalid == 1)  // Error.
+        Diag(Tok, diag::err_invalid_decl_spec_combination, PrevSpec);
+      else                 // extwarn.
+        Diag(Tok, diag::ext_duplicate_declspec, PrevSpec);
+    }
+    ConsumeToken();
+  }
+}
+
+/// ParseTag - Parse "struct-or-union-or-class-or-enum identifier[opt]", where
+/// the first token has already been read and has been turned into an instance
+/// of DeclSpec::TST (TagType).  This returns true if there is an error parsing,
+/// otherwise it returns false and fills in Decl.
+bool Parser::ParseTag(DeclTy *&Decl, unsigned TagType, SourceLocation StartLoc){
+  AttributeList *Attr = 0;
+  // If attributes exist after tag, parse them.
+  if (Tok.getKind() == tok::kw___attribute)
+    Attr = ParseAttributes();
+  
+  // Must have either 'struct name' or 'struct {...}'.
+  if (Tok.getKind() != tok::identifier &&
+      Tok.getKind() != tok::l_brace) {
+    Diag(Tok, diag::err_expected_ident_lbrace);
+    // TODO: better error recovery here.
+    return true;
+  }
+  
+  // If an identifier is present, consume and remember it.
+  IdentifierInfo *Name = 0;
+  SourceLocation NameLoc;
+  if (Tok.getKind() == tok::identifier) {
+    Name = Tok.getIdentifierInfo();
+    NameLoc = ConsumeToken();
+  }
+  
+  // There are three options here.  If we have 'struct foo;', then this is a
+  // forward declaration.  If we have 'struct foo {...' then this is a
+  // definition. Otherwise we have something like 'struct foo xyz', a reference.
+  //
+  // This is needed to handle stuff like this right (C99 6.7.2.3p11):
+  // struct foo {..};  void bar() { struct foo; }    <- new foo in bar.
+  // struct foo {..};  void bar() { struct foo x; }  <- use of old foo.
+  //
+  Action::TagKind TK;
+  if (Tok.getKind() == tok::l_brace)
+    TK = Action::TK_Definition;
+  else if (Tok.getKind() == tok::semi)
+    TK = Action::TK_Declaration;
+  else
+    TK = Action::TK_Reference;
+  Decl = Actions.ParseTag(CurScope, TagType, TK, StartLoc, Name, NameLoc, Attr);
+  return false;
+}
+
+
+/// ParseStructUnionSpecifier
+///       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::ParseStructUnionSpecifier(DeclSpec &DS) {
+  assert((Tok.getKind() == tok::kw_struct ||
+          Tok.getKind() == tok::kw_union) && "Not a struct/union specifier");
+  DeclSpec::TST TagType =
+    Tok.getKind() == tok::kw_union ? DeclSpec::TST_union : DeclSpec::TST_struct;
+  SourceLocation StartLoc = ConsumeToken();
+
+  // Parse the tag portion of this.
+  DeclTy *TagDecl;
+  if (ParseTag(TagDecl, TagType, StartLoc))
+    return;
+  
+  // If there is a body, parse it and inform the actions module.
+  if (Tok.getKind() == tok::l_brace)
+    ParseStructUnionBody(StartLoc, TagType, TagDecl);
+
+  const char *PrevSpec = 0;
+  if (DS.SetTypeSpecType(TagType, StartLoc, PrevSpec, TagDecl))
+    Diag(StartLoc, diag::err_invalid_decl_spec_combination, PrevSpec);
+}
+
+
+/// 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 ')'                         [TODO]
+///       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::ParseStructUnionBody(SourceLocation RecordLoc,
+                                  unsigned TagType, DeclTy *TagDecl) {
+  SourceLocation LBraceLoc = ConsumeBrace();
+  
+  // Empty structs are an extension in C (C99 6.7.2.1p7), but are allowed in
+  // C++.
+  if (Tok.getKind() == tok::r_brace)
+    Diag(Tok, diag::ext_empty_struct_union_enum, 
+         DeclSpec::getSpecifierName((DeclSpec::TST)TagType));
+
+  llvm::SmallVector<DeclTy*, 32> FieldDecls;
+  
+  // While we still have something to read, read the declarations in the struct.
+  while (Tok.getKind() != tok::r_brace && 
+         Tok.getKind() != tok::eof) {
+    // Each iteration of this loop reads one struct-declaration.
+    
+    // Check for extraneous top-level semicolon.
+    if (Tok.getKind() == tok::semi) {
+      Diag(Tok, diag::ext_extra_struct_semi);
+      ConsumeToken();
+      continue;
+    }
+
+    // FIXME: When __extension__ is specified, disable extension diagnostics.
+    if (Tok.getKind() == tok::kw___extension__)
+      ConsumeToken();
+    
+    // Parse the common specifier-qualifiers-list piece.
+    DeclSpec DS;
+    SourceLocation SpecQualLoc = Tok.getLocation();
+    ParseSpecifierQualifierList(DS);
+    // TODO: Does specifier-qualifier list correctly check that *something* is
+    // specified?
+    
+    // If there are no declarators, issue a warning.
+    if (Tok.getKind() == tok::semi) {
+      Diag(SpecQualLoc, diag::w_no_declarators);
+      ConsumeToken();
+      continue;
+    }
+
+    // Read struct-declarators until we find the semicolon.
+    Declarator DeclaratorInfo(DS, Declarator::MemberContext);
+
+    while (1) {
+      /// struct-declarator: declarator
+      /// struct-declarator: declarator[opt] ':' constant-expression
+      if (Tok.getKind() != tok::colon)
+        ParseDeclarator(DeclaratorInfo);
+      
+      ExprTy *BitfieldSize = 0;
+      if (Tok.getKind() == tok::colon) {
+        ConsumeToken();
+        ExprResult Res = ParseConstantExpression();
+        if (Res.isInvalid) {
+          SkipUntil(tok::semi, true, true);
+        } else {
+          BitfieldSize = Res.Val;
+        }
+      }
+      
+      // If attributes exist after the declarator, parse them.
+      if (Tok.getKind() == tok::kw___attribute)
+        DeclaratorInfo.AddAttributes(ParseAttributes());
+      
+      // Install the declarator into the current TagDecl.
+      DeclTy *Field = Actions.ParseField(CurScope, TagDecl, SpecQualLoc,
+                                         DeclaratorInfo, BitfieldSize);
+      FieldDecls.push_back(Field);
+      
+      // If we don't have a comma, it is either the end of the list (a ';')
+      // or an error, bail out.
+      if (Tok.getKind() != tok::comma)
+        break;
+      
+      // Consume the comma.
+      ConsumeToken();
+      
+      // Parse the next declarator.
+      DeclaratorInfo.clear();
+      
+      // Attributes are only allowed on the second declarator.
+      if (Tok.getKind() == tok::kw___attribute)
+        DeclaratorInfo.AddAttributes(ParseAttributes());
+    }
+    
+    if (Tok.getKind() == tok::semi) {
+      ConsumeToken();
+    } else if (Tok.getKind() == tok::r_brace) {
+      Diag(Tok.getLocation(), diag::ext_expected_semi_decl_list);
+      break;
+    } else {
+      Diag(Tok, diag::err_expected_semi_decl_list);
+      // Skip to end of block or statement
+      SkipUntil(tok::r_brace, true, true);
+    }
+  }
+  
+  MatchRHSPunctuation(tok::r_brace, LBraceLoc);
+  
+  Actions.ParseRecordBody(RecordLoc, TagDecl, &FieldDecls[0],FieldDecls.size());
+  
+  AttributeList *AttrList = 0;
+  // If attributes exist after struct contents, parse them.
+  if (Tok.getKind() == tok::kw___attribute)
+    AttrList = ParseAttributes(); // FIXME: where should I put them?
+}
+
+
+/// ParseEnumSpecifier
+///       enum-specifier: [C99 6.7.2.2]
+///         'enum' identifier[opt] '{' enumerator-list '}'
+/// [C99]   'enum' identifier[opt] '{' enumerator-list ',' '}'
+/// [GNU]   'enum' attributes[opt] identifier[opt] '{' enumerator-list ',' [opt]
+///                                                 '}' attributes[opt]
+///         'enum' identifier
+/// [GNU]   'enum' attributes[opt] identifier
+void Parser::ParseEnumSpecifier(DeclSpec &DS) {
+  assert(Tok.getKind() == tok::kw_enum && "Not an enum specifier");
+  SourceLocation StartLoc = ConsumeToken();
+  
+  // Parse the tag portion of this.
+  DeclTy *TagDecl;
+  if (ParseTag(TagDecl, DeclSpec::TST_enum, StartLoc))
+    return;
+  
+  if (Tok.getKind() == tok::l_brace)
+    ParseEnumBody(StartLoc, TagDecl);
+  
+  // TODO: semantic analysis on the declspec for enums.
+  const char *PrevSpec = 0;
+  if (DS.SetTypeSpecType(DeclSpec::TST_enum, StartLoc, PrevSpec, TagDecl))
+    Diag(StartLoc, diag::err_invalid_decl_spec_combination, 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, DeclTy *EnumDecl) {
+  SourceLocation LBraceLoc = ConsumeBrace();
+  
+  if (Tok.getKind() == tok::r_brace)
+    Diag(Tok, diag::ext_empty_struct_union_enum, "enum");
+  
+  llvm::SmallVector<DeclTy*, 32> EnumConstantDecls;
+
+  DeclTy *LastEnumConstDecl = 0;
+  
+  // Parse the enumerator-list.
+  while (Tok.getKind() == tok::identifier) {
+    IdentifierInfo *Ident = Tok.getIdentifierInfo();
+    SourceLocation IdentLoc = ConsumeToken();
+    
+    SourceLocation EqualLoc;
+    ExprTy *AssignedVal = 0;
+    if (Tok.getKind() == tok::equal) {
+      EqualLoc = ConsumeToken();
+      ExprResult Res = ParseConstantExpression();
+      if (Res.isInvalid)
+        SkipUntil(tok::comma, tok::r_brace, true, true);
+      else
+        AssignedVal = Res.Val;
+    }
+    
+    // Install the enumerator constant into EnumDecl.
+    DeclTy *EnumConstDecl = Actions.ParseEnumConstant(CurScope, EnumDecl,
+                                                      LastEnumConstDecl,
+                                                      IdentLoc, Ident,
+                                                      EqualLoc, AssignedVal);
+    EnumConstantDecls.push_back(EnumConstDecl);
+    LastEnumConstDecl = EnumConstDecl;
+    
+    if (Tok.getKind() != tok::comma)
+      break;
+    SourceLocation CommaLoc = ConsumeToken();
+    
+    if (Tok.getKind() != tok::identifier && !getLang().C99)
+      Diag(CommaLoc, diag::ext_c99_enumerator_list_comma);
+  }
+  
+  // Eat the }.
+  MatchRHSPunctuation(tok::r_brace, LBraceLoc);
+
+  Actions.ParseEnumBody(StartLoc, EnumDecl, &EnumConstantDecls[0],
+                        EnumConstantDecls.size());
+  
+  DeclTy *AttrList = 0;
+  // If attributes exist after the identifier list, parse them.
+  if (Tok.getKind() == tok::kw___attribute)
+    AttrList = ParseAttributes(); // FIXME: where do they do?
+}
+
+/// isTypeSpecifierQualifier - Return true if the current token could be the
+/// start of a specifier-qualifier-list.
+bool Parser::isTypeSpecifierQualifier() const {
+  switch (Tok.getKind()) {
+  default: return false;
+    // GNU attributes support.
+  case tok::kw___attribute:
+    // 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_int:
+  case tok::kw_float:
+  case tok::kw_double:
+  case tok::kw__Bool:
+  case tok::kw__Decimal32:
+  case tok::kw__Decimal64:
+  case tok::kw__Decimal128:
+    
+    // struct-or-union-specifier
+  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:
+    return true;
+    
+    // typedef-name
+  case tok::identifier:
+    return Actions.isTypeName(*Tok.getIdentifierInfo(), CurScope) != 0;
+    
+    // TODO: Attributes.
+  }
+}
+
+/// isDeclarationSpecifier() - Return true if the current token is part of a
+/// declaration specifier.
+bool Parser::isDeclarationSpecifier() const {
+  switch (Tok.getKind()) {
+  default: return false;
+    // storage-class-specifier
+  case tok::kw_typedef:
+  case tok::kw_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_int:
+  case tok::kw_float:
+  case tok::kw_double:
+  case tok::kw__Bool:
+  case tok::kw__Decimal32:
+  case tok::kw__Decimal64:
+  case tok::kw__Decimal128:
+  
+    // struct-or-union-specifier
+  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:
+    return true;
+    
+    // typedef-name
+  case tok::identifier:
+    return Actions.isTypeName(*Tok.getIdentifierInfo(), CurScope) != 0;
+    // TODO: Attributes.
+  }
+}
+
+
+/// ParseTypeQualifierListOpt
+///       type-qualifier-list: [C99 6.7.5]
+///         type-qualifier
+/// [GNU]   attributes
+///         type-qualifier-list type-qualifier
+/// [GNU]   type-qualifier-list attributes
+///
+void Parser::ParseTypeQualifierListOpt(DeclSpec &DS) {
+  while (1) {
+    int isInvalid = false;
+    const char *PrevSpec = 0;
+    SourceLocation Loc = Tok.getLocation();
+
+    switch (Tok.getKind()) {
+    default:
+      // If this is not a type-qualifier token, we're done reading type
+      // qualifiers.  First verify that DeclSpec's are consistent.
+      DS.Finish(Diags, getLang());
+      return;
+    case tok::kw_const:
+      isInvalid = DS.SetTypeQual(DeclSpec::TQ_const   , Loc, PrevSpec,
+                                 getLang())*2;
+      break;
+    case tok::kw_volatile:
+      isInvalid = DS.SetTypeQual(DeclSpec::TQ_volatile, Loc, PrevSpec,
+                                 getLang())*2;
+      break;
+    case tok::kw_restrict:
+      isInvalid = DS.SetTypeQual(DeclSpec::TQ_restrict, Loc, PrevSpec,
+                                 getLang())*2;
+      break;
+    case tok::kw___attribute:
+      DS.AddAttributes(ParseAttributes());
+      continue; // do *not* consume the next token!
+    }
+    
+    // If the specifier combination wasn't legal, issue a diagnostic.
+    if (isInvalid) {
+      assert(PrevSpec && "Method did not return previous specifier!");
+      if (isInvalid == 1)  // Error.
+        Diag(Tok, diag::err_invalid_decl_spec_combination, PrevSpec);
+      else                 // extwarn.
+        Diag(Tok, diag::ext_duplicate_declspec, 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);
+  
+  // TODO: validate D.
+
+}
+
+/// ParseDeclaratorInternal
+///       declarator: [C99 6.7.5]
+///         pointer[opt] direct-declarator
+/// [C++]   '&' declarator [C++ 8p4, dcl.decl]
+/// [GNU]   '&' restrict[opt] attributes[opt] declarator
+///
+///       pointer: [C99 6.7.5]
+///         '*' type-qualifier-list[opt]
+///         '*' type-qualifier-list[opt] pointer
+///
+void Parser::ParseDeclaratorInternal(Declarator &D) {
+  tok::TokenKind Kind = Tok.getKind();
+
+  // Not a pointer or C++ reference.
+  if (Kind != tok::star && !(Kind == tok::amp && getLang().CPlusPlus))
+    return ParseDirectDeclarator(D);
+  
+  // Otherwise, '*' -> pointer or '&' -> reference.
+  SourceLocation Loc = ConsumeToken();  // Eat the * or &.
+
+  if (Kind == tok::star) {
+    // Is a pointer
+    DeclSpec DS;
+    
+    ParseTypeQualifierListOpt(DS);
+  
+    // Recursively parse the declarator.
+    ParseDeclaratorInternal(D);
+
+    // Remember that we parsed a pointer type, and remember the type-quals.
+    D.AddTypeInfo(DeclaratorChunk::getPointer(DS.getTypeQualifiers(), Loc));
+  } else {
+    // Is a reference
+    DeclSpec DS;
+
+    // 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.
+    ParseTypeQualifierListOpt(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);
+
+    // Remember that we parsed a reference type. It doesn't have type-quals.
+    D.AddTypeInfo(DeclaratorChunk::getReference(DS.getTypeQualifiers(), Loc));
+  }
+}
+
+/// ParseDirectDeclarator
+///       direct-declarator: [C99 6.7.5]
+///         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] ')'
+///
+void Parser::ParseDirectDeclarator(Declarator &D) {
+  // Parse the first direct-declarator seen.
+  if (Tok.getKind() == tok::identifier && D.mayHaveIdentifier()) {
+    assert(Tok.getIdentifierInfo() && "Not an identifier?");
+    D.SetIdentifier(Tok.getIdentifierInfo(), Tok.getLocation());
+    ConsumeToken();
+  } else if (Tok.getKind() == tok::l_paren) {
+    // direct-declarator: '(' declarator ')'
+    // direct-declarator: '(' attributes declarator ')'
+    // Example: 'char (*X)'   or 'int (*XX)(void)'
+    ParseParenDeclarator(D);
+  } 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 {
+    // Expected identifier or '('.
+    Diag(Tok, diag::err_expected_ident_lparen);
+    D.SetIdentifier(0, Tok.getLocation());
+  }
+  
+  assert(D.isPastIdentifier() &&
+         "Haven't past the location of the identifier yet?");
+  
+  while (1) {
+    if (Tok.getKind() == tok::l_paren) {
+      ParseParenDeclarator(D);
+    } else if (Tok.getKind() == tok::l_square) {
+      ParseBracketDeclarator(D);
+    } else {
+      break;
+    }
+  }
+}
+
+/// ParseParenDeclarator - We parsed the declarator D up to a paren.  This may
+/// either be before the identifier (in which case these are just grouping
+/// parens for precedence) or it may be after the identifier, in which case
+/// these are function arguments.
+///
+/// This method also handles this portion of the grammar:
+///       parameter-type-list: [C99 6.7.5]
+///         parameter-list
+///         parameter-list ',' '...'
+///
+///       parameter-list: [C99 6.7.5]
+///         parameter-declaration
+///         parameter-list ',' parameter-declaration
+///
+///       parameter-declaration: [C99 6.7.5]
+///         declaration-specifiers declarator
+/// [GNU]   declaration-specifiers declarator attributes
+///         declaration-specifiers abstract-declarator[opt] 
+/// [GNU]   declaration-specifiers abstract-declarator[opt] attributes
+///
+///       identifier-list: [C99 6.7.5]
+///         identifier
+///         identifier-list ',' identifier
+///
+void Parser::ParseParenDeclarator(Declarator &D) {
+  SourceLocation StartLoc = ConsumeParen();
+  
+  // 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.
+  if (!D.isPastIdentifier()) {
+    // Okay, this is probably a grouping paren.  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.getKind() == tok::r_paren ||  // 'int()' is a function.
+               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) {
+      if (Tok.getKind() == tok::kw___attribute)
+        D.AddAttributes(ParseAttributes());
+      
+      ParseDeclaratorInternal(D);
+      // Match the ')'.
+      MatchRHSPunctuation(tok::r_paren, StartLoc);
+      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 fall through to
+    // the handling of argument lists.
+    D.SetIdentifier(0, Tok.getLocation());
+  }
+  
+  // Okay, this is the parameter list of a function definition, or it is an
+  // identifier list of a K&R-style function.
+  bool IsVariadic;
+  bool HasPrototype;
+  bool ErrorEmitted = false;
+
+  // Build up an array of information about the parsed arguments.
+  llvm::SmallVector<DeclaratorChunk::ParamInfo, 16> ParamInfo;
+  llvm::SmallSet<const IdentifierInfo*, 16> ParamsSoFar;
+  
+  if (Tok.getKind() == tok::r_paren) {
+    // int() -> no prototype, no '...'.
+    IsVariadic   = false;
+    HasPrototype = false;
+  } else if (Tok.getKind() == tok::identifier &&
+             // K&R identifier lists can't have typedefs as identifiers, per
+             // C99 6.7.5.3p11.
+             !Actions.isTypeName(*Tok.getIdentifierInfo(), CurScope)) {
+    // Identifier list.  Note that '(' identifier-list ')' is only allowed for
+    // normal declarators, not for abstract-declarators.
+    assert(D.isPastIdentifier() && "Identifier (if present) must be passed!");
+    
+    // If there was no identifier specified, 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);
+
+    // Remember this identifier in ParamInfo.
+    ParamInfo.push_back(DeclaratorChunk::ParamInfo(Tok.getIdentifierInfo(),
+                                                   Tok.getLocation(), 0));
+
+    ConsumeToken();
+    while (Tok.getKind() == tok::comma) {
+      // Eat the comma.
+      ConsumeToken();
+      
+      if (Tok.getKind() != tok::identifier) {
+        Diag(Tok, diag::err_expected_ident);
+        ErrorEmitted = true;
+        break;
+      }
+      
+      IdentifierInfo *ParmII = Tok.getIdentifierInfo();
+      
+      // Verify that the argument identifier has not already been mentioned.
+      if (!ParamsSoFar.insert(ParmII)) {
+        Diag(Tok.getLocation(), diag::err_param_redefinition,ParmII->getName());
+        ParmII = 0;
+      }
+          
+      // Remember this identifier in ParamInfo.
+      if (ParmII)
+        ParamInfo.push_back(DeclaratorChunk::ParamInfo(ParmII,
+                                                       Tok.getLocation(), 0));
+      
+      // Eat the identifier.
+      ConsumeToken();
+    }
+    
+    // K&R 'prototype'.
+    IsVariadic = false;
+    HasPrototype = false;
+  } else {
+    // Finally, a normal, non-empty parameter type list.
+    
+    // Enter function-declaration scope, limiting any declarators for struct
+    // tags to the function prototype scope.
+    // FIXME: is this needed?
+    EnterScope(0);
+    
+    IsVariadic = false;
+    while (1) {
+      if (Tok.getKind() == tok::ellipsis) {
+        IsVariadic = true;
+
+        // Check to see if this is "void(...)" which is not allowed.
+        if (ParamInfo.empty()) {
+          // Otherwise, parse parameter type list.  If it starts with an
+          // ellipsis,  diagnose the malformed function.
+          Diag(Tok, diag::err_ellipsis_first_arg);
+          IsVariadic = false;       // Treat this like 'void()'.
+        }
+
+        // Consume the ellipsis.
+        ConsumeToken();
+        break;
+      }
+      
+      // Parse the declaration-specifiers.
+      DeclSpec DS;
+      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.getKind() == tok::kw___attribute)
+        ParmDecl.AddAttributes(ParseAttributes());
+      
+      // Verify C99 6.7.5.3p2: The only SCS allowed is 'register'.
+      // NOTE: we could trivially allow 'int foo(auto int X)' if we wanted.
+      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();
+      }
+      
+      // Inform the actions module about the parameter declarator, so it gets
+      // added to the current scope.
+      Action::TypeResult ParamTy =
+        Actions.ParseParamDeclaratorType(CurScope, ParmDecl);
+        
+      // Remember this parsed parameter in ParamInfo.
+      IdentifierInfo *ParmII = ParmDecl.getIdentifier();
+      
+      // Verify that the argument identifier has not already been mentioned.
+      if (ParmII && !ParamsSoFar.insert(ParmII)) {
+        Diag(ParmDecl.getIdentifierLoc(), diag::err_param_redefinition,
+             ParmII->getName());
+        ParmII = 0;
+      }
+        
+      ParamInfo.push_back(DeclaratorChunk::ParamInfo(ParmII,
+                                                    ParmDecl.getIdentifierLoc(),
+                                                     ParamTy.Val));
+      
+      // If the next token is a comma, consume it and keep reading arguments.
+      if (Tok.getKind() != tok::comma) break;
+      
+      // Consume the comma.
+      ConsumeToken();
+    }
+    
+    HasPrototype = true;
+    
+    // Leave prototype scope.
+    ExitScope();
+  }
+  
+  // Remember that we parsed a function type, and remember the attributes.
+  if (!ErrorEmitted)
+    D.AddTypeInfo(DeclaratorChunk::getFunction(HasPrototype, IsVariadic,
+                                               &ParamInfo[0], ParamInfo.size(),
+                                               StartLoc));
+  
+  // If we have the closing ')', eat it and we're done.
+  if (Tok.getKind() == tok::r_paren) {
+    ConsumeParen();
+  } else {
+    // If an error happened earlier parsing something else in the proto, don't
+    // issue another error.
+    if (!ErrorEmitted)
+      Diag(Tok, diag::err_expected_rparen);
+    SkipUntil(tok::r_paren);
+  }
+}
+
+
+/// [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();
+  
+  // If valid, this location is the position where we read the 'static' keyword.
+  SourceLocation StaticLoc;
+  if (Tok.getKind() == tok::kw_static)
+    StaticLoc = ConsumeToken();
+  
+  // If there is a type-qualifier-list, read it now.
+  DeclSpec DS;
+  ParseTypeQualifierListOpt(DS);
+  
+  // If we haven't already read 'static', check to see if there is one after the
+  // type-qualifier-list.
+  if (!StaticLoc.isValid() && Tok.getKind() == tok::kw_static)
+    StaticLoc = ConsumeToken();
+  
+  // Handle "direct-declarator [ type-qual-list[opt] * ]".
+  bool isStar = false;
+  ExprResult NumElements(false);
+  if (Tok.getKind() == tok::star) {
+    // Remember the '*' token, in case we have to un-get it.
+    LexerToken StarTok = Tok;
+    ConsumeToken();
+
+    // Check that the ']' token is present to avoid incorrectly parsing
+    // expressions starting with '*' as [*].
+    if (Tok.getKind() == tok::r_square) {
+      if (StaticLoc.isValid())
+        Diag(StaticLoc, diag::err_unspecified_vla_size_with_static);
+      StaticLoc = SourceLocation();  // Drop the static.
+      isStar = true;
+    } else {
+      // Otherwise, the * must have been some expression (such as '*ptr') that
+      // started an assignment-expr.  We already consumed the token, but now we
+      // need to reparse it.  This handles cases like 'X[*p + 4]'
+      NumElements = ParseAssignmentExpressionWithLeadingStar(StarTok);
+    }
+  } else if (Tok.getKind() != tok::r_square) {
+    // Parse the assignment-expression now.
+    NumElements = ParseAssignmentExpression();
+  }
+  
+  // If there was an error parsing the assignment-expression, recover.
+  if (NumElements.isInvalid) {
+    // If the expression was invalid, skip it.
+    SkipUntil(tok::r_square);
+    return;
+  }
+  
+  MatchRHSPunctuation(tok::r_square, StartLoc);
+    
+  // If C99 isn't enabled, emit an ext-warn if the arg list wasn't empty and if
+  // it was not a constant expression.
+  if (!getLang().C99) {
+    // TODO: check C90 array constant exprness.
+    if (isStar || StaticLoc.isValid() ||
+        0/*TODO: NumElts is not a C90 constantexpr */)
+      Diag(StartLoc, diag::ext_c99_array_usage);
+  }
+
+  // Remember that we parsed a pointer type, and remember the type-quals.
+  D.AddTypeInfo(DeclaratorChunk::getArray(DS.getTypeQualifiers(),
+                                          StaticLoc.isValid(), isStar,
+                                          NumElements.Val, StartLoc));
+}
+
diff --git a/Parse/ParseExpr.cpp b/Parse/ParseExpr.cpp
new file mode 100644
index 0000000..41f347f
--- /dev/null
+++ b/Parse/ParseExpr.cpp
@@ -0,0 +1,935 @@
+//===--- ParseExpr.cpp - Expression Parsing -------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file was developed by Chris Lattner and 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/Basic/Diagnostic.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    // *, /, %
+  };
+}
+
+
+/// getBinOpPrecedence - Return the precedence of the specified binary operator
+/// token.  This returns:
+///
+static prec::Level getBinOpPrecedence(tok::TokenKind Kind) {
+  switch (Kind) {
+  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:
+  case tok::greater:              return prec::Relational;
+  case tok::lessless:
+  case tok::greatergreater:       return prec::Shift;
+  case tok::plus:
+  case tok::minus:                return prec::Additive;
+  case tok::percent:
+  case tok::slash:
+  case tok::star:                 return prec::Multiplicative;
+  }
+}
+
+
+/// 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.
+///
+///       multiplicative-expression: [C99 6.5.5]
+///         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
+///
+///       assignment-expression: [C99 6.5.16]
+///         conditional-expression
+///         unary-expression assignment-operator assignment-expression
+///
+///       assignment-operator: one of
+///         = *= /= %= += -= <<= >>= &= ^= |=
+///
+///       expression: [C99 6.5.17]
+///         assignment-expression
+///         expression ',' assignment-expression
+///
+Parser::ExprResult Parser::ParseExpression() {
+  ExprResult LHS = ParseCastExpression(false);
+  if (LHS.isInvalid) return LHS;
+  
+  return ParseRHSOfBinaryExpression(LHS, prec::Comma);
+}
+
+/// ParseAssignmentExpression - Parse an expr that doesn't include commas.
+///
+Parser::ExprResult Parser::ParseAssignmentExpression() {
+  ExprResult LHS = ParseCastExpression(false);
+  if (LHS.isInvalid) return LHS;
+  
+  return ParseRHSOfBinaryExpression(LHS, prec::Assignment);
+}
+
+Parser::ExprResult Parser::ParseConstantExpression() {
+  ExprResult LHS = ParseCastExpression(false);
+  if (LHS.isInvalid) return LHS;
+  
+  // TODO: Validate that this is a constant expr!
+  return ParseRHSOfBinaryExpression(LHS, prec::Conditional);
+}
+
+/// ParseExpressionWithLeadingIdentifier - This special purpose method is used
+/// in contexts where we have already consumed an identifier (which we saved in
+/// 'IdTok'), then discovered that the identifier was really the leading token
+/// of part of an expression.  For example, in "A[1]+B", we consumed "A" (which
+/// is now in 'IdTok') and the current token is "[".
+Parser::ExprResult Parser::
+ParseExpressionWithLeadingIdentifier(const LexerToken &IdTok) {
+  // We know that 'IdTok' must correspond to this production:
+  //   primary-expression: identifier
+  
+  // Let the actions module handle the identifier.
+  ExprResult Res = Actions.ParseIdentifierExpr(CurScope, IdTok.getLocation(),
+                                               *IdTok.getIdentifierInfo(),
+                                               Tok.getKind() == tok::l_paren);
+  
+  // Because we have to parse an entire cast-expression before starting the
+  // ParseRHSOfBinaryExpression method (which parses any trailing binops), we
+  // need to handle the 'postfix-expression' rules.  We do this by invoking
+  // ParsePostfixExpressionSuffix to consume any postfix-expression suffixes:
+  Res = ParsePostfixExpressionSuffix(Res);
+  if (Res.isInvalid) return Res;
+
+  // At this point, the "A[1]" part of "A[1]+B" has been consumed. Once this is
+  // done, we know we don't have to do anything for cast-expression, because the
+  // only non-postfix-expression production starts with a '(' token, and we know
+  // we have an identifier.  As such, we can invoke ParseRHSOfBinaryExpression
+  // to consume any trailing operators (e.g. "+" in this example) and connected
+  // chunks of the expression.
+  return ParseRHSOfBinaryExpression(Res, prec::Comma);
+}
+
+/// ParseExpressionWithLeadingIdentifier - This special purpose method is used
+/// in contexts where we have already consumed an identifier (which we saved in
+/// 'IdTok'), then discovered that the identifier was really the leading token
+/// of part of an assignment-expression.  For example, in "A[1]+B", we consumed
+/// "A" (which is now in 'IdTok') and the current token is "[".
+Parser::ExprResult Parser::
+ParseAssignmentExprWithLeadingIdentifier(const LexerToken &IdTok) {
+  // We know that 'IdTok' must correspond to this production:
+  //   primary-expression: identifier
+  
+  // Let the actions module handle the identifier.
+  ExprResult Res = Actions.ParseIdentifierExpr(CurScope, IdTok.getLocation(),
+                                               *IdTok.getIdentifierInfo(),
+                                               Tok.getKind() == tok::l_paren);
+  
+  // Because we have to parse an entire cast-expression before starting the
+  // ParseRHSOfBinaryExpression method (which parses any trailing binops), we
+  // need to handle the 'postfix-expression' rules.  We do this by invoking
+  // ParsePostfixExpressionSuffix to consume any postfix-expression suffixes:
+  Res = ParsePostfixExpressionSuffix(Res);
+  if (Res.isInvalid) return Res;
+  
+  // At this point, the "A[1]" part of "A[1]+B" has been consumed. Once this is
+  // done, we know we don't have to do anything for cast-expression, because the
+  // only non-postfix-expression production starts with a '(' token, and we know
+  // we have an identifier.  As such, we can invoke ParseRHSOfBinaryExpression
+  // to consume any trailing operators (e.g. "+" in this example) and connected
+  // chunks of the expression.
+  return ParseRHSOfBinaryExpression(Res, prec::Assignment);
+}
+
+
+/// ParseAssignmentExpressionWithLeadingStar - This special purpose method is
+/// used in contexts where we have already consumed a '*' (which we saved in
+/// 'StarTok'), then discovered that the '*' was really the leading token of an
+/// expression.  For example, in "*(int*)P+B", we consumed "*" (which is
+/// now in 'StarTok') and the current token is "(".
+Parser::ExprResult Parser::
+ParseAssignmentExpressionWithLeadingStar(const LexerToken &StarTok) {
+  // We know that 'StarTok' must correspond to this production:
+  //  unary-expression: unary-operator cast-expression
+  // where 'unary-operator' is '*'.
+  
+  // Parse the cast-expression that follows the '*'.  This will parse the
+  // "*(int*)P" part of "*(int*)P+B".
+  ExprResult Res = ParseCastExpression(false);
+  if (Res.isInvalid) return Res;
+
+  // Combine StarTok + Res to get the new AST for the combined expression..
+  Res = Actions.ParseUnaryOp(StarTok.getLocation(), tok::star, Res.Val);
+  if (Res.isInvalid) return Res;
+  
+  
+  // We have to parse an entire cast-expression before starting the
+  // ParseRHSOfBinaryExpression method (which parses any trailing binops). Since
+  // we know that the only production above us is the cast-expression
+  // production, and because the only alternative productions start with a '('
+  // token (we know we had a '*'), there is no work to do to get a whole
+  // cast-expression.
+  
+  // At this point, the "*(int*)P" part of "*(int*)P+B" has been consumed. Once
+  // this is done, we can invoke ParseRHSOfBinaryExpression to consume any
+  // trailing operators (e.g. "+" in this example) and connected chunks of the
+  // assignment-expression.
+  return ParseRHSOfBinaryExpression(Res, prec::Assignment);
+}
+
+
+/// ParseRHSOfBinaryExpression - Parse a binary expression that starts with
+/// LHS and has a precedence of at least MinPrec.
+Parser::ExprResult
+Parser::ParseRHSOfBinaryExpression(ExprResult LHS, unsigned MinPrec) {
+  unsigned NextTokPrec = getBinOpPrecedence(Tok.getKind());
+  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 LHS;
+
+    // Consume the operator, saving the operator token for error reporting.
+    LexerToken OpToken = Tok;
+    ConsumeToken();
+    
+    // Special case handling for the ternary operator.
+    ExprResult TernaryMiddle(true);
+    if (NextTokPrec == prec::Conditional) {
+      if (Tok.getKind() != tok::colon) {
+        // 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 TernaryMiddle;
+      } else {
+        // Special case handling of "X ? Y : Z" where Y is empty:
+        //   logical-OR-expression '?' ':' conditional-expression   [GNU]
+        TernaryMiddle = ExprResult(false);
+        Diag(Tok, diag::ext_gnu_conditional_expr);
+      }
+      
+      if (Tok.getKind() != tok::colon) {
+        Diag(Tok, diag::err_expected_colon);
+        Diag(OpToken, diag::err_matching, "?");
+        return ExprResult(true);
+      }
+      
+      // Eat the colon.
+      ColonLoc = ConsumeToken();
+    }
+    
+    // Parse another leaf here for the RHS of the operator.
+    ExprResult RHS = ParseCastExpression(false);
+    if (RHS.isInvalid) return 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());
+
+    // Assignment and conditional expressions are right-associative.
+    bool isRightAssoc = NextTokPrec == prec::Conditional ||
+                        NextTokPrec == 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.
+      RHS = ParseRHSOfBinaryExpression(RHS, ThisPrec + !isRightAssoc);
+      if (RHS.isInvalid) return RHS;
+
+      NextTokPrec = getBinOpPrecedence(Tok.getKind());
+    }
+    assert(NextTokPrec <= ThisPrec && "Recursion didn't work!");
+  
+    // Combine the LHS and RHS into the LHS (e.g. build AST).
+    if (TernaryMiddle.isInvalid)
+      LHS = Actions.ParseBinOp(OpToken.getLocation(), OpToken.getKind(),
+                               LHS.Val, RHS.Val);
+    else
+      LHS = Actions.ParseConditionalOp(OpToken.getLocation(), ColonLoc,
+                                       LHS.Val, TernaryMiddle.Val, RHS.Val);
+  }
+}
+
+/// ParseCastExpression - Parse a cast-expression, or, if isUnaryExpression is
+/// true, parse a unary-expression.
+///
+///       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 ')'
+/// [GNU]   '&&' identifier
+///
+///       unary-operator: one of
+///         '&'  '*'  '+'  '-'  '~'  '!'
+/// [GNU]   '__extension__'  '__real'  '__imag'
+///
+///       primary-expression: [C99 6.5.1]
+///         identifier
+///         constant
+///         string-literal
+/// [C++]   boolean-literal  [C++ 2.13.5]
+///         '(' 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 ')'
+/// [OBC]   '[' objc-receiver objc-message-args ']'    [TODO]
+/// [OBC]   '@selector' '(' objc-selector-arg ')'      [TODO]
+/// [OBC]   '@protocol' '(' identifier ')'             [TODO]
+/// [OBC]   '@encode' '(' type-name ')'                [TODO]
+/// [OBC]   objc-string-literal                        [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]
+///
+///       constant: [C99 6.4.4]
+///         integer-constant
+///         floating-constant
+///         enumeration-constant -> identifier
+///         character-constant
+///
+Parser::ExprResult Parser::ParseCastExpression(bool isUnaryExpression) {
+  ExprResult Res;
+  tok::TokenKind SavedKind = Tok.getKind();
+  
+  // 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;
+    Res = ParseParenExpression(ParenExprType, CastTy, RParenLoc);
+    if (Res.isInvalid) return 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 parsed '(' type-name ')' and the thing after it wasn't a '{'.  Parse
+      // the cast-expression that follows it next.
+      // TODO: For cast expression with CastTy.
+      Res = ParseCastExpression(false);
+      if (!Res.isInvalid)
+        Res = Actions.ParseCastExpr(LParenLoc, CastTy, RParenLoc, Res.Val);
+      return Res;
+    }
+      
+    // These can be followed by postfix-expr pieces.
+    return ParsePostfixExpressionSuffix(Res);
+  }
+    
+    // primary-expression
+  case tok::numeric_constant:
+    // constant: integer-constant
+    // constant: floating-constant
+    
+    Res = Actions.ParseNumericConstant(Tok);
+    ConsumeToken();
+    
+    // These can be followed by postfix-expr pieces.
+    return ParsePostfixExpressionSuffix(Res);
+
+  case tok::kw_true:
+  case tok::kw_false:
+    return ParseCXXBoolLiteral();
+
+  case tok::identifier: {      // primary-expression: identifier
+                               // constant: enumeration-constant
+    // Consume the identifier so that we can see if it is followed by a '('.
+    // 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.
+    IdentifierInfo &II = *Tok.getIdentifierInfo();
+    SourceLocation L = ConsumeToken();
+    Res = Actions.ParseIdentifierExpr(CurScope, L, II,
+                                      Tok.getKind() == tok::l_paren);
+    // These can be followed by postfix-expr pieces.
+    return ParsePostfixExpressionSuffix(Res);
+  }
+  case tok::char_constant:     // constant: character-constant
+    Res = Actions.ParseCharacterConstant(Tok);
+    ConsumeToken();
+    // These can be followed by postfix-expr pieces.
+    return ParsePostfixExpressionSuffix(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.ParseSimplePrimaryExpr(Tok.getLocation(), SavedKind);
+    ConsumeToken();
+    // These can be followed by postfix-expr pieces.
+    return ParsePostfixExpressionSuffix(Res);
+  case tok::string_literal:    // primary-expression: string-literal
+  case tok::wide_string_literal:
+    Res = ParseStringLiteralExpression();
+    if (Res.isInvalid) return Res;
+    // This can be followed by postfix-expr pieces (e.g. "foo"[1]).
+    return ParsePostfixExpressionSuffix(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::plusplus:      // unary-expression: '++' unary-expression
+  case tok::minusminus: {  // unary-expression: '--' unary-expression
+    SourceLocation SavedLoc = ConsumeToken();
+    Res = ParseCastExpression(true);
+    if (!Res.isInvalid)
+      Res = Actions.ParseUnaryOp(SavedLoc, SavedKind, Res.Val);
+    return Res;
+  }
+  case tok::amp:           // unary-expression: '&' cast-expression
+  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]
+  case tok::kw___extension__:{//unary-expression:'__extension__' cast-expr [GNU]
+    // FIXME: Extension not handled correctly here!
+    SourceLocation SavedLoc = ConsumeToken();
+    Res = ParseCastExpression(false);
+    if (!Res.isInvalid)
+      Res = Actions.ParseUnaryOp(SavedLoc, SavedKind, Res.Val);
+    return Res;
+  }
+  case tok::kw_sizeof:     // unary-expression: 'sizeof' unary-expression
+                           // unary-expression: 'sizeof' '(' type-name ')'
+  case tok::kw___alignof:  // unary-expression: '__alignof' unary-expression
+                           // unary-expression: '__alignof' '(' type-name ')'
+    return ParseSizeofAlignofExpression();
+  case tok::ampamp: {      // unary-expression: '&&' identifier
+    SourceLocation AmpAmpLoc = ConsumeToken();
+    if (Tok.getKind() != tok::identifier) {
+      Diag(Tok, diag::err_expected_ident);
+      return ExprResult(true);
+    }
+    
+    Diag(AmpAmpLoc, diag::ext_gnu_address_of_label);
+    Res = Actions.ParseAddrLabel(AmpAmpLoc, Tok.getLocation(),
+                                 Tok.getIdentifierInfo());
+    ConsumeToken();
+    return Res;
+  }
+  case tok::kw_const_cast:
+  case tok::kw_dynamic_cast:
+  case tok::kw_reinterpret_cast:
+  case tok::kw_static_cast:
+    return ParseCXXCasts();
+  default:
+    Diag(Tok, diag::err_expected_expression);
+    return ExprResult(true);
+  }
+  
+  // 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::ExprResult Parser::ParsePostfixExpressionSuffix(ExprResult 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 LHS;
+    case tok::l_square: {  // postfix-expression: p-e '[' expression ']'
+      Loc = ConsumeBracket();
+      ExprResult Idx = ParseExpression();
+      
+      SourceLocation RLoc = Tok.getLocation();
+      
+      if (!LHS.isInvalid && !Idx.isInvalid && Tok.getKind() == tok::r_square)
+        LHS = Actions.ParseArraySubscriptExpr(LHS.Val, Loc, Idx.Val, RLoc);
+      else 
+        LHS = ExprResult(true);
+
+      // Match the ']'.
+      MatchRHSPunctuation(tok::r_square, Loc);
+      break;
+    }
+      
+    case tok::l_paren: {   // p-e: p-e '(' argument-expression-list[opt] ')'
+      llvm::SmallVector<ExprTy*, 8> ArgExprs;
+      llvm::SmallVector<SourceLocation, 8> CommaLocs;
+      bool ArgExprsOk = true;
+      
+      Loc = ConsumeParen();
+      
+      if (Tok.getKind() != tok::r_paren) {
+        while (1) {
+          ExprResult ArgExpr = ParseAssignmentExpression();
+          if (ArgExpr.isInvalid) {
+            ArgExprsOk = false;
+            SkipUntil(tok::r_paren);
+            break;
+          } else
+            ArgExprs.push_back(ArgExpr.Val);
+          
+          if (Tok.getKind() != tok::comma)
+            break;
+          // Move to the next argument, remember where the comma was.
+          CommaLocs.push_back(ConsumeToken());
+        }
+      }
+        
+      // Match the ')'.
+      if (!LHS.isInvalid && ArgExprsOk && Tok.getKind() == tok::r_paren) {
+        assert((ArgExprs.size() == 0 || ArgExprs.size()-1 == CommaLocs.size())&&
+               "Unexpected number of commas!");
+        LHS = Actions.ParseCallExpr(LHS.Val, Loc, &ArgExprs[0], ArgExprs.size(),
+                                    &CommaLocs[0], Tok.getLocation());
+      }
+      
+      if (ArgExprsOk)
+        MatchRHSPunctuation(tok::r_paren, Loc);
+      break;
+    }
+    case tok::arrow:       // postfix-expression: p-e '->' identifier
+    case tok::period: {    // postfix-expression: p-e '.' identifier
+      tok::TokenKind OpKind = Tok.getKind();
+      SourceLocation OpLoc = ConsumeToken();  // Eat the "." or "->" token.
+      
+      if (Tok.getKind() != tok::identifier) {
+        Diag(Tok, diag::err_expected_ident);
+        return ExprResult(true);
+      }
+      
+      if (!LHS.isInvalid)
+        LHS = Actions.ParseMemberReferenceExpr(LHS.Val, OpLoc, OpKind,
+                                               Tok.getLocation(),
+                                               *Tok.getIdentifierInfo());
+      ConsumeToken();
+      break;
+    }
+    case tok::plusplus:    // postfix-expression: postfix-expression '++'
+    case tok::minusminus:  // postfix-expression: postfix-expression '--'
+      if (!LHS.isInvalid)
+        LHS = Actions.ParsePostfixUnaryOp(Tok.getLocation(), Tok.getKind(),
+                                          LHS.Val);
+      ConsumeToken();
+      break;
+    }
+  }
+}
+
+
+/// 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 ')'
+Parser::ExprResult Parser::ParseSizeofAlignofExpression() {
+  assert((Tok.getKind() == tok::kw_sizeof ||
+          Tok.getKind() == tok::kw___alignof) &&
+         "Not a sizeof/alignof expression!");
+  LexerToken OpTok = Tok;
+  ConsumeToken();
+  
+  // If the operand doesn't start with an '(', it must be an expression.
+  ExprResult Operand;
+  if (Tok.getKind() != tok::l_paren) {
+    Operand = ParseCastExpression(true);
+  } 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;
+    TypeTy *CastTy;
+    SourceLocation LParenLoc = Tok.getLocation(), RParenLoc;
+    Operand = ParseParenExpression(ExprType, CastTy, RParenLoc);
+    
+    // If ParseParenExpression parsed a '(typename)' sequence only, the this is
+    // sizeof/alignof a type.  Otherwise, it is sizeof/alignof an expression.
+    if (ExprType == CastExpr) {
+      return Actions.ParseSizeOfAlignOfTypeExpr(OpTok.getLocation(),
+                                              OpTok.getKind() == tok::kw_sizeof,
+                                                LParenLoc, CastTy, RParenLoc);
+    }
+  }
+  
+  // If we get here, the operand to the sizeof/alignof was an expresion.
+  if (!Operand.isInvalid)
+    Operand = Actions.ParseUnaryOp(OpTok.getLocation(), OpTok.getKind(),
+                                   Operand.Val);
+  return 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::ExprResult Parser::ParseBuiltinPrimaryExpression() {
+  ExprResult Res(false);
+  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.getKind() != tok::l_paren) {
+    Diag(Tok, diag::err_expected_lparen_after, BuiltinII->getName());
+    return ExprResult(true);
+  }
+  
+  SourceLocation LParenLoc = ConsumeParen();
+  // TODO: Build AST.
+
+  switch (T) {
+  default: assert(0 && "Not a builtin primary expression!");
+  case tok::kw___builtin_va_arg:
+    Res = ParseAssignmentExpression();
+    if (Res.isInvalid) {
+      SkipUntil(tok::r_paren);
+      return Res;
+    }
+
+    if (ExpectAndConsume(tok::comma, diag::err_expected_comma, "",tok::r_paren))
+      return ExprResult(true);
+
+    ParseTypeName();
+    break;
+    
+  case tok::kw___builtin_offsetof:
+    ParseTypeName();
+
+    if (ExpectAndConsume(tok::comma, diag::err_expected_comma, "",tok::r_paren))
+      return ExprResult(true);
+    
+    // We must have at least one identifier here.
+    if (ExpectAndConsume(tok::identifier, diag::err_expected_ident, "",
+                         tok::r_paren))
+      return ExprResult(true);
+
+    while (1) {
+      if (Tok.getKind() == tok::period) {
+        // offsetof-member-designator: offsetof-member-designator '.' identifier
+        ConsumeToken();
+        
+        if (ExpectAndConsume(tok::identifier, diag::err_expected_ident, "",
+                             tok::r_paren))
+          return ExprResult(true);
+      } else if (Tok.getKind() == tok::l_square) {
+        // offsetof-member-designator: offsetof-member-design '[' expression ']'
+        SourceLocation LSquareLoc = ConsumeBracket();
+        Res = ParseExpression();
+        if (Res.isInvalid) {
+          SkipUntil(tok::r_paren);
+          return Res;
+        }
+
+        MatchRHSPunctuation(tok::r_square, LSquareLoc);
+      } else {
+        break;
+      }
+    }
+    break;
+  case tok::kw___builtin_choose_expr:
+    Res = ParseAssignmentExpression();
+    
+    if (ExpectAndConsume(tok::comma, diag::err_expected_comma, "",tok::r_paren))
+      return ExprResult(true);
+    
+    Res = ParseAssignmentExpression();
+    
+    if (ExpectAndConsume(tok::comma, diag::err_expected_comma, "",tok::r_paren))
+      return ExprResult(true);
+    
+    Res = ParseAssignmentExpression();
+    break;
+  case tok::kw___builtin_types_compatible_p:
+    ParseTypeName();
+    
+    if (ExpectAndConsume(tok::comma, diag::err_expected_comma, "",tok::r_paren))
+      return ExprResult(true);
+    
+    ParseTypeName();
+    break;
+  }      
+  
+  MatchRHSPunctuation(tok::r_paren, LParenLoc);
+  
+  // These can be followed by postfix-expr pieces because they are
+  // primary-expressions.
+  return ParsePostfixExpressionSuffix(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.
+///
+///       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::ExprResult Parser::ParseParenExpression(ParenParseOption &ExprType,
+                                                TypeTy *&CastTy,
+                                                SourceLocation &RParenLoc) {
+  assert(Tok.getKind() == tok::l_paren && "Not a paren expr!");
+  SourceLocation OpenLoc = ConsumeParen();
+  ExprResult Result(false);
+  CastTy = 0;
+  
+  if (ExprType >= CompoundStmt && Tok.getKind() == tok::l_brace &&
+      !getLang().NoExtensions) {
+    Diag(Tok, diag::ext_gnu_statement_expr);
+    ParseCompoundStatement();
+    ExprType = CompoundStmt;
+    // TODO: Build AST for GNU compound stmt.
+  } else if (ExprType >= CompoundLiteral && isTypeSpecifierQualifier()) {
+    // Otherwise, this is a compound literal expression or cast expression.
+    TypeTy *Ty = ParseTypeName();
+
+    // Match the ')'.
+    if (Tok.getKind() == tok::r_paren)
+      RParenLoc = ConsumeParen();
+    else
+      MatchRHSPunctuation(tok::r_paren, OpenLoc);
+    
+    if (Tok.getKind() == tok::l_brace) {
+      if (!getLang().C99)   // Compound literals don't exist in C90.
+        Diag(OpenLoc, diag::ext_c99_compound_literal);
+      Result = ParseInitializer();
+      ExprType = CompoundLiteral;
+      // TODO: Build AST for compound literal.
+    } else if (ExprType == CastExpr) {
+      // Note that this doesn't parse the subsequence cast-expression, it just
+      // returns the parsed type to the callee.
+      ExprType = CastExpr;
+      CastTy = Ty;
+      return ExprResult(false);
+    } else {
+      Diag(Tok, diag::err_expected_lbrace_in_compound_literal);
+      return ExprResult(true);
+    }
+    return Result;
+  } else {
+    Result = ParseExpression();
+    ExprType = SimpleExpr;
+    if (!Result.isInvalid && Tok.getKind() == tok::r_paren)
+      Result = Actions.ParseParenExpr(OpenLoc, Tok.getLocation(), Result.Val);
+  }
+  
+  // Match the ')'.
+  if (Result.isInvalid)
+    SkipUntil(tok::r_paren);
+  else {
+    if (Tok.getKind() == tok::r_paren)
+      RParenLoc = ConsumeParen();
+    else
+      MatchRHSPunctuation(tok::r_paren, OpenLoc);
+  }
+  
+  return 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::ExprResult 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<LexerToken, 4> StringToks;
+  
+  do {
+    StringToks.push_back(Tok);
+    ConsumeStringToken();
+  } while (isTokenStringLiteral());
+
+  // Pass the set of string tokens, ready for concatenation, to the actions.
+  return Actions.ParseStringLiteral(&StringToks[0], StringToks.size());
+}
diff --git a/Parse/ParseExprCXX.cpp b/Parse/ParseExprCXX.cpp
new file mode 100644
index 0000000..7048660
--- /dev/null
+++ b/Parse/ParseExprCXX.cpp
@@ -0,0 +1,78 @@
+//===--- ParseExprCXX.cpp - C++ Expression Parsing ------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file was developed by Bill Wendling and 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/Basic/Diagnostic.h"
+#include "clang/Parse/Parser.h"
+using namespace clang;
+
+/// 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::ExprResult 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 ExprResult(true);
+
+  TypeTy *CastTy = ParseTypeName();
+  SourceLocation RAngleBracketLoc = Tok.getLocation();
+
+  if (ExpectAndConsume(tok::greater, diag::err_expected_greater)) {
+    Diag(LAngleBracketLoc, diag::err_matching, "<");
+    return ExprResult(true);
+  }
+
+  SourceLocation LParenLoc = Tok.getLocation(), RParenLoc;
+
+  if (Tok.getKind() != tok::l_paren) {
+    Diag(Tok, diag::err_expected_lparen_after, CastName);
+    return ExprResult(true);
+  }
+
+  ExprResult Result = ParseSimpleParenExpression(RParenLoc);
+
+  if (!Result.isInvalid)
+    Result = Actions.ParseCXXCasts(OpLoc, Kind,
+                                   LAngleBracketLoc, CastTy, RAngleBracketLoc,
+                                   LParenLoc, Result.Val, RParenLoc);
+
+  return Result;
+}
+
+/// ParseCXXBoolLiteral - This handles the C++ Boolean literals.
+///
+///       boolean-literal: [C++ 2.13.5]
+///         'true'
+///         'false'
+Parser::ExprResult Parser::ParseCXXBoolLiteral() {
+  tok::TokenKind Kind = Tok.getKind();
+  return Actions.ParseCXXBoolLiteral(ConsumeToken(), Kind);
+}
diff --git a/Parse/ParseInit.cpp b/Parse/ParseInit.cpp
new file mode 100644
index 0000000..01169d8
--- /dev/null
+++ b/Parse/ParseInit.cpp
@@ -0,0 +1,188 @@
+//===--- ParseInit.cpp - Initializer Parsing ------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file was developed by Chris Lattner and 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/Parser.h"
+#include "clang/Basic/Diagnostic.h"
+using namespace clang;
+
+
+/// MayBeDesignationStart - Return true if this token might be the start of a
+/// designator.
+static bool MayBeDesignationStart(tok::TokenKind K) {
+  switch (K) {
+  default: return false;
+  case tok::period:      // designator: '.' identifier
+  case tok::l_square:    // designator: array-designator
+  case tok::identifier:  // designation: identifier ':'
+    return true;
+  }
+}
+
+/// 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.  We need to consider this case when parsing array designators.
+///
+Parser::ExprResult Parser::ParseInitializerWithPotentialDesignator() {
+  // Parse each designator in the designator list until we find an initializer.
+  while (1) {
+    switch (Tok.getKind()) {
+    case tok::equal:
+      // We read some number (at least one due to the grammar we implemented)
+      // of designators and found an '=' sign.  The following tokens must be
+      // the initializer.
+      ConsumeToken();
+      return ParseInitializer();
+      
+    default: {
+      // We read some number (at least one due to the grammar we implemented)
+      // of designators and found something that isn't an = or an initializer.
+      // If we have exactly one array designator [TODO CHECK], this is the GNU
+      // 'designation: array-designator' extension.  Otherwise, it is a parse
+      // error.
+      SourceLocation Loc = Tok.getLocation();
+      ExprResult Init = ParseInitializer();
+      if (Init.isInvalid) return Init;
+      
+      Diag(Tok, diag::ext_gnu_missing_equal_designator);
+      return Init;
+    }
+    case tok::period:
+      // designator: '.' identifier
+      ConsumeToken();
+      if (ExpectAndConsume(tok::identifier, diag::err_expected_ident))
+        return ExprResult(true);
+      break;
+                         
+    case tok::l_square: {
+      // array-designator: '[' constant-expression ']'
+      // array-designator: '[' constant-expression '...' constant-expression ']'
+      SourceLocation StartLoc = ConsumeBracket();
+      
+      ExprResult Idx = ParseConstantExpression();
+      if (Idx.isInvalid) {
+        SkipUntil(tok::r_square);
+        return Idx;
+      }
+      
+      // Handle the gnu array range extension.
+      if (Tok.getKind() == tok::ellipsis) {
+        Diag(Tok, diag::ext_gnu_array_range);
+        ConsumeToken();
+        
+        ExprResult RHS = ParseConstantExpression();
+        if (RHS.isInvalid) {
+          SkipUntil(tok::r_square);
+          return RHS;
+        }
+      }
+      
+      MatchRHSPunctuation(tok::r_square, StartLoc);
+      break;
+    }
+    case tok::identifier: {
+      // Due to the GNU "designation: identifier ':'" extension, we don't know
+      // whether something starting with an identifier is an
+      // assignment-expression or if it is an old-style structure field
+      // designator.
+      // TODO: Check that this is the first designator.
+      LexerToken Ident = Tok;
+      ConsumeToken();
+      
+      // If this is the gross GNU extension, handle it now.
+      if (Tok.getKind() == tok::colon) {
+        Diag(Ident, diag::ext_gnu_old_style_field_designator);
+        ConsumeToken();
+        return ParseInitializer();
+      }
+      
+      // Otherwise, we just consumed the first token of an expression.  Parse
+      // the rest of it now.
+      return ParseAssignmentExprWithLeadingIdentifier(Ident);
+    }
+    }
+  }
+}
+
+
+/// ParseInitializer
+///       initializer: [C99 6.7.8]
+///         assignment-expression
+///         '{' initializer-list '}'
+///         '{' initializer-list ',' '}'
+/// [GNU]   '{' '}'
+///
+///       initializer-list:
+///         designation[opt] initializer
+///         initializer-list ',' designation[opt] initializer
+///
+Parser::ExprResult Parser::ParseInitializer() {
+  if (Tok.getKind() != tok::l_brace)
+    return ParseAssignmentExpression();
+
+  SourceLocation LBraceLoc = ConsumeBrace();
+  
+  // We support empty initializers, but tell the user that they aren't using
+  // C99-clean code.
+  if (Tok.getKind() == tok::r_brace)
+    Diag(LBraceLoc, diag::ext_gnu_empty_initializer);
+  else {
+    while (1) {
+      // Parse: designation[opt] initializer
+      
+      // If we know that this cannot be a designation, just parse the nested
+      // initializer directly.
+      ExprResult SubElt;
+      if (!MayBeDesignationStart(Tok.getKind()))
+        SubElt = ParseInitializer();
+      else
+        SubElt = ParseInitializerWithPotentialDesignator();
+      
+      // If we couldn't parse the subelement, bail out.
+      if (SubElt.isInvalid) {
+        SkipUntil(tok::r_brace);
+        return SubElt;
+      }
+    
+      // If we don't have a comma continued list, we're done.
+      if (Tok.getKind() != tok::comma) break;
+      ConsumeToken();
+      
+      // Handle trailing comma.
+      if (Tok.getKind() == tok::r_brace) break;
+    }    
+  }
+  
+  // Match the '}'.
+  MatchRHSPunctuation(tok::r_brace, LBraceLoc);
+  return ExprResult(false);
+}
+
diff --git a/Parse/ParseObjc.cpp b/Parse/ParseObjc.cpp
new file mode 100644
index 0000000..00b606a
--- /dev/null
+++ b/Parse/ParseObjc.cpp
@@ -0,0 +1,105 @@
+//===--- ParseObjc.cpp - Objective C Parsing ------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file was developed by Steve Naroff and is distributed under
+// the University of Illinois Open Source License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+//  This file implements the Objective-C portions of the Parser interface.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Parse/Parser.h"
+#include "clang/Basic/Diagnostic.h"
+#include "llvm/ADT/SmallVector.h"
+using namespace clang;
+
+
+/// ParseExternalDeclaration:
+///       external-declaration: [C99 6.9]
+/// [OBJC]  objc-class-definition
+/// [OBJC]  objc-class-declaration     [TODO]
+/// [OBJC]  objc-alias-declaration     [TODO]
+/// [OBJC]  objc-protocol-definition   [TODO]
+/// [OBJC]  objc-method-definition     [TODO]
+/// [OBJC]  '@' 'end'                  [TODO]
+void Parser::ParseObjCAtDirectives() {
+  SourceLocation AtLoc = ConsumeToken(); // the "@"
+  
+  IdentifierInfo *II = Tok.getIdentifierInfo();
+  switch (II ? II->getObjCKeywordID() : tok::objc_not_keyword) {
+    case tok::objc_class:
+      return ParseObjCAtClassDeclaration(AtLoc);
+    case tok::objc_interface:
+      return ParseObjCAtInterfaceDeclaration();
+    case tok::objc_protocol:
+      return ParseObjCAtProtocolDeclaration();
+    case tok::objc_implementation:
+      return ParseObjCAtImplementationDeclaration();
+    case tok::objc_end:
+      return ParseObjCAtEndDeclaration();
+    case tok::objc_compatibility_alias:
+      return ParseObjCAtAliasDeclaration();
+    default:
+      Diag(AtLoc, diag::err_unexpected_at);
+      SkipUntil(tok::semi);
+  }
+}
+
+///
+/// objc-class-declaration: 
+///    '@' 'class' identifier-list ';'
+///  
+void Parser::ParseObjCAtClassDeclaration(SourceLocation atLoc) {
+  ConsumeToken(); // the identifier "class"
+  llvm::SmallVector<IdentifierInfo *, 8> ClassNames;
+  
+  while (1) {
+    if (Tok.getKind() != tok::identifier) {
+      Diag(Tok, diag::err_expected_ident);
+      SkipUntil(tok::semi);
+      return;
+    }
+    
+    ClassNames.push_back(Tok.getIdentifierInfo());
+    ConsumeToken();
+    
+    if (Tok.getKind() != tok::comma)
+      break;
+    
+    ConsumeToken();
+  }
+  
+  // Consume the ';'.
+  if (ExpectAndConsume(tok::semi, diag::err_expected_semi_after, "@class"))
+    return;
+  
+  Actions.ParsedObjcClassDeclaration(CurScope,
+                                     &ClassNames[0], ClassNames.size());
+}
+
+void Parser::ParseObjCAtInterfaceDeclaration() {
+  assert(0 && "Unimp");
+}
+void Parser::ParseObjCAtProtocolDeclaration() {
+  assert(0 && "Unimp");
+}
+void Parser::ParseObjCAtImplementationDeclaration() {
+  assert(0 && "Unimp");
+}
+void Parser::ParseObjCAtEndDeclaration() {
+  assert(0 && "Unimp");
+}
+void Parser::ParseObjCAtAliasDeclaration() {
+  assert(0 && "Unimp");
+}
+
+void Parser::ParseObjCInstanceMethodDeclaration() {
+  assert(0 && "Unimp");
+}
+
+void Parser::ParseObjCClassMethodDeclaration() {
+  assert(0 && "Unimp");
+}
diff --git a/Parse/ParseStmt.cpp b/Parse/ParseStmt.cpp
new file mode 100644
index 0000000..7bc7a9c
--- /dev/null
+++ b/Parse/ParseStmt.cpp
@@ -0,0 +1,848 @@
+//===--- ParseStmt.cpp - Statement and Block Parser -----------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file was developed by Chris Lattner and 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 "clang/Basic/Diagnostic.h"
+#include "clang/Parse/DeclSpec.h"
+#include "clang/Parse/Scope.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
+/// [OBC]   objc-throw-statement         [TODO]
+/// [OBC]   objc-try-catch-statement     [TODO]
+/// [OBC]   objc-synchronized-statement  [TODO]
+/// [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:           [TODO]
+/// [OBC]   '@' 'throw' expression ';'    [TODO]
+/// [OBC]   '@' 'throw' ';'               [TODO]
+/// 
+Parser::StmtResult Parser::ParseStatementOrDeclaration(bool OnlyStatement) {
+  const char *SemiError = 0;
+  Parser::StmtResult Res;
+  
+  // 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.
+  switch (Tok.getKind()) {
+  case tok::identifier:             // C99 6.8.1: labeled-statement
+    // identifier ':' statement
+    // declaration                  (if !OnlyStatement)
+    // expression[opt] ';'
+    return ParseIdentifierStatement(OnlyStatement);
+
+  default:
+    if (!OnlyStatement && isDeclarationSpecifier()) {
+      // TODO: warn/disable if declaration is in the middle of a block and !C99.
+      return Actions.ParseDeclStmt(ParseDeclaration(Declarator::BlockContext));
+    } else if (Tok.getKind() == tok::r_brace) {
+      Diag(Tok, diag::err_expected_statement);
+      return true;
+    } else {
+      // expression[opt] ';'
+      ExprResult Res = ParseExpression();
+      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 true;
+      }
+      // Otherwise, eat the semicolon.
+      ExpectAndConsume(tok::semi, diag::err_expected_semi_after_expr);
+      return Actions.ParseExprStmt(Res.Val);
+    }
+    
+  case tok::kw_case:                // C99 6.8.1: labeled-statement
+    return ParseCaseStatement();
+  case tok::kw_default:             // C99 6.8.1: labeled-statement
+    return ParseDefaultStatement();
+    
+  case tok::l_brace:                // C99 6.8.2: compound-statement
+    return ParseCompoundStatement();
+  case tok::semi:                   // C99 6.8.3p3: expression[opt] ';'
+    return Actions.ParseNullStmt(ConsumeToken());
+    
+  case tok::kw_if:                  // C99 6.8.4.1: if-statement
+    return ParseIfStatement();
+  case tok::kw_switch:              // C99 6.8.4.2: switch-statement
+    return ParseSwitchStatement();
+    
+  case tok::kw_while:               // C99 6.8.5.1: while-statement
+    return ParseWhileStatement();
+  case tok::kw_do:                  // C99 6.8.5.2: do-statement
+    Res = ParseDoStatement();
+    SemiError = "do/while loop";
+    break;
+  case tok::kw_for:                 // C99 6.8.5.3: for-statement
+    return ParseForStatement();
+
+  case tok::kw_goto:                // C99 6.8.6.1: goto-statement
+    Res = ParseGotoStatement();
+    SemiError = "goto statement";
+    break;
+  case tok::kw_continue:            // C99 6.8.6.2: continue-statement
+    Res = ParseContinueStatement();
+    SemiError = "continue statement";
+    break;
+  case tok::kw_break:               // C99 6.8.6.3: break-statement
+    Res = ParseBreakStatement();
+    SemiError = "break statement";
+    break;
+  case tok::kw_return:              // C99 6.8.6.4: return-statement
+    Res = ParseReturnStatement();
+    SemiError = "return statement";
+    break;
+    
+  case tok::kw_asm:
+    Res = ParseAsmStatement();
+    SemiError = "asm statement";
+    break;
+  }
+  
+  // If we reached this code, the statement must end in a semicolon.
+  if (Tok.getKind() == tok::semi) {
+    ConsumeToken();
+  } else {
+    Diag(Tok, diag::err_expected_semi_after, SemiError);
+    SkipUntil(tok::semi);
+  }
+  return Res;
+}
+
+/// ParseIdentifierStatement - Because we don't have two-token lookahead, we
+/// have a bit of a quandry here.  Reading the identifier is necessary to see if
+/// there is a ':' after it.  If there is, this is a label, regardless of what
+/// else the identifier can mean.  If not, this is either part of a declaration
+/// (if the identifier is a type-name) or part of an expression.
+///
+///       labeled-statement:
+///         identifier ':' statement
+/// [GNU]   identifier ':' attributes[opt] statement
+///         declaration                  (if !OnlyStatement)
+///         expression[opt] ';'
+///
+Parser::StmtResult Parser::ParseIdentifierStatement(bool OnlyStatement) {
+  assert(Tok.getKind() == tok::identifier && Tok.getIdentifierInfo() &&
+         "Not an identifier!");
+
+  LexerToken IdentTok = Tok;  // Save the whole token.
+  ConsumeToken();  // eat the identifier.
+  
+  // identifier ':' statement
+  if (Tok.getKind() == tok::colon) {
+    SourceLocation ColonLoc = ConsumeToken();
+
+    // Read label attributes, if present.
+    DeclTy *AttrList = 0;
+    if (Tok.getKind() == tok::kw___attribute)
+      // TODO: save these somewhere.
+      AttrList = ParseAttributes();
+
+    StmtResult SubStmt = ParseStatement();
+    
+    // Broken substmt shouldn't prevent the label from being added to the AST.
+    if (SubStmt.isInvalid)
+      SubStmt = Actions.ParseNullStmt(ColonLoc);
+    
+    return Actions.ParseLabelStmt(IdentTok.getLocation(), 
+                                  IdentTok.getIdentifierInfo(),
+                                  ColonLoc, SubStmt.Val);
+  }
+  
+  // Check to see if this is a declaration.
+  void *TypeRep;
+  if (!OnlyStatement &&
+      (TypeRep = Actions.isTypeName(*IdentTok.getIdentifierInfo(), CurScope))) {
+    // Handle this.  Warn/disable if in middle of block and !C99.
+    DeclSpec DS;
+    
+    // Add the typedef name to the start of the decl-specs.
+    const char *PrevSpec = 0;
+    int isInvalid = DS.SetTypeSpecType(DeclSpec::TST_typedef,
+                                       IdentTok.getLocation(), PrevSpec,
+                                       TypeRep);
+    assert(!isInvalid && "First declspec can't be invalid!");
+    
+    // ParseDeclarationSpecifiers will continue from there.
+    ParseDeclarationSpecifiers(DS);
+
+    // C99 6.7.2.3p6: Handle "struct-or-union identifier;", "enum { X };"
+    // declaration-specifiers init-declarator-list[opt] ';'
+    if (Tok.getKind() == tok::semi) {
+      // TODO: emit error on 'int;' or 'const enum foo;'.
+      // if (!DS.isMissingDeclaratorOk()) Diag(...);
+      
+      ConsumeToken();
+      // FIXME: Return this as a type decl.
+      return 0;
+    }
+    
+    // Parse all the declarators.
+    Declarator DeclaratorInfo(DS, Declarator::BlockContext);
+    ParseDeclarator(DeclaratorInfo);
+    
+    DeclTy *Decl = ParseInitDeclaratorListAfterFirstDeclarator(DeclaratorInfo);
+    return Decl ? Actions.ParseDeclStmt(Decl) : 0;
+  }
+  
+  // Otherwise, this is an expression.  Seed it with II and parse it.
+  ExprResult Res = ParseExpressionWithLeadingIdentifier(IdentTok);
+  if (Res.isInvalid) {
+    SkipUntil(tok::semi);
+    return true;
+  } else if (Tok.getKind() != tok::semi) {
+    Diag(Tok, diag::err_expected_semi_after, "expression");
+    SkipUntil(tok::semi);
+    return true;
+  } else {
+    ConsumeToken();
+    // Convert expr to a stmt.
+    return Actions.ParseExprStmt(Res.Val);
+  }
+}
+
+/// ParseCaseStatement
+///       labeled-statement:
+///         'case' constant-expression ':' statement
+/// [GNU]   'case' constant-expression '...' constant-expression ':' statement
+///
+/// Note that this does not parse the 'statement' at the end.
+///
+Parser::StmtResult Parser::ParseCaseStatement() {
+  assert(Tok.getKind() == tok::kw_case && "Not a case stmt!");
+  SourceLocation CaseLoc = ConsumeToken();  // eat the 'case'.
+
+  ExprResult LHS = ParseConstantExpression();
+  if (LHS.isInvalid) {
+    SkipUntil(tok::colon);
+    return true;
+  }
+  
+  // GNU case range extension.
+  SourceLocation DotDotDotLoc;
+  ExprTy *RHSVal = 0;
+  if (Tok.getKind() == tok::ellipsis) {
+    Diag(Tok, diag::ext_gnu_case_range);
+    DotDotDotLoc = ConsumeToken();
+    
+    ExprResult RHS = ParseConstantExpression();
+    if (RHS.isInvalid) {
+      SkipUntil(tok::colon);
+      return true;
+    }
+    RHSVal = RHS.Val;
+  }
+  
+  if (Tok.getKind() != tok::colon) {
+    Diag(Tok, diag::err_expected_colon_after, "'case'");
+    SkipUntil(tok::colon);
+    return true;
+  }
+  
+  SourceLocation ColonLoc = ConsumeToken();
+  
+  // Diagnose the common error "switch (X) { case 4: }", which is not valid.
+  if (Tok.getKind() == tok::r_brace) {
+    Diag(Tok, diag::err_label_end_of_compound_statement);
+    return true;
+  }
+  
+  StmtResult SubStmt = ParseStatement();
+
+  // Broken substmt shouldn't prevent the case from being added to the AST.
+  if (SubStmt.isInvalid)
+    SubStmt = Actions.ParseNullStmt(ColonLoc);
+  
+  // TODO: look up enclosing switch stmt.
+  return Actions.ParseCaseStmt(CaseLoc, LHS.Val, DotDotDotLoc, RHSVal, ColonLoc,
+                               SubStmt.Val);
+}
+
+/// ParseDefaultStatement
+///       labeled-statement:
+///         'default' ':' statement
+/// Note that this does not parse the 'statement' at the end.
+///
+Parser::StmtResult Parser::ParseDefaultStatement() {
+  assert(Tok.getKind() == tok::kw_default && "Not a default stmt!");
+  SourceLocation DefaultLoc = ConsumeToken();  // eat the 'default'.
+
+  if (Tok.getKind() != tok::colon) {
+    Diag(Tok, diag::err_expected_colon_after, "'default'");
+    SkipUntil(tok::colon);
+    return true;
+  }
+  
+  SourceLocation ColonLoc = ConsumeToken();
+  
+  // Diagnose the common error "switch (X) {... default: }", which is not valid.
+  if (Tok.getKind() == tok::r_brace) {
+    Diag(Tok, diag::err_label_end_of_compound_statement);
+    return true;
+  }
+
+  StmtResult SubStmt = ParseStatement();
+  if (SubStmt.isInvalid)
+    return true;
+  
+  // TODO: look up enclosing switch stmt.
+  return Actions.ParseDefaultStmt(DefaultLoc, ColonLoc, SubStmt.Val);
+}
+
+
+/// 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 [TODO]
+///         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::StmtResult Parser::ParseCompoundStatement() {
+  assert(Tok.getKind() == tok::l_brace && "Not a compount stmt!");
+  
+  // Enter a scope to hold everything within the compound stmt.
+  EnterScope(0);
+
+  // Parse the statements in the body.
+  StmtResult Body = ParseCompoundStatementBody();
+
+  ExitScope();
+  return Body;
+}
+
+
+/// ParseCompoundStatementBody - Parse a sequence of statements and invoke the
+/// ParseCompoundStmt 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::StmtResult Parser::ParseCompoundStatementBody() {
+  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.
+  
+  llvm::SmallVector<StmtTy*, 32> Stmts;
+  while (Tok.getKind() != tok::r_brace && Tok.getKind() != tok::eof) {
+    StmtResult R = ParseStatementOrDeclaration(false);
+    if (!R.isInvalid && R.Val)
+      Stmts.push_back(R.Val);
+  }
+  
+  // We broke out of the while loop because we found a '}' or EOF.
+  if (Tok.getKind() != tok::r_brace) {
+    Diag(Tok, diag::err_expected_rbrace);
+    return 0;
+  }
+  
+  SourceLocation RBraceLoc = ConsumeBrace();
+  return Actions.ParseCompoundStmt(LBraceLoc, RBraceLoc,
+                                   &Stmts[0], Stmts.size());
+}
+
+/// ParseIfStatement
+///       if-statement: [C99 6.8.4.1]
+///         'if' '(' expression ')' statement
+///         'if' '(' expression ')' statement 'else' statement
+///
+Parser::StmtResult Parser::ParseIfStatement() {
+  assert(Tok.getKind() == tok::kw_if && "Not an if stmt!");
+  SourceLocation IfLoc = ConsumeToken();  // eat the 'if'.
+
+  if (Tok.getKind() != tok::l_paren) {
+    Diag(Tok, diag::err_expected_lparen_after, "if");
+    SkipUntil(tok::semi);
+    return true;
+  }
+  
+  // Parse the condition.
+  ExprResult CondExp = ParseSimpleParenExpression();
+  if (CondExp.isInvalid) {
+    SkipUntil(tok::semi);
+    return true;
+  }
+  
+  // Read the if condition.
+  StmtResult CondStmt = ParseStatement();
+
+  // Broken substmt shouldn't prevent the label from being added to the AST.
+  if (CondStmt.isInvalid)
+    CondStmt = Actions.ParseNullStmt(Tok.getLocation());
+  
+  
+  // If it has an else, parse it.
+  SourceLocation ElseLoc;
+  StmtResult ElseStmt(false);
+  if (Tok.getKind() == tok::kw_else) {
+    ElseLoc = ConsumeToken();
+    ElseStmt = ParseStatement();
+    
+    if (ElseStmt.isInvalid)
+      ElseStmt = Actions.ParseNullStmt(ElseLoc);
+  }
+  
+  return Actions.ParseIfStmt(IfLoc, CondExp.Val, CondStmt.Val,
+                             ElseLoc, ElseStmt.Val);
+}
+
+/// ParseSwitchStatement
+///       switch-statement:
+///         'switch' '(' expression ')' statement
+Parser::StmtResult Parser::ParseSwitchStatement() {
+  assert(Tok.getKind() == tok::kw_switch && "Not a switch stmt!");
+  SourceLocation SwitchLoc = ConsumeToken();  // eat the 'switch'.
+
+  if (Tok.getKind() != tok::l_paren) {
+    Diag(Tok, diag::err_expected_lparen_after, "switch");
+    SkipUntil(tok::semi);
+    return true;
+  }
+  
+  // Start the switch scope.
+  EnterScope(Scope::BreakScope);
+
+  // Parse the condition.
+  ExprResult Cond = ParseSimpleParenExpression();
+  
+  // Read the body statement.
+  StmtResult Body = ParseStatement();
+
+  ExitScope();
+  
+  if (Cond.isInvalid || Body.isInvalid) return true;
+  
+  return Actions.ParseSwitchStmt(SwitchLoc, Cond.Val, Body.Val);
+}
+
+/// ParseWhileStatement
+///       while-statement: [C99 6.8.5.1]
+///         'while' '(' expression ')' statement
+Parser::StmtResult Parser::ParseWhileStatement() {
+  assert(Tok.getKind() == tok::kw_while && "Not a while stmt!");
+  SourceLocation WhileLoc = Tok.getLocation();
+  ConsumeToken();  // eat the 'while'.
+  
+  if (Tok.getKind() != tok::l_paren) {
+    Diag(Tok, diag::err_expected_lparen_after, "while");
+    SkipUntil(tok::semi);
+    return true;
+  }
+  
+  // Start the loop scope.
+  EnterScope(Scope::BreakScope | Scope::ContinueScope);
+
+  // Parse the condition.
+  ExprResult Cond = ParseSimpleParenExpression();
+  
+  // Read the body statement.
+  StmtResult Body = ParseStatement();
+
+  ExitScope();
+  
+  if (Cond.isInvalid || Body.isInvalid) return true;
+  
+  return Actions.ParseWhileStmt(WhileLoc, Cond.Val, Body.Val);
+}
+
+/// ParseDoStatement
+///       do-statement: [C99 6.8.5.2]
+///         'do' statement 'while' '(' expression ')' ';'
+/// Note: this lets the caller parse the end ';'.
+Parser::StmtResult Parser::ParseDoStatement() {
+  assert(Tok.getKind() == tok::kw_do && "Not a do stmt!");
+  SourceLocation DoLoc = ConsumeToken();  // eat the 'do'.
+  
+  // Start the loop scope.
+  EnterScope(Scope::BreakScope | Scope::ContinueScope);
+
+  // Read the body statement.
+  StmtResult Body = ParseStatement();
+
+  if (Tok.getKind() != tok::kw_while) {
+    ExitScope();
+    Diag(Tok, diag::err_expected_while);
+    Diag(DoLoc, diag::err_matching, "do");
+    SkipUntil(tok::semi);
+    return true;
+  }
+  SourceLocation WhileLoc = ConsumeToken();
+  
+  if (Tok.getKind() != tok::l_paren) {
+    ExitScope();
+    Diag(Tok, diag::err_expected_lparen_after, "do/while");
+    SkipUntil(tok::semi);
+    return true;
+  }
+  
+  // Parse the condition.
+  ExprResult Cond = ParseSimpleParenExpression();
+  
+  ExitScope();
+  
+  if (Cond.isInvalid || Body.isInvalid) return true;
+  
+  return Actions.ParseDoStmt(DoLoc, Body.Val, WhileLoc, Cond.Val);
+}
+
+/// ParseForStatement
+///       for-statement: [C99 6.8.5.3]
+///         'for' '(' expr[opt] ';' expr[opt] ';' expr[opt] ')' statement
+///         'for' '(' declaration expr[opt] ';' expr[opt] ')' statement
+Parser::StmtResult Parser::ParseForStatement() {
+  assert(Tok.getKind() == tok::kw_for && "Not a for stmt!");
+  SourceLocation ForLoc = ConsumeToken();  // eat the 'for'.
+  
+  if (Tok.getKind() != tok::l_paren) {
+    Diag(Tok, diag::err_expected_lparen_after, "for");
+    SkipUntil(tok::semi);
+    return true;
+  }
+  
+  EnterScope(Scope::BreakScope | Scope::ContinueScope);
+
+  SourceLocation LParenLoc = ConsumeParen();
+  ExprResult Value;
+  
+  StmtTy *FirstPart = 0;
+  ExprTy *SecondPart = 0;
+  StmtTy *ThirdPart = 0;
+  
+  // Parse the first part of the for specifier.
+  if (Tok.getKind() == tok::semi) {  // for (;
+    // no first part, eat the ';'.
+    ConsumeToken();
+  } else if (isDeclarationSpecifier()) {  // for (int X = 4;
+    // Parse declaration, which eats the ';'.
+    if (!getLang().C99)   // Use of C99-style for loops in C90 mode?
+      Diag(Tok, diag::ext_c99_variable_decl_in_for_loop);
+    DeclTy *aBlockVarDecl = ParseDeclaration(Declarator::ForContext);
+    StmtResult stmtResult = Actions.ParseDeclStmt(aBlockVarDecl);
+    FirstPart = stmtResult.isInvalid ? 0 : stmtResult.Val;
+  } else {
+    Value = ParseExpression();
+
+    // Turn the expression into a stmt.
+    if (!Value.isInvalid) {
+      StmtResult R = Actions.ParseExprStmt(Value.Val);
+      if (!R.isInvalid)
+        FirstPart = R.Val;
+    }
+      
+    if (Tok.getKind() == tok::semi) {
+      ConsumeToken();
+    } else {
+      if (!Value.isInvalid) Diag(Tok, diag::err_expected_semi_for);
+      SkipUntil(tok::semi);
+    }
+  }
+  
+  // Parse the second part of the for specifier.
+  if (Tok.getKind() == tok::semi) {  // for (...;;
+    // no second part.
+    Value = ExprResult();
+  } else {
+    Value = ParseExpression();
+    if (!Value.isInvalid)
+      SecondPart = Value.Val;
+  }
+  
+  if (Tok.getKind() == tok::semi) {
+    ConsumeToken();
+  } else {
+    if (!Value.isInvalid) Diag(Tok, diag::err_expected_semi_for);
+    SkipUntil(tok::semi);
+  }
+  
+  // Parse the third part of the for specifier.
+  if (Tok.getKind() == tok::r_paren) {  // for (...;...;)
+    // no third part.
+    Value = ExprResult();
+  } else {
+    Value = ParseExpression();
+    if (!Value.isInvalid) {
+      // Turn the expression into a stmt.
+      StmtResult R = Actions.ParseExprStmt(Value.Val);
+      if (!R.isInvalid)
+        ThirdPart = R.Val;
+    }
+  }
+  
+  // Match the ')'.
+  SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc);
+  
+  // Read the body statement.
+  StmtResult Body = ParseStatement();
+  
+  // Leave the for-scope.
+  ExitScope();
+    
+  if (Body.isInvalid)
+    return Body;
+  
+  return Actions.ParseForStmt(ForLoc, LParenLoc, FirstPart, SecondPart,
+                              ThirdPart, RParenLoc, Body.Val);
+}
+
+/// ParseGotoStatement
+///       jump-statement:
+///         'goto' identifier ';'
+/// [GNU]   'goto' '*' expression ';'
+///
+/// Note: this lets the caller parse the end ';'.
+///
+Parser::StmtResult Parser::ParseGotoStatement() {
+  assert(Tok.getKind() == tok::kw_goto && "Not a goto stmt!");
+  SourceLocation GotoLoc = ConsumeToken();  // eat the 'goto'.
+  
+  StmtResult Res;
+  if (Tok.getKind() == tok::identifier) {
+    Res = Actions.ParseGotoStmt(GotoLoc, Tok.getLocation(),
+                                Tok.getIdentifierInfo());
+    ConsumeToken();
+  } else if (Tok.getKind() == tok::star && !getLang().NoExtensions) {
+    // GNU indirect goto extension.
+    Diag(Tok, diag::ext_gnu_indirect_goto);
+    SourceLocation StarLoc = ConsumeToken();
+    ExprResult R = ParseExpression();
+    if (R.isInvalid) {  // Skip to the semicolon, but don't consume it.
+      SkipUntil(tok::semi, false, true);
+      return true;
+    }
+    Res = Actions.ParseIndirectGotoStmt(GotoLoc, StarLoc, R.Val);
+  }
+  return Res;
+}
+
+/// ParseContinueStatement
+///       jump-statement:
+///         'continue' ';'
+///
+/// Note: this lets the caller parse the end ';'.
+///
+Parser::StmtResult Parser::ParseContinueStatement() {
+  SourceLocation ContinueLoc = ConsumeToken();  // eat the 'continue'.
+  return Actions.ParseContinueStmt(ContinueLoc, CurScope);
+}
+
+/// ParseBreakStatement
+///       jump-statement:
+///         'break' ';'
+///
+/// Note: this lets the caller parse the end ';'.
+///
+Parser::StmtResult Parser::ParseBreakStatement() {
+  SourceLocation BreakLoc = ConsumeToken();  // eat the 'break'.
+  return Actions.ParseBreakStmt(BreakLoc, CurScope);
+}
+
+/// ParseReturnStatement
+///       jump-statement:
+///         'return' expression[opt] ';'
+Parser::StmtResult Parser::ParseReturnStatement() {
+  assert(Tok.getKind() == tok::kw_return && "Not a return stmt!");
+  SourceLocation ReturnLoc = ConsumeToken();  // eat the 'return'.
+  
+  ExprResult R(0);
+  if (Tok.getKind() != tok::semi) {
+    R = ParseExpression();
+    if (R.isInvalid) {  // Skip to the semicolon, but don't consume it.
+      SkipUntil(tok::semi, false, true);
+      return true;
+    }
+  }
+  return Actions.ParseReturnStmt(ReturnLoc, R.Val);
+}
+
+/// ParseAsmStatement - Parse a GNU extended asm statement.
+/// [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
+///
+Parser::StmtResult Parser::ParseAsmStatement() {
+  assert(Tok.getKind() == tok::kw_asm && "Not an asm stmt");
+  ConsumeToken();
+  
+  DeclSpec DS;
+  SourceLocation Loc = Tok.getLocation();
+  ParseTypeQualifierListOpt(DS);
+  
+  // 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.TypeQualifiers & DeclSpec::TQ_volatile;
+  
+  if (Tok.getKind() != tok::l_paren) {
+    Diag(Tok, diag::err_expected_lparen_after, "asm");
+    SkipUntil(tok::r_paren);
+    return true;
+  }
+  Loc = ConsumeParen();
+  
+  ParseAsmStringLiteral();
+  
+  // Parse Outputs, if present.
+  ParseAsmOperandsOpt();
+  
+  // Parse Inputs, if present.
+  ParseAsmOperandsOpt();
+  
+  // Parse the clobbers, if present.
+  if (Tok.getKind() == tok::colon) {
+    ConsumeToken();
+    
+    if (isTokenStringLiteral()) {
+      // Parse the asm-string list for clobbers.
+      while (1) {
+        ParseAsmStringLiteral();
+
+        if (Tok.getKind() != tok::comma) break;
+        ConsumeToken();
+      }
+    }
+  }
+  
+  MatchRHSPunctuation(tok::r_paren, Loc);
+  
+  // FIXME: Implement action for asm parsing.
+  return false;
+}
+
+/// ParseAsmOperands - Parse the asm-operands production as used by
+/// asm-statement.  We also parse a leading ':' token.  If the leading colon is
+/// not present, we do not parse anything.
+///
+/// [GNU] asm-operands:
+///         asm-operand
+///         asm-operands ',' asm-operand
+///
+/// [GNU] asm-operand:
+///         asm-string-literal '(' expression ')'
+///         '[' identifier ']' asm-string-literal '(' expression ')'
+///
+void Parser::ParseAsmOperandsOpt() {
+  // Only do anything if this operand is present.
+  if (Tok.getKind() != tok::colon) return;
+  ConsumeToken();
+  
+  // 'asm-operands' isn't present?
+  if (!isTokenStringLiteral() && Tok.getKind() != tok::l_square)
+    return;
+  
+  while (1) {
+    // Read the [id] if present.
+    if (Tok.getKind() == tok::l_square) {
+      SourceLocation Loc = ConsumeBracket();
+      
+      if (Tok.getKind() != tok::identifier) {
+        Diag(Tok, diag::err_expected_ident);
+        SkipUntil(tok::r_paren);
+        return;
+      }
+      MatchRHSPunctuation(tok::r_square, Loc);
+    }
+    
+    ParseAsmStringLiteral();
+
+    if (Tok.getKind() != tok::l_paren) {
+      Diag(Tok, diag::err_expected_lparen_after, "asm operand");
+      SkipUntil(tok::r_paren);
+      return;
+    }
+    
+    // Read the parenthesized expression.
+    ExprResult Res = ParseSimpleParenExpression();
+    if (Res.isInvalid) {
+      SkipUntil(tok::r_paren);
+      return;
+    }
+
+    // Eat the comma and continue parsing if it exists.
+    if (Tok.getKind() != tok::comma) return;
+    ConsumeToken();
+  }
+}
diff --git a/Parse/Parser.cpp b/Parse/Parser.cpp
new file mode 100644
index 0000000..251febb
--- /dev/null
+++ b/Parse/Parser.cpp
@@ -0,0 +1,615 @@
+//===--- Parser.cpp - C Language Family Parser ----------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file was developed by Chris Lattner and 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/DeclSpec.h"
+#include "clang/Parse/Scope.h"
+using namespace clang;
+
+Parser::Parser(Preprocessor &pp, Action &actions)
+  : PP(pp), Actions(actions), Diags(PP.getDiagnostics()) {
+  Tok.setKind(tok::eof);
+  CurScope = 0;
+  
+  ParenCount = BracketCount = BraceCount = 0;
+}
+
+///  Out-of-line virtual destructor to provide home for Action class.
+Action::~Action() {}
+
+
+void Parser::Diag(SourceLocation Loc, unsigned DiagID,
+                  const std::string &Msg) {
+  Diags.Report(Loc, DiagID, &Msg, 1);
+}
+
+/// 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.getKind() == 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::err_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.getKind() == ExpectedTok) {
+    ConsumeAnyToken();
+    return false;
+  }
+  
+  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 false).  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.getKind() == 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
+//===----------------------------------------------------------------------===//
+
+/// ScopeCache - Cache scopes to avoid malloc traffic.
+/// FIXME: eliminate this static ctor
+static llvm::SmallVector<Scope*, 16> ScopeCache;
+
+/// EnterScope - Start a new scope.
+void Parser::EnterScope(unsigned ScopeFlags) {
+  if (!ScopeCache.empty()) {
+    Scope *N = ScopeCache.back();
+    ScopeCache.pop_back();
+    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.
+  Actions.PopScope(Tok.getLocation(), CurScope);
+  
+  Scope *Old = CurScope;
+  CurScope = Old->getParent();
+  
+  if (ScopeCache.size() == 16)
+    delete Old;
+  else
+    ScopeCache.push_back(Old);
+}
+
+
+
+
+//===----------------------------------------------------------------------===//
+// C99 6.9: External Definitions.
+//===----------------------------------------------------------------------===//
+
+Parser::~Parser() {
+  // If we still have scopes active, delete the scope tree.
+  delete CurScope;
+  
+  // Free the scope cache.
+  while (!ScopeCache.empty()) {
+    delete ScopeCache.back();
+    ScopeCache.pop_back();
+  }
+}
+
+/// Initialize - Warm up the parser.
+///
+void Parser::Initialize() {
+  // Prime the lexer look-ahead.
+  ConsumeToken();
+  
+  // Create the global scope, install it as the current scope.
+  assert(CurScope == 0 && "A scope is already active?");
+  EnterScope(0);
+  
+  
+  // Install builtin types.
+  // TODO: Move this someplace more useful.
+  {
+    const char *Dummy;
+    
+    //__builtin_va_list
+    DeclSpec DS;
+    bool Error = DS.SetStorageClassSpec(DeclSpec::SCS_typedef, SourceLocation(),
+                                        Dummy);
+    
+    // TODO: add a 'TST_builtin' type?
+    Error |= DS.SetTypeSpecType(DeclSpec::TST_int, SourceLocation(), Dummy);
+    assert(!Error && "Error setting up __builtin_va_list!");
+    
+    Declarator D(DS, Declarator::FileContext);
+    D.SetIdentifier(PP.getIdentifierInfo("__builtin_va_list"),SourceLocation());
+    Actions.ParseDeclarator(CurScope, D, 0, 0);
+  }
+  
+  if (Tok.getKind() == tok::eof)  // Empty source file is an extension.
+    Diag(Tok, diag::ext_empty_source_file);
+}
+
+/// ParseTopLevelDecl - Parse one top-level declaration, return whatever the
+/// action tells us to.  This returns true if the EOF was encountered.
+bool Parser::ParseTopLevelDecl(DeclTy*& Result) {
+  Result = 0;
+  if (Tok.getKind() == tok::eof) return true;
+  
+  Result = ParseExternalDeclaration();
+  return false;
+}
+
+/// Finalize - Shut down the parser.
+///
+void Parser::Finalize() {
+  ExitScope();
+  assert(CurScope == 0 && "Scope imbalance!");
+}
+
+/// ParseTranslationUnit:
+///       translation-unit: [C99 6.9]
+///         external-declaration 
+///         translation-unit external-declaration 
+void Parser::ParseTranslationUnit() {
+  Initialize();
+  
+  DeclTy *Res;
+  while (!ParseTopLevelDecl(Res))
+    /*parse them all*/;
+  
+  Finalize();
+}
+
+/// ParseExternalDeclaration:
+///       external-declaration: [C99 6.9]
+///         function-definition        [TODO]
+///         declaration                [TODO]
+/// [EXT]   ';'
+/// [GNU]   asm-definition
+/// [GNU]   __extension__ external-declaration     [TODO]
+/// [OBJC]  objc-class-definition
+/// [OBJC]  objc-class-declaration
+/// [OBJC]  objc-alias-declaration
+/// [OBJC]  objc-protocol-definition
+/// [OBJC]  objc-method-definition
+/// [OBJC]  @end
+///
+/// [GNU] asm-definition:
+///         simple-asm-expr ';'
+///
+Parser::DeclTy *Parser::ParseExternalDeclaration() {
+  switch (Tok.getKind()) {
+  case tok::semi:
+    Diag(Tok, diag::ext_top_level_semi);
+    ConsumeToken();
+    // TODO: Invoke action for top-level semicolon.
+    return 0;
+  case tok::kw_asm:
+    ParseSimpleAsm();
+    ExpectAndConsume(tok::semi, diag::err_expected_semi_after,
+                     "top-level asm block");
+    // TODO: Invoke action for top-level asm.
+    return 0;
+  case tok::at:
+    // @ is not a legal token unless objc is enabled, no need to check.
+    ParseObjCAtDirectives();
+    return 0;
+  case tok::minus:
+    if (getLang().ObjC1) {
+      ParseObjCInstanceMethodDeclaration();
+    } else {
+      Diag(Tok, diag::err_expected_external_declaration);
+      ConsumeToken();
+    }
+    return 0;
+  case tok::plus:
+    if (getLang().ObjC1) {
+      ParseObjCClassMethodDeclaration();
+    } else {
+      Diag(Tok, diag::err_expected_external_declaration);
+      ConsumeToken();
+    }
+    return 0;
+  case tok::kw_typedef:
+    // A function definition cannot start with a 'typedef' keyword.
+    return ParseDeclaration(Declarator::FileContext);
+  default:
+    // We can't tell whether this is a function-definition or declaration yet.
+    return ParseDeclarationOrFunctionDefinition();
+  }
+}
+
+/// 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.
+///
+///       function-definition: [C99 6.9.1]
+///         declaration-specifiers[opt] declarator declaration-list[opt] 
+///                 compound-statement                           [TODO]
+///       declaration: [C99 6.7]
+///         declaration-specifiers init-declarator-list[opt] ';' [TODO]
+/// [!C99]  init-declarator-list ';'                             [TODO]
+/// [OMP]   threadprivate-directive                              [TODO]
+///
+Parser::DeclTy *Parser::ParseDeclarationOrFunctionDefinition() {
+  // Parse the common declaration-specifiers piece.
+  DeclSpec DS;
+  ParseDeclarationSpecifiers(DS);
+
+  // C99 6.7.2.3p6: Handle "struct-or-union identifier;", "enum { X };"
+  // declaration-specifiers init-declarator-list[opt] ';'
+  if (Tok.getKind() == tok::semi) {
+    ConsumeToken();
+    return Actions.ParsedFreeStandingDeclSpec(CurScope, DS);
+  }
+  
+  // Parse the first declarator.
+  Declarator DeclaratorInfo(DS, Declarator::FileContext);
+  ParseDeclarator(DeclaratorInfo);
+  // Error parsing the declarator?
+  if (DeclaratorInfo.getIdentifier() == 0) {
+    // If so, skip until the semi-colon or a }.
+    SkipUntil(tok::r_brace, true);
+    if (Tok.getKind() == tok::semi)
+      ConsumeToken();
+    return 0;
+  }
+
+  // If the declarator is the start of a function definition, handle it.
+  if (Tok.getKind() == tok::equal ||  // int X()=  -> not a function def
+      Tok.getKind() == tok::comma ||  // int X(),  -> not a function def
+      Tok.getKind() == tok::semi  ||  // int X();  -> not a function def
+      Tok.getKind() == tok::kw_asm || // int X() __asm__ -> not a fn def
+      Tok.getKind() == tok::kw___attribute) {// int X() __attr__ -> not a fn def
+    // FALL THROUGH.
+  } else if (DeclaratorInfo.isFunctionDeclarator() &&
+             (Tok.getKind() == tok::l_brace ||  // int X() {}
+              isDeclarationSpecifier())) {      // int X(f) int f; {}
+    return ParseFunctionDefinition(DeclaratorInfo);
+  } else {
+    if (DeclaratorInfo.isFunctionDeclarator())
+      Diag(Tok, diag::err_expected_fn_body);
+    else
+      Diag(Tok, diag::err_expected_after_declarator);
+    SkipUntil(tok::semi);
+    return 0;
+  }
+
+  // Parse the init-declarator-list for a normal declaration.
+  return ParseInitDeclaratorListAfterFirstDeclarator(DeclaratorInfo);
+}
+
+/// 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.
+///
+///         declaration-specifiers[opt] declarator declaration-list[opt] 
+///                 compound-statement                           [TODO]
+///
+Parser::DeclTy *Parser::ParseFunctionDefinition(Declarator &D) {
+  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 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);
+
+  // Enter a scope for the function body.
+  EnterScope(Scope::FnScope);
+  
+  // Tell the actions module that we have entered a function definition with the
+  // specified Declarator for the function.
+  DeclTy *Res = Actions.ParseStartOfFunctionDef(CurScope, D);
+  
+  
+  // We should have an opening brace now.
+  if (Tok.getKind() != tok::l_brace) {
+    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.getKind() != tok::l_brace) {
+      ExitScope();
+      return 0;
+    }
+  }
+  
+  // 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.
+  StmtResult FnBody = ParseCompoundStatementBody();
+  if (FnBody.isInvalid) {
+    ExitScope();
+    return 0;
+  }
+
+  // Leave the function body scope.
+  ExitScope();
+
+  // TODO: Pass argument information.
+  return Actions.ParseFunctionDefBody(Res, FnBody.Val);
+}
+
+/// 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;
+
+  // 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.getKind() == 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) {
+      DeclTy *AttrList;
+      // If attributes are present, parse them.
+      if (Tok.getKind() == tok::kw___attribute)
+        // FIXME: attach attributes too.
+        AttrList = ParseAttributes();
+      
+      // Ask the actions module to compute the type for this declarator.
+      Action::TypeResult TR =
+        Actions.ParseParamDeclaratorType(CurScope, ParmDeclarator);
+      if (!TR.isInvalid && 
+          // 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()->getName());
+            break;
+          }
+          
+          if (FTI.ArgInfo[i].Ident == ParmDeclarator.getIdentifier()) {
+            // Reject redefinitions of parameters.
+            if (FTI.ArgInfo[i].TypeInfo) {
+              Diag(ParmDeclarator.getIdentifierLoc(),
+                   diag::err_param_redefinition,
+                   ParmDeclarator.getIdentifier()->getName());
+            } else {
+              FTI.ArgInfo[i].TypeInfo = TR.Val;
+            }
+            break;
+          }
+        }
+      }
+
+      // If we don't have a comma, it is either the end of the list (a ';') or
+      // an error, bail out.
+      if (Tok.getKind() != tok::comma)
+        break;
+      
+      // Consume the comma.
+      ConsumeToken();
+      
+      // Parse the next declarator.
+      ParmDeclarator.clear();
+      ParseDeclarator(ParmDeclarator);
+    }
+    
+    if (Tok.getKind() == tok::semi) {
+      ConsumeToken();
+    } else {
+      Diag(Tok, diag::err_parse_error);
+      // Skip to end of block or statement
+      SkipUntil(tok::semi, true);
+      if (Tok.getKind() == tok::semi)
+        ConsumeToken();
+    }
+  }
+  
+  // The actions module must verify that all arguments were declared.
+}
+
+
+/// 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
+///
+void Parser::ParseAsmStringLiteral() {
+  if (!isTokenStringLiteral()) {
+    Diag(Tok, diag::err_expected_string_literal);
+    return;
+  }
+  
+  ExprResult Res = ParseStringLiteralExpression();
+  if (Res.isInvalid) return;
+  
+  // TODO: Diagnose: wide string literal in 'asm'
+}
+
+/// ParseSimpleAsm
+///
+/// [GNU] simple-asm-expr:
+///         'asm' '(' asm-string-literal ')'
+///
+void Parser::ParseSimpleAsm() {
+  assert(Tok.getKind() == tok::kw_asm && "Not an asm!");
+  ConsumeToken();
+  
+  if (Tok.getKind() != tok::l_paren) {
+    Diag(Tok, diag::err_expected_lparen_after, "asm");
+    return;
+  }
+  
+  SourceLocation Loc = ConsumeParen();
+  
+  ParseAsmStringLiteral();
+  
+  MatchRHSPunctuation(tok::r_paren, Loc);
+}
+