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/Sema/ASTStreamer.cpp b/Sema/ASTStreamer.cpp
new file mode 100644
index 0000000..1057d93
--- /dev/null
+++ b/Sema/ASTStreamer.cpp
@@ -0,0 +1,111 @@
+//===--- ASTStreamer.cpp - Provide streaming interface to ASTs ------------===//
+//
+//                     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 ASTStreamer interface.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Sema/ASTStreamer.h"
+#include "clang/AST/ASTContext.h"
+#include "Sema.h"
+#include "clang/Parse/Action.h"
+#include "clang/Parse/Parser.h"
+using namespace clang;
+
+namespace {
+  class ASTStreamer {
+    Parser P;
+    std::vector<Decl*> LastInGroupList;
+  public:
+    ASTStreamer(Preprocessor &pp, ASTContext &ctxt, unsigned MainFileID)
+      : P(pp, *new Sema(pp, ctxt, LastInGroupList)) {
+      pp.EnterSourceFile(MainFileID, 0, true);
+      
+      // Initialize the parser.
+      P.Initialize();
+    }
+    
+    /// ReadTopLevelDecl - Parse and return the next top-level declaration.
+    Decl *ReadTopLevelDecl();
+    
+    void PrintStats() const;
+
+    ~ASTStreamer() {
+      P.Finalize();
+      delete &P.getActions();
+    }
+  };
+}
+
+/// ReadTopLevelDecl - Parse and return the next top-level declaration.
+///
+Decl *ASTStreamer::ReadTopLevelDecl() {
+  Parser::DeclTy *Result;
+  
+  /// If the previous time through we read something like 'int X, Y', return
+  /// the next declarator.
+  if (!LastInGroupList.empty()) {
+    Result = LastInGroupList.back();
+    LastInGroupList.pop_back();
+    return static_cast<Decl*>(Result);
+  }
+  
+  do {
+    if (P.ParseTopLevelDecl(Result))
+      return 0;  // End of file.
+    
+    // If we got a null return and something *was* parsed, try again.  This
+    // is due to a top-level semicolon, an action override, or a parse error
+    // skipping something.
+  } while (Result == 0);
+  
+  // If we parsed a declspec with multiple declarators, reverse the list and
+  // return the first one.
+  if (!LastInGroupList.empty()) {
+    LastInGroupList.push_back((Decl*)Result);
+    std::reverse(LastInGroupList.begin(), LastInGroupList.end());
+    Result = LastInGroupList.back();
+    LastInGroupList.pop_back();
+  }
+  
+  return static_cast<Decl*>(Result);
+}
+
+void ASTStreamer::PrintStats() const {
+}
+
+//===----------------------------------------------------------------------===//
+// Public interface to the file
+//===----------------------------------------------------------------------===//
+
+/// ASTStreamer_Init - Create an ASTStreamer with the specified preprocessor
+/// and FileID.
+ASTStreamerTy *clang::ASTStreamer_Init(Preprocessor &pp, ASTContext &ctxt,
+                                       unsigned MainFileID) {
+  return new ASTStreamer(pp, ctxt, MainFileID);
+}
+
+/// ASTStreamer_ReadTopLevelDecl - Parse and return one top-level declaration. This
+/// returns null at end of file.
+Decl *clang::ASTStreamer_ReadTopLevelDecl(ASTStreamerTy *Streamer) {
+  return static_cast<ASTStreamer*>(Streamer)->ReadTopLevelDecl();
+}
+
+
+/// ASTStreamer_PrintStats - Emit statistic information to stderr.
+///
+void clang::ASTStreamer_PrintStats(ASTStreamerTy *Streamer) {
+  return static_cast<ASTStreamer*>(Streamer)->PrintStats();
+}
+
+/// ASTStreamer_Terminate - Gracefully shut down the streamer.
+///
+void clang::ASTStreamer_Terminate(ASTStreamerTy *Streamer) {
+  delete static_cast<ASTStreamer*>(Streamer);
+}
diff --git a/Sema/Makefile b/Sema/Makefile
new file mode 100644
index 0000000..83a1eff
--- /dev/null
+++ b/Sema/Makefile
@@ -0,0 +1,23 @@
+##===- clang/Sema/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 semantic analyzer and AST builder library for the 
+#  C-Language front-end.
+#
+##===----------------------------------------------------------------------===##
+
+LEVEL = ../../..
+LIBRARYNAME := clangSEMA
+BUILD_ARCHIVE = 1
+CXXFLAGS = -fno-rtti
+
+CPPFLAGS += -I$(PROJ_SRC_DIR)/../include
+
+include $(LEVEL)/Makefile.common
+
diff --git a/Sema/Sema.cpp b/Sema/Sema.cpp
new file mode 100644
index 0000000..64c18a8
--- /dev/null
+++ b/Sema/Sema.cpp
@@ -0,0 +1,88 @@
+//===--- Sema.cpp - AST Builder and Semantic Analysis Implementation ------===//
+//
+//                     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 actions class which performs semantic analysis and
+// builds an AST out of a parse stream.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Sema.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/Lex/Preprocessor.h"
+#include "clang/Basic/Diagnostic.h"
+using namespace clang;
+
+Sema::Sema(Preprocessor &pp, ASTContext &ctxt, std::vector<Decl*> &prevInGroup)
+  : PP(pp), Context(ctxt), CurFunctionDecl(0), LastInGroupList(prevInGroup) {
+}
+
+//===----------------------------------------------------------------------===//
+// Helper functions.
+//===----------------------------------------------------------------------===//
+
+bool Sema::Diag(SourceLocation Loc, unsigned DiagID) {
+  PP.getDiagnostics().Report(Loc, DiagID);
+  return true;
+}
+
+bool Sema::Diag(SourceLocation Loc, unsigned DiagID, const std::string &Msg) {
+  PP.getDiagnostics().Report(Loc, DiagID, &Msg, 1);
+  return true;
+}
+
+bool Sema::Diag(SourceLocation Loc, unsigned DiagID, const std::string &Msg1,
+                const std::string &Msg2) {
+  std::string MsgArr[] = { Msg1, Msg2 };
+  PP.getDiagnostics().Report(Loc, DiagID, MsgArr, 2);
+  return true;
+}
+
+bool Sema::Diag(SourceLocation Loc, unsigned DiagID, SourceRange Range) {
+  PP.getDiagnostics().Report(Loc, DiagID, 0, 0, &Range, 1);
+  return true;
+}
+
+bool Sema::Diag(SourceLocation Loc, unsigned DiagID, const std::string &Msg,
+                SourceRange Range) {
+  PP.getDiagnostics().Report(Loc, DiagID, &Msg, 1, &Range, 1);
+  return true;
+}
+
+bool Sema::Diag(SourceLocation Loc, unsigned DiagID, const std::string &Msg1,
+                const std::string &Msg2, SourceRange Range) {
+  std::string MsgArr[] = { Msg1, Msg2 };
+  PP.getDiagnostics().Report(Loc, DiagID, MsgArr, 2, &Range, 1);
+  return true;
+}
+
+bool Sema::Diag(SourceLocation Loc, unsigned DiagID,
+                SourceRange R1, SourceRange R2) {
+  SourceRange RangeArr[] = { R1, R2 };
+  PP.getDiagnostics().Report(Loc, DiagID, 0, 0, RangeArr, 2);
+  return true;
+}
+
+bool Sema::Diag(SourceLocation Loc, unsigned DiagID, const std::string &Msg,
+                SourceRange R1, SourceRange R2) {
+  SourceRange RangeArr[] = { R1, R2 };
+  PP.getDiagnostics().Report(Loc, DiagID, &Msg, 1, RangeArr, 2);
+  return true;
+}
+
+bool Sema::Diag(SourceLocation Range, unsigned DiagID, const std::string &Msg1,
+                const std::string &Msg2, SourceRange R1, SourceRange R2) {
+  std::string MsgArr[] = { Msg1, Msg2 };
+  SourceRange RangeArr[] = { R1, R2 };
+  PP.getDiagnostics().Report(Range, DiagID, MsgArr, 2, RangeArr, 2);
+  return true;
+}
+
+const LangOptions &Sema::getLangOptions() const {
+  return PP.getLangOptions();
+}
diff --git a/Sema/Sema.h b/Sema/Sema.h
new file mode 100644
index 0000000..ac85868
--- /dev/null
+++ b/Sema/Sema.h
@@ -0,0 +1,353 @@
+//===--- Sema.h - Semantic Analysis & AST Building --------------*- C++ -*-===//
+//
+//                     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 defines the Sema class, which performs semantic analysis and
+// builds ASTs.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_AST_SEMA_H
+#define LLVM_CLANG_AST_SEMA_H
+
+#include "clang/Parse/Action.h"
+#include "llvm/ADT/DenseMap.h"
+#include <vector>
+#include <string>
+
+namespace clang {
+  class ASTContext;
+  class Preprocessor;
+  class Decl;
+  class Expr;
+  class VarDecl;
+  class ParmVarDecl;
+  class TypedefDecl;
+  class FunctionDecl;
+  class QualType;
+  class LangOptions;
+  class DeclaratorChunk;
+  class LexerToken;
+  class IntegerLiteral;
+  class ArrayType;
+  class LabelStmt;
+  
+/// Sema - This implements semantic analysis and AST building for C.
+class Sema : public Action {
+  Preprocessor &PP;
+  
+  ASTContext &Context;
+  
+  /// CurFunctionDecl - If inside of a function body, this contains a pointer to
+  /// the function decl for the function being parsed.
+  FunctionDecl *CurFunctionDecl;
+  
+  /// LastInGroupList - This vector is populated when there are multiple
+  /// declarators in a single decl group (e.g. "int A, B, C").  In this case,
+  /// all but the last decl will be entered into this.  This is used by the
+  /// ASTStreamer.
+  std::vector<Decl*> &LastInGroupList;
+  
+  /// LabelMap - This is a mapping from label identifiers to the LabelStmt for
+  /// it (which acts like the label decl in some ways).  Forward referenced
+  /// labels have a LabelStmt created for them with a null location & SubStmt.
+  llvm::DenseMap<IdentifierInfo*, LabelStmt*> LabelMap;
+public:
+  Sema(Preprocessor &pp, ASTContext &ctxt, std::vector<Decl*> &prevInGroup);
+  
+  const LangOptions &getLangOptions() const;
+  
+  /// The primitive diagnostic helpers - always returns true, which simplifies 
+  /// error handling (i.e. less code).
+  bool Diag(SourceLocation Loc, unsigned DiagID);
+  bool Diag(SourceLocation Loc, unsigned DiagID, const std::string &Msg);
+  bool Diag(SourceLocation Loc, unsigned DiagID, const std::string &Msg1,
+            const std::string &Msg2);
+
+  /// More expressive diagnostic helpers for expressions (say that 6 times:-)
+  bool Diag(SourceLocation Loc, unsigned DiagID, SourceRange R1);
+  bool Diag(SourceLocation Loc, unsigned DiagID, 
+            SourceRange R1, SourceRange R2);
+  bool Diag(SourceLocation Loc, unsigned DiagID, const std::string &Msg,
+            SourceRange R1);
+  bool Diag(SourceLocation Loc, unsigned DiagID, const std::string &Msg,
+            SourceRange R1, SourceRange R2);
+  bool Diag(SourceLocation Loc, unsigned DiagID, const std::string &Msg1, 
+            const std::string &Msg2, SourceRange R1);
+  bool Diag(SourceLocation Loc, unsigned DiagID, 
+            const std::string &Msg1, const std::string &Msg2, 
+            SourceRange R1, SourceRange R2);
+
+  //===--------------------------------------------------------------------===//
+  // Type Analysis / Processing: SemaType.cpp.
+  //
+  QualType GetTypeForDeclarator(Declarator &D, Scope *S);
+  
+  virtual TypeResult ParseTypeName(Scope *S, Declarator &D);
+  
+  virtual TypeResult ParseParamDeclaratorType(Scope *S, Declarator &D);
+private:
+  //===--------------------------------------------------------------------===//
+  // Symbol table / Decl tracking callbacks: SemaDecl.cpp.
+  //
+  virtual DeclTy *isTypeName(const IdentifierInfo &II, Scope *S) const;
+  virtual DeclTy *ParseDeclarator(Scope *S, Declarator &D, ExprTy *Init,
+                                  DeclTy *LastInGroup);
+  virtual DeclTy *FinalizeDeclaratorGroup(Scope *S, DeclTy *Group);
+
+  virtual DeclTy *ParseStartOfFunctionDef(Scope *S, Declarator &D);
+  virtual DeclTy *ParseFunctionDefBody(DeclTy *Decl, StmtTy *Body);
+  virtual void PopScope(SourceLocation Loc, Scope *S);
+
+  /// ParsedFreeStandingDeclSpec - This method is invoked when a declspec with
+  /// no declarator (e.g. "struct foo;") is parsed.
+  virtual DeclTy *ParsedFreeStandingDeclSpec(Scope *S, DeclSpec &DS);  
+  
+  virtual DeclTy *ParseTag(Scope *S, unsigned TagType, TagKind TK,
+                           SourceLocation KWLoc, IdentifierInfo *Name,
+                           SourceLocation NameLoc, AttributeList *Attr);
+  virtual DeclTy *ParseField(Scope *S, DeclTy *TagDecl,SourceLocation DeclStart,
+                             Declarator &D, ExprTy *BitfieldWidth);
+  virtual void ParseRecordBody(SourceLocation RecLoc, DeclTy *TagDecl,
+                               DeclTy **Fields, unsigned NumFields);
+  virtual DeclTy *ParseEnumConstant(Scope *S, DeclTy *EnumDecl,
+                                    DeclTy *LastEnumConstant,
+                                    SourceLocation IdLoc, IdentifierInfo *Id,
+                                    SourceLocation EqualLoc, ExprTy *Val);
+  virtual void ParseEnumBody(SourceLocation EnumLoc, DeclTy *EnumDecl,
+                             DeclTy **Elements, unsigned NumElements);
+private:
+  /// Subroutines of ParseDeclarator()...
+  TypedefDecl *ParseTypedefDecl(Scope *S, Declarator &D, Decl *LastDeclarator);
+  TypedefDecl *MergeTypeDefDecl(TypedefDecl *New, Decl *Old);
+  FunctionDecl *MergeFunctionDecl(FunctionDecl *New, Decl *Old);
+  VarDecl *MergeVarDecl(VarDecl *New, Decl *Old);
+  /// AddTopLevelDecl - called after the decl has been fully processed.
+  /// Allows for bookkeeping and post-processing of each declaration.
+  void AddTopLevelDecl(Decl *current, Decl *last);
+
+  /// More parsing and symbol table subroutines...
+  ParmVarDecl *ParseParamDeclarator(DeclaratorChunk &FI, unsigned ArgNo,
+                                    Scope *FnBodyScope);
+  Decl *LookupScopedDecl(IdentifierInfo *II, unsigned NSI, SourceLocation IdLoc,
+                         Scope *S);  
+  Decl *LazilyCreateBuiltin(IdentifierInfo *II, unsigned ID, Scope *S);
+  Decl *ImplicitlyDefineFunction(SourceLocation Loc, IdentifierInfo &II,
+                                 Scope *S);
+  // Decl attributes - this routine is the top level dispatcher. 
+  void HandleDeclAttributes(Decl *New, AttributeList *declspec_prefix,
+                            AttributeList *declarator_postfix);
+  void HandleDeclAttribute(Decl *New, AttributeList *rawAttr);
+                                
+  // HandleVectorTypeAttribute - this attribute is only applicable to 
+  // integral and float scalars, although arrays, pointers, and function
+  // return values are allowed in conjunction with this construct. Aggregates
+  // with this attribute are invalid, even if they are of the same size as a
+  // corresponding scalar.
+  // The raw attribute should contain precisely 1 argument, the vector size 
+  // for the variable, measured in bytes. If curType and rawAttr are well
+  // formed, this routine will return a new vector type.
+  QualType HandleVectorTypeAttribute(QualType curType, AttributeList *rawAttr);
+  
+  //===--------------------------------------------------------------------===//
+  // Statement Parsing Callbacks: SemaStmt.cpp.
+public:
+  virtual StmtResult ParseExprStmt(ExprTy *Expr);
+  
+  virtual StmtResult ParseNullStmt(SourceLocation SemiLoc);
+  virtual StmtResult ParseCompoundStmt(SourceLocation L, SourceLocation R,
+                                       StmtTy **Elts, unsigned NumElts);
+  virtual StmtResult ParseDeclStmt(DeclTy *Decl);
+  virtual StmtResult ParseCaseStmt(SourceLocation CaseLoc, ExprTy *LHSVal,
+                                   SourceLocation DotDotDotLoc, ExprTy *RHSVal,
+                                   SourceLocation ColonLoc, StmtTy *SubStmt);
+  virtual StmtResult ParseDefaultStmt(SourceLocation DefaultLoc,
+                                      SourceLocation ColonLoc, StmtTy *SubStmt);
+  virtual StmtResult ParseLabelStmt(SourceLocation IdentLoc, IdentifierInfo *II,
+                                    SourceLocation ColonLoc, StmtTy *SubStmt);
+  virtual StmtResult ParseIfStmt(SourceLocation IfLoc, ExprTy *CondVal,
+                                 StmtTy *ThenVal, SourceLocation ElseLoc,
+                                 StmtTy *ElseVal);
+  virtual StmtResult ParseSwitchStmt(SourceLocation SwitchLoc, ExprTy *Cond,
+                                     StmtTy *Body);
+  virtual StmtResult ParseWhileStmt(SourceLocation WhileLoc, ExprTy *Cond,
+                                    StmtTy *Body);
+  virtual StmtResult ParseDoStmt(SourceLocation DoLoc, StmtTy *Body,
+                                 SourceLocation WhileLoc, ExprTy *Cond);
+  
+  virtual StmtResult ParseForStmt(SourceLocation ForLoc, 
+                                  SourceLocation LParenLoc, 
+                                  StmtTy *First, ExprTy *Second, ExprTy *Third,
+                                  SourceLocation RParenLoc, StmtTy *Body);
+  virtual StmtResult ParseGotoStmt(SourceLocation GotoLoc,
+                                   SourceLocation LabelLoc,
+                                   IdentifierInfo *LabelII);
+  virtual StmtResult ParseIndirectGotoStmt(SourceLocation GotoLoc,
+                                           SourceLocation StarLoc,
+                                           ExprTy *DestExp);
+  virtual StmtResult ParseContinueStmt(SourceLocation ContinueLoc,
+                                       Scope *CurScope);
+  virtual StmtResult ParseBreakStmt(SourceLocation GotoLoc, Scope *CurScope);
+  
+  virtual StmtResult ParseReturnStmt(SourceLocation ReturnLoc,
+                                     ExprTy *RetValExp);
+  
+  //===--------------------------------------------------------------------===//
+  // Expression Parsing Callbacks: SemaExpr.cpp.
+
+  // Primary Expressions.
+  virtual ExprResult ParseIdentifierExpr(Scope *S, SourceLocation Loc,
+                                         IdentifierInfo &II,
+                                         bool HasTrailingLParen);
+  virtual ExprResult ParseSimplePrimaryExpr(SourceLocation Loc,
+                                            tok::TokenKind Kind);
+  virtual ExprResult ParseNumericConstant(const LexerToken &);
+  virtual ExprResult ParseCharacterConstant(const LexerToken &);
+  virtual ExprResult ParseParenExpr(SourceLocation L, SourceLocation R,
+                                    ExprTy *Val);
+
+  /// ParseStringLiteral - The specified tokens were lexed as pasted string
+  /// fragments (e.g. "foo" "bar" L"baz").
+  virtual ExprResult ParseStringLiteral(const LexerToken *Toks, unsigned NumToks);
+    
+  // Binary/Unary Operators.  'Tok' is the token for the operator.
+  virtual ExprResult ParseUnaryOp(SourceLocation OpLoc, tok::TokenKind Op,
+                                  ExprTy *Input);
+  virtual ExprResult 
+    ParseSizeOfAlignOfTypeExpr(SourceLocation OpLoc, bool isSizeof, 
+                               SourceLocation LParenLoc, TypeTy *Ty,
+                               SourceLocation RParenLoc);
+  
+  virtual ExprResult ParsePostfixUnaryOp(SourceLocation OpLoc, 
+                                         tok::TokenKind Kind, ExprTy *Input);
+  
+  virtual ExprResult ParseArraySubscriptExpr(ExprTy *Base, SourceLocation LLoc,
+                                             ExprTy *Idx, SourceLocation RLoc);
+  virtual ExprResult ParseMemberReferenceExpr(ExprTy *Base,SourceLocation OpLoc,
+                                              tok::TokenKind OpKind,
+                                              SourceLocation MemberLoc,
+                                              IdentifierInfo &Member);
+  
+  /// ParseCallExpr - Handle a call to Fn with the specified array of arguments.
+  /// This provides the location of the left/right parens and a list of comma
+  /// locations.
+  virtual ExprResult ParseCallExpr(ExprTy *Fn, SourceLocation LParenLoc,
+                                   ExprTy **Args, unsigned NumArgs,
+                                   SourceLocation *CommaLocs,
+                                   SourceLocation RParenLoc);
+  
+  virtual ExprResult ParseCastExpr(SourceLocation LParenLoc, TypeTy *Ty,
+                                   SourceLocation RParenLoc, ExprTy *Op);
+  
+  virtual ExprResult ParseBinOp(SourceLocation TokLoc, tok::TokenKind Kind,
+                                ExprTy *LHS,ExprTy *RHS);
+  
+  /// ParseConditionalOp - Parse a ?: operation.  Note that 'LHS' may be null
+  /// in the case of a the GNU conditional expr extension.
+  virtual ExprResult ParseConditionalOp(SourceLocation QuestionLoc, 
+                                        SourceLocation ColonLoc,
+                                        ExprTy *Cond, ExprTy *LHS, ExprTy *RHS);
+
+  /// ParseAddrLabel - Parse the GNU address of label extension: "&&foo".
+  virtual ExprResult ParseAddrLabel(SourceLocation OpLoc, SourceLocation LabLoc,
+                                    IdentifierInfo *LabelII);
+  
+  /// ParseCXXCasts - Parse {dynamic,static,reinterpret,const}_cast's.
+  virtual ExprResult ParseCXXCasts(SourceLocation OpLoc, tok::TokenKind Kind,
+                                   SourceLocation LAngleBracketLoc, TypeTy *Ty,
+                                   SourceLocation RAngleBracketLoc,
+                                   SourceLocation LParenLoc, ExprTy *E,
+                                   SourceLocation RParenLoc);
+
+  /// ParseCXXBoolLiteral - Parse {true,false} literals.
+  virtual ExprResult ParseCXXBoolLiteral(SourceLocation OpLoc,
+                                         tok::TokenKind Kind);
+private:
+  // UsualUnaryConversions - promotes integers (C99 6.3.1.1p2) and converts
+  // functions and arrays to their respective pointers (C99 6.3.2.1)
+  QualType UsualUnaryConversions(QualType t); 
+  // UsualArithmeticConversions - performs the UsualUnaryConversions on it's
+  // operands and then handles various conversions that are common to binary
+  // operators (C99 6.3.1.8). If both operands aren't arithmetic, this
+  // routine returns the first non-arithmetic type found. The client is 
+  // responsible for emitting appropriate error diagnostics.
+  QualType UsualArithmeticConversions(QualType &t1, QualType &t2);
+  // DefaultFunctionArrayConversion - converts functions and arrays
+  // to their respective pointers (C99 6.3.2.1). If the type isn't a function
+  // or array, this routine simply returns the input type (unmodified).
+  QualType DefaultFunctionArrayConversion(QualType t);
+  
+  enum AssignmentCheckResult {
+    Compatible,
+    Incompatible,
+    PointerFromInt, 
+    IntFromPointer,
+    IncompatiblePointer,
+    CompatiblePointerDiscardsQualifiers
+  };
+  // CheckAssignmentConstraints - conversions for assignment, argument passing, 
+  // variable initialization, and function return values. Currently used by 
+  // CheckAssignmentOperands, ParseCallExpr, and ParseReturnStmt.  C99 6.5.16.
+  AssignmentCheckResult CheckAssignmentConstraints(QualType lhs, QualType rhs);
+  // Helper function for CheckAssignmentConstraints (C99 6.5.16.1p1)
+  AssignmentCheckResult CheckPointerTypesForAssignment(QualType lhsType, 
+                                                       QualType rhsType);
+  
+  /// the following "Check" methods will return a valid/converted QualType
+  /// or a null QualType (indicating an error diagnostic was issued).
+    
+  /// type checking binary operators (subroutines of ParseBinOp).
+  inline void InvalidOperands(SourceLocation l, Expr *lex, Expr *rex);
+  inline QualType CheckVectorOperands(SourceLocation l, Expr *lex, Expr *rex);
+  inline QualType CheckMultiplyDivideOperands( // C99 6.5.5
+    Expr *lex, Expr *rex, SourceLocation OpLoc); 
+  inline QualType CheckRemainderOperands( // C99 6.5.5
+    Expr *lex, Expr *rex, SourceLocation OpLoc); 
+  inline QualType CheckAdditionOperands( // C99 6.5.6
+    Expr *lex, Expr *rex, SourceLocation OpLoc);
+  inline QualType CheckSubtractionOperands( // C99 6.5.6
+    Expr *lex, Expr *rex, SourceLocation OpLoc);
+  inline QualType CheckShiftOperands( // C99 6.5.7
+    Expr *lex, Expr *rex, SourceLocation OpLoc);
+  inline QualType CheckRelationalOperands( // C99 6.5.8
+    Expr *lex, Expr *rex, SourceLocation OpLoc);
+  inline QualType CheckEqualityOperands( // C99 6.5.9
+    Expr *lex, Expr *rex, SourceLocation OpLoc); 
+  inline QualType CheckBitwiseOperands( // C99 6.5.[10...12]
+    Expr *lex, Expr *rex, SourceLocation OpLoc); 
+  inline QualType CheckLogicalOperands( // C99 6.5.[13,14]
+    Expr *lex, Expr *rex, SourceLocation OpLoc);
+  // CheckAssignmentOperands is used for both simple and compound assignment.
+  // For simple assignment, pass both expressions and a null converted type.
+  // For compound assignment, pass both expressions and the converted type.
+  inline QualType CheckAssignmentOperands( // C99 6.5.16.[1,2]
+    Expr *lex, Expr *rex, SourceLocation OpLoc, QualType convertedType);
+  inline QualType CheckCommaOperands( // C99 6.5.17
+    Expr *lex, Expr *rex, SourceLocation OpLoc);
+  inline QualType CheckConditionalOperands( // C99 6.5.15
+    Expr *cond, Expr *lhs, Expr *rhs, SourceLocation questionLoc);
+  
+  /// type checking unary operators (subroutines of ParseUnaryOp).
+  /// C99 6.5.3.1, 6.5.3.2, 6.5.3.4
+  QualType CheckIncrementDecrementOperand(Expr *op, SourceLocation OpLoc);   
+  QualType CheckAddressOfOperand(Expr *op, SourceLocation OpLoc);
+  QualType CheckIndirectionOperand(Expr *op, SourceLocation OpLoc);
+  QualType CheckSizeOfAlignOfOperand(QualType type, SourceLocation loc, 
+                                     bool isSizeof);
+    
+  /// C99: 6.7.5p3: Used by ParseDeclarator/ParseField to make sure we have
+  /// a constant expression of type int with a value greater than zero.  If the
+  /// array has an incomplete type or a valid constant size, return false,
+  /// otherwise emit a diagnostic and return true.
+  bool VerifyConstantArrayType(const ArrayType *ary, SourceLocation loc); 
+};
+
+
+}  // end namespace clang
+
+#endif
diff --git a/Sema/SemaDecl.cpp b/Sema/SemaDecl.cpp
new file mode 100644
index 0000000..9b98c4b
--- /dev/null
+++ b/Sema/SemaDecl.cpp
@@ -0,0 +1,1024 @@
+//===--- SemaDecl.cpp - Semantic Analysis for Declarations ----------------===//
+//
+//                     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 declarations.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Sema.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/Builtins.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/Type.h"
+#include "clang/Parse/DeclSpec.h"
+#include "clang/Parse/Scope.h"
+#include "clang/Lex/IdentifierTable.h"
+#include "clang/Basic/LangOptions.h"
+#include "clang/Basic/TargetInfo.h"
+#include "llvm/ADT/SmallSet.h"
+using namespace clang;
+
+// C99: 6.7.5p3: Used by ParseDeclarator/ParseField to make sure we have
+// a constant expression of type int with a value greater than zero.
+bool Sema::VerifyConstantArrayType(const ArrayType *Array,
+                                   SourceLocation DeclLoc) { 
+  const Expr *Size = Array->getSize();
+  if (Size == 0) return false;  // incomplete type.
+  
+  if (!Size->getType()->isIntegerType()) {
+    Diag(Size->getLocStart(), diag::err_array_size_non_int, 
+         Size->getType().getAsString(), Size->getSourceRange());
+    return true;
+  }
+
+  // Verify that the size of the array is an integer constant expr.
+  SourceLocation Loc;
+  llvm::APSInt SizeVal(32);
+  if (!Size->isIntegerConstantExpr(SizeVal, &Loc)) {
+    // FIXME: This emits the diagnostic to enforce 6.7.2.1p8, but the message
+    // is wrong.  It is also wrong for static variables.
+    // FIXME: This is also wrong for:
+    // int sub1(int i, char *pi) { typedef int foo[i];
+    // struct bar {foo f1; int f2:3; int f3:4} *p; }
+    Diag(DeclLoc, diag::err_typecheck_illegal_vla, Size->getSourceRange());
+    return true;
+  }
+  
+  // We have a constant expression with an integer type, now make sure 
+  // value greater than zero (C99 6.7.5.2p1).
+  
+  // FIXME: This check isn't specific to static VLAs, this should be moved
+  // elsewhere or replicated.  'int X[-1];' inside a function should emit an
+  // error.
+  if (SizeVal.isSigned()) {
+    llvm::APSInt Zero(SizeVal.getBitWidth());
+    Zero.setIsUnsigned(false);
+    if (SizeVal < Zero) {
+      Diag(DeclLoc, diag::err_typecheck_negative_array_size,
+           Size->getSourceRange());
+      return true;
+    } else if (SizeVal == 0) {
+      // GCC accepts zero sized static arrays.
+      Diag(DeclLoc, diag::err_typecheck_zero_array_size, 
+           Size->getSourceRange());
+    }
+  }
+  return false;
+}
+
+Sema::DeclTy *Sema::isTypeName(const IdentifierInfo &II, Scope *S) const {
+  return dyn_cast_or_null<TypedefDecl>(II.getFETokenInfo<Decl>());
+}
+
+void Sema::PopScope(SourceLocation Loc, Scope *S) {
+  for (Scope::decl_iterator I = S->decl_begin(), E = S->decl_end();
+       I != E; ++I) {
+    Decl *D = static_cast<Decl*>(*I);
+    assert(D && "This decl didn't get pushed??");
+    IdentifierInfo *II = D->getIdentifier();
+    if (!II) continue;
+    
+    // Unlink this decl from the identifier.  Because the scope contains decls
+    // in an unordered collection, and because we have multiple identifier
+    // namespaces (e.g. tag, normal, label),the decl may not be the first entry.
+    if (II->getFETokenInfo<Decl>() == D) {
+      // Normal case, no multiple decls in different namespaces.
+      II->setFETokenInfo(D->getNext());
+    } else {
+      // Scan ahead.  There are only three namespaces in C, so this loop can
+      // never execute more than 3 times.
+      Decl *SomeDecl = II->getFETokenInfo<Decl>();
+      while (SomeDecl->getNext() != D) {
+        SomeDecl = SomeDecl->getNext();
+        assert(SomeDecl && "Didn't find this decl on its identifier's chain!");
+      }
+      SomeDecl->setNext(D->getNext());
+    }
+    
+    // This will have to be revisited for C++: there we want to nest stuff in
+    // namespace decls etc.  Even for C, we might want a top-level translation
+    // unit decl or something.
+    if (!CurFunctionDecl)
+      continue;
+
+    // Chain this decl to the containing function, it now owns the memory for
+    // the decl.
+    D->setNext(CurFunctionDecl->getDeclChain());
+    CurFunctionDecl->setDeclChain(D);
+  }
+}
+
+/// LookupScopedDecl - Look up the inner-most declaration in the specified
+/// namespace.
+Decl *Sema::LookupScopedDecl(IdentifierInfo *II, unsigned NSI,
+                             SourceLocation IdLoc, Scope *S) {
+  if (II == 0) return 0;
+  Decl::IdentifierNamespace NS = (Decl::IdentifierNamespace)NSI;
+  
+  // Scan up the scope chain looking for a decl that matches this identifier
+  // that is in the appropriate namespace.  This search should not take long, as
+  // shadowing of names is uncommon, and deep shadowing is extremely uncommon.
+  for (Decl *D = II->getFETokenInfo<Decl>(); D; D = D->getNext())
+    if (D->getIdentifierNamespace() == NS)
+      return D;
+  
+  // If we didn't find a use of this identifier, and if the identifier
+  // corresponds to a compiler builtin, create the decl object for the builtin
+  // now, injecting it into translation unit scope, and return it.
+  if (NS == Decl::IDNS_Ordinary) {
+    // If this is a builtin on some other target, or if this builtin varies
+    // across targets (e.g. in type), emit a diagnostic and mark the translation
+    // unit non-portable for using it.
+    if (II->isNonPortableBuiltin()) {
+      // Only emit this diagnostic once for this builtin.
+      II->setNonPortableBuiltin(false);
+      Context.Target.DiagnoseNonPortability(IdLoc,
+                                            diag::port_target_builtin_use);
+    }
+    // If this is a builtin on this (or all) targets, create the decl.
+    if (unsigned BuiltinID = II->getBuiltinID())
+      return LazilyCreateBuiltin(II, BuiltinID, S);
+  }
+  return 0;
+}
+
+/// LazilyCreateBuiltin - The specified Builtin-ID was first used at file scope.
+/// lazily create a decl for it.
+Decl *Sema::LazilyCreateBuiltin(IdentifierInfo *II, unsigned bid, Scope *S) {
+  Builtin::ID BID = (Builtin::ID)bid;
+
+  QualType R = Context.BuiltinInfo.GetBuiltinType(BID, Context);
+  FunctionDecl *New = new FunctionDecl(SourceLocation(), II, R,
+                                       FunctionDecl::Extern, 0);
+  
+  // Find translation-unit scope to insert this function into.
+  while (S->getParent())
+    S = S->getParent();
+  S->AddDecl(New);
+  
+  // Add this decl to the end of the identifier info.
+  if (Decl *LastDecl = II->getFETokenInfo<Decl>()) {
+    // Scan until we find the last (outermost) decl in the id chain. 
+    while (LastDecl->getNext())
+      LastDecl = LastDecl->getNext();
+    // Insert before (outside) it.
+    LastDecl->setNext(New);
+  } else {
+    II->setFETokenInfo(New);
+  }    
+  // Make sure clients iterating over decls see this.
+  LastInGroupList.push_back(New);
+  
+  return New;
+}
+
+/// MergeTypeDefDecl - We just parsed a typedef 'New' which has the same name
+/// and scope as a previous declaration 'Old'.  Figure out how to resolve this
+/// situation, merging decls or emitting diagnostics as appropriate.
+///
+TypedefDecl *Sema::MergeTypeDefDecl(TypedefDecl *New, Decl *OldD) {
+  // Verify the old decl was also a typedef.
+  TypedefDecl *Old = dyn_cast<TypedefDecl>(OldD);
+  if (!Old) {
+    Diag(New->getLocation(), diag::err_redefinition_different_kind,
+         New->getName());
+    Diag(OldD->getLocation(), diag::err_previous_definition);
+    return New;
+  }
+  
+  // TODO: CHECK FOR CONFLICTS, multiple decls with same name in one scope.
+  // TODO: This is totally simplistic.  It should handle merging functions
+  // together etc, merging extern int X; int X; ...
+  Diag(New->getLocation(), diag::err_redefinition, New->getName());
+  Diag(Old->getLocation(), diag::err_previous_definition);
+  return New;
+}
+
+/// MergeFunctionDecl - We just parsed a function 'New' which has the same name
+/// and scope as a previous declaration 'Old'.  Figure out how to resolve this
+/// situation, merging decls or emitting diagnostics as appropriate.
+///
+FunctionDecl *Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD) {
+  // Verify the old decl was also a function.
+  FunctionDecl *Old = dyn_cast<FunctionDecl>(OldD);
+  if (!Old) {
+    Diag(New->getLocation(), diag::err_redefinition_different_kind,
+         New->getName());
+    Diag(OldD->getLocation(), diag::err_previous_definition);
+    return New;
+  }
+  
+  // This is not right, but it's a start.  If 'Old' is a function prototype with
+  // the same type as 'New', silently allow this.  FIXME: We should link up decl
+  // objects here.
+  if (Old->getBody() == 0 && 
+      Old->getCanonicalType() == New->getCanonicalType()) {
+    return New;
+  }
+  
+  // TODO: CHECK FOR CONFLICTS, multiple decls with same name in one scope.
+  // TODO: This is totally simplistic.  It should handle merging functions
+  // together etc, merging extern int X; int X; ...
+  Diag(New->getLocation(), diag::err_redefinition, New->getName());
+  Diag(Old->getLocation(), diag::err_previous_definition);
+  return New;
+}
+
+/// MergeVarDecl - We just parsed a variable 'New' which has the same name
+/// and scope as a previous declaration 'Old'.  Figure out how to resolve this
+/// situation, merging decls or emitting diagnostics as appropriate.
+///
+/// FIXME: Need to carefully consider tentative definition rules (C99 6.9.2p2).
+/// For example, we incorrectly complain about i1, i4 from C99 6.9.2p4.
+/// 
+VarDecl *Sema::MergeVarDecl(VarDecl *New, Decl *OldD) {
+  // Verify the old decl was also a variable.
+  VarDecl *Old = dyn_cast<VarDecl>(OldD);
+  if (!Old) {
+    Diag(New->getLocation(), diag::err_redefinition_different_kind,
+         New->getName());
+    Diag(OldD->getLocation(), diag::err_previous_definition);
+    return New;
+  }
+  // Verify the types match.
+  if (Old->getCanonicalType() != New->getCanonicalType()) {
+    Diag(New->getLocation(), diag::err_redefinition, New->getName());
+    Diag(Old->getLocation(), diag::err_previous_definition);
+    return New;
+  }
+  // We've verified the types match, now check if Old is "extern".
+  if (Old->getStorageClass() != VarDecl::Extern) {
+    Diag(New->getLocation(), diag::err_redefinition, New->getName());
+    Diag(Old->getLocation(), diag::err_previous_definition);
+  }
+  return New;
+}
+
+/// ParsedFreeStandingDeclSpec - This method is invoked when a declspec with
+/// no declarator (e.g. "struct foo;") is parsed.
+Sema::DeclTy *Sema::ParsedFreeStandingDeclSpec(Scope *S, DeclSpec &DS) {
+  // TODO: emit error on 'int;' or 'const enum foo;'.
+  // TODO: emit error on 'typedef int;'
+  // if (!DS.isMissingDeclaratorOk()) Diag(...);
+  
+  return 0;
+}
+
+Sema::DeclTy *
+Sema::ParseDeclarator(Scope *S, Declarator &D, ExprTy *Init, 
+                      DeclTy *lastDeclarator) {
+  Decl *LastDeclarator = (Decl*)lastDeclarator;
+  IdentifierInfo *II = D.getIdentifier();
+  
+  // See if this is a redefinition of a variable in the same scope.
+  Decl *PrevDecl = LookupScopedDecl(II, Decl::IDNS_Ordinary,
+                                    D.getIdentifierLoc(), S);
+  if (PrevDecl && !S->isDeclScope(PrevDecl))
+    PrevDecl = 0;   // If in outer scope, it isn't the same thing.
+
+  Decl *New;
+  if (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_typedef) {
+    TypedefDecl *NewTD = ParseTypedefDecl(S, D, LastDeclarator);
+    if (!NewTD) return 0;
+
+    // Handle attributes prior to checking for duplicates in MergeVarDecl
+    HandleDeclAttributes(NewTD, D.getDeclSpec().getAttributes(),
+                         D.getAttributes());
+    // Merge the decl with the existing one if appropriate.
+    if (PrevDecl) {
+      NewTD = MergeTypeDefDecl(NewTD, PrevDecl);
+      if (NewTD == 0) return 0;
+    }
+    New = NewTD;
+    if (S->getParent() == 0) {
+      // C99 6.7.7p2: If a typedef name specifies a variably modified type
+      // then it shall have block scope.
+      if (ArrayType *ary = dyn_cast<ArrayType>(NewTD->getUnderlyingType())) {
+        if (VerifyConstantArrayType(ary, D.getIdentifierLoc()))
+          return 0;
+      }
+    }
+  } else if (D.isFunctionDeclarator()) {
+    QualType R = GetTypeForDeclarator(D, S);
+    if (R.isNull()) return 0; // FIXME: "auto func();" passes through...
+    
+    FunctionDecl::StorageClass SC;
+    switch (D.getDeclSpec().getStorageClassSpec()) {
+      default: assert(0 && "Unknown storage class!");
+      case DeclSpec::SCS_auto:        
+      case DeclSpec::SCS_register:
+        Diag(D.getIdentifierLoc(), diag::err_typecheck_sclass_func,
+             R.getAsString());
+        return 0;
+      case DeclSpec::SCS_unspecified: SC = FunctionDecl::None; break;
+      case DeclSpec::SCS_extern:      SC = FunctionDecl::Extern; break;
+      case DeclSpec::SCS_static:      SC = FunctionDecl::Static; break;
+    }
+
+    FunctionDecl *NewFD = new FunctionDecl(D.getIdentifierLoc(), II, R, SC,
+                                           LastDeclarator);
+    
+    // Merge the decl with the existing one if appropriate.
+    if (PrevDecl) {
+      NewFD = MergeFunctionDecl(NewFD, PrevDecl);
+      if (NewFD == 0) return 0;
+    }
+    New = NewFD;
+  } else {
+    QualType R = GetTypeForDeclarator(D, S);
+    if (R.isNull()) return 0;
+
+    VarDecl *NewVD;
+    VarDecl::StorageClass SC;
+    switch (D.getDeclSpec().getStorageClassSpec()) {
+      default: assert(0 && "Unknown storage class!");
+      case DeclSpec::SCS_unspecified: SC = VarDecl::None; break;
+      case DeclSpec::SCS_extern:      SC = VarDecl::Extern; break;
+      case DeclSpec::SCS_static:      SC = VarDecl::Static; break;
+      case DeclSpec::SCS_auto:        SC = VarDecl::Auto; break;
+      case DeclSpec::SCS_register:    SC = VarDecl::Register; break;
+    }    
+    if (S->getParent() == 0) {
+      // File scope. C99 6.9.2p2: A declaration of an identifier for and 
+      // object that has file scope without an initializer, and without a
+      // storage-class specifier or with the storage-class specifier "static",
+      // constitutes a tentative definition. Note: A tentative definition with
+      // external linkage is valid (C99 6.2.2p5).
+      if (!Init && SC == VarDecl::Static) {
+        // C99 6.9.2p3: If the declaration of an identifier for an object is
+        // a tentative definition and has internal linkage (C99 6.2.2p3), the  
+        // declared type shall not be an incomplete type.
+        if (R->isIncompleteType()) {
+          Diag(D.getIdentifierLoc(), diag::err_typecheck_decl_incomplete_type,
+               R.getAsString());
+          return 0;
+        }
+      }
+      // C99 6.9p2: The storage-class specifiers auto and register shall not
+      // appear in the declaration specifiers in an external declaration.
+      if (SC == VarDecl::Auto || SC == VarDecl::Register) {
+        Diag(D.getIdentifierLoc(), diag::err_typecheck_sclass_fscope,
+             R.getAsString());
+        return 0;
+      }
+      // C99 6.7.5.2p2: If an identifier is declared to be an object with 
+      // static storage duration, it shall not have a variable length array.
+      if (ArrayType *ary = dyn_cast<ArrayType>(R.getCanonicalType())) {
+        if (VerifyConstantArrayType(ary, D.getIdentifierLoc()))
+          return 0;
+      }
+      NewVD = new FileVarDecl(D.getIdentifierLoc(), II, R, SC, LastDeclarator);
+    } else { 
+      // Block scope. C99 6.7p7: If an identifier for an object is declared with
+      // no linkage (C99 6.2.2p6), the type for the object shall be complete...
+      if (SC != VarDecl::Extern) {
+        if (R->isIncompleteType()) {
+          Diag(D.getIdentifierLoc(), diag::err_typecheck_decl_incomplete_type,
+               R.getAsString());
+          return 0;
+        }
+      }
+      if (SC == VarDecl::Static) {
+        // C99 6.7.5.2p2: If an identifier is declared to be an object with 
+        // static storage duration, it shall not have a variable length array.
+        if (ArrayType *ary = dyn_cast<ArrayType>(R.getCanonicalType())) {
+          if (VerifyConstantArrayType(ary, D.getIdentifierLoc()))
+            return 0;
+        }
+      }
+      NewVD = new BlockVarDecl(D.getIdentifierLoc(), II, R, SC, LastDeclarator);
+    }    
+    // Handle attributes prior to checking for duplicates in MergeVarDecl
+    HandleDeclAttributes(NewVD, D.getDeclSpec().getAttributes(),
+                         D.getAttributes());
+     
+    // Merge the decl with the existing one if appropriate.
+    if (PrevDecl) {
+      NewVD = MergeVarDecl(NewVD, PrevDecl);
+      if (NewVD == 0) return 0;
+    }
+    New = NewVD;
+  }
+  
+  // If this has an identifier, add it to the scope stack.
+  if (II) {
+    New->setNext(II->getFETokenInfo<Decl>());
+    II->setFETokenInfo(New);
+    S->AddDecl(New);
+  }
+  
+  if (S->getParent() == 0)
+    AddTopLevelDecl(New, LastDeclarator);
+  
+  return New;
+}
+
+/// The declarators are chained together backwards, reverse the list.
+Sema::DeclTy *Sema::FinalizeDeclaratorGroup(Scope *S, DeclTy *group) {
+  // Often we have single declarators, handle them quickly.
+  Decl *Group = static_cast<Decl*>(group);
+  if (Group == 0 || Group->getNextDeclarator() == 0) return Group;
+  
+  Decl *NewGroup = 0;
+  while (Group) {
+    Decl *Next = Group->getNextDeclarator();
+    Group->setNextDeclarator(NewGroup);
+    NewGroup = Group;
+    Group = Next;
+  }
+  return NewGroup;
+}
+  
+ParmVarDecl *
+Sema::ParseParamDeclarator(DeclaratorChunk &FTI, unsigned ArgNo,
+                           Scope *FnScope) {
+  const DeclaratorChunk::ParamInfo &PI = FTI.Fun.ArgInfo[ArgNo];
+
+  IdentifierInfo *II = PI.Ident;
+  // TODO: CHECK FOR CONFLICTS, multiple decls with same name in one scope.
+  // Can this happen for params?  We already checked that they don't conflict
+  // among each other.  Here they can only shadow globals, which is ok.
+  if (Decl *PrevDecl = LookupScopedDecl(II, Decl::IDNS_Ordinary,
+                                        PI.IdentLoc, FnScope)) {
+    
+  }
+  
+  // FIXME: Handle storage class (auto, register). No declarator?
+  // TODO: Chain to previous parameter with the prevdeclarator chain?
+  ParmVarDecl *New = new ParmVarDecl(PI.IdentLoc, II, 
+                                     QualType::getFromOpaquePtr(PI.TypeInfo), 
+                                     VarDecl::None, 0);
+
+  // If this has an identifier, add it to the scope stack.
+  if (II) {
+    New->setNext(II->getFETokenInfo<Decl>());
+    II->setFETokenInfo(New);
+    FnScope->AddDecl(New);
+  }
+
+  return New;
+}
+  
+
+Sema::DeclTy *Sema::ParseStartOfFunctionDef(Scope *FnBodyScope, Declarator &D) {
+  assert(CurFunctionDecl == 0 && "Function parsing confused");
+  assert(D.getTypeObject(0).Kind == DeclaratorChunk::Function &&
+         "Not a function declarator!");
+  DeclaratorChunk::FunctionTypeInfo &FTI = D.getTypeObject(0).Fun;
+  
+  // Verify 6.9.1p6: 'every identifier in the identifier list shall be declared'
+  // for a K&R function.
+  if (!FTI.hasPrototype) {
+    for (unsigned i = 0, e = FTI.NumArgs; i != e; ++i) {
+      if (FTI.ArgInfo[i].TypeInfo == 0) {
+        Diag(FTI.ArgInfo[i].IdentLoc, diag::ext_param_not_declared,
+             FTI.ArgInfo[i].Ident->getName());
+        // Implicitly declare the argument as type 'int' for lack of a better
+        // type.
+        FTI.ArgInfo[i].TypeInfo = Context.IntTy.getAsOpaquePtr();
+      }
+    }
+   
+    // Since this is a function definition, act as though we have information
+    // about the arguments.
+    FTI.hasPrototype = true;
+  } else {
+    // FIXME: Diagnose arguments without names in C.
+    
+  }
+  
+  Scope *GlobalScope = FnBodyScope->getParent();
+  
+  FunctionDecl *FD =
+    static_cast<FunctionDecl*>(ParseDeclarator(GlobalScope, D, 0, 0));
+  CurFunctionDecl = FD;
+  
+  // Create Decl objects for each parameter, adding them to the FunctionDecl.
+  llvm::SmallVector<ParmVarDecl*, 16> Params;
+  
+  // Check for C99 6.7.5.3p10 - foo(void) is a non-varargs function that takes
+  // no arguments, not a function that takes a single void argument.
+  if (FTI.NumArgs == 1 && !FTI.isVariadic && FTI.ArgInfo[0].Ident == 0 &&
+      FTI.ArgInfo[0].TypeInfo == Context.VoidTy.getAsOpaquePtr()) {
+    // empty arg list, don't push any params.
+  } else {
+    for (unsigned i = 0, e = FTI.NumArgs; i != e; ++i)
+      Params.push_back(ParseParamDeclarator(D.getTypeObject(0), i,FnBodyScope));
+  }
+  
+  FD->setParams(&Params[0], Params.size());
+  
+  return FD;
+}
+
+Sema::DeclTy *Sema::ParseFunctionDefBody(DeclTy *D, StmtTy *Body) {
+  FunctionDecl *FD = static_cast<FunctionDecl*>(D);
+  FD->setBody((Stmt*)Body);
+  
+  assert(FD == CurFunctionDecl && "Function parsing confused");
+  CurFunctionDecl = 0;
+  
+  // Verify and clean out per-function state.
+  
+  // Check goto/label use.
+  for (llvm::DenseMap<IdentifierInfo*, LabelStmt*>::iterator
+       I = LabelMap.begin(), E = LabelMap.end(); I != E; ++I) {
+    // Verify that we have no forward references left.  If so, there was a goto
+    // or address of a label taken, but no definition of it.  Label fwd
+    // definitions are indicated with a null substmt.
+    if (I->second->getSubStmt() == 0) {
+      LabelStmt *L = I->second;
+      // Emit error.
+      Diag(L->getIdentLoc(), diag::err_undeclared_label_use, L->getName());
+      
+      // At this point, we have gotos that use the bogus label.  Stitch it into
+      // the function body so that they aren't leaked and that the AST is well
+      // formed.
+      L->setSubStmt(new NullStmt(L->getIdentLoc()));
+      cast<CompoundStmt>((Stmt*)Body)->push_back(L);
+    }
+  }
+  LabelMap.clear();
+  
+  return FD;
+}
+
+
+/// ImplicitlyDefineFunction - An undeclared identifier was used in a function
+/// call, forming a call to an implicitly defined function (per C99 6.5.1p2).
+Decl *Sema::ImplicitlyDefineFunction(SourceLocation Loc, IdentifierInfo &II,
+                                     Scope *S) {
+  if (getLangOptions().C99)  // Extension in C99.
+    Diag(Loc, diag::ext_implicit_function_decl, II.getName());
+  else  // Legal in C90, but warn about it.
+    Diag(Loc, diag::warn_implicit_function_decl, II.getName());
+  
+  // FIXME: handle stuff like:
+  // void foo() { extern float X(); }
+  // void bar() { X(); }  <-- implicit decl for X in another scope.
+
+  // Set a Declarator for the implicit definition: int foo();
+  const char *Dummy;
+  DeclSpec DS;
+  bool Error = DS.SetTypeSpecType(DeclSpec::TST_int, Loc, Dummy);
+  Error = Error; // Silence warning.
+  assert(!Error && "Error setting up implicit decl!");
+  Declarator D(DS, Declarator::BlockContext);
+  D.AddTypeInfo(DeclaratorChunk::getFunction(false, false, 0, 0, Loc));
+  D.SetIdentifier(&II, Loc);
+  
+  // Find translation-unit scope to insert this function into.
+  while (S->getParent())
+    S = S->getParent();
+  
+  return static_cast<Decl*>(ParseDeclarator(S, D, 0, 0));
+}
+
+
+TypedefDecl *Sema::ParseTypedefDecl(Scope *S, Declarator &D,
+                                    Decl *LastDeclarator) {
+  assert(D.getIdentifier() && "Wrong callback for declspec without declarator");
+  
+  QualType T = GetTypeForDeclarator(D, S);
+  if (T.isNull()) return 0;
+  
+  // Scope manipulation handled by caller.
+  return new TypedefDecl(D.getIdentifierLoc(), D.getIdentifier(), T,
+                         LastDeclarator);
+}
+
+
+/// ParseTag - This is invoked when we see 'struct foo' or 'struct {'.  In the
+/// former case, Name will be non-null.  In the later case, Name will be null.
+/// TagType indicates what kind of tag this is. TK indicates whether this is a
+/// reference/declaration/definition of a tag.
+Sema::DeclTy *Sema::ParseTag(Scope *S, unsigned TagType, TagKind TK,
+                             SourceLocation KWLoc, IdentifierInfo *Name,
+                             SourceLocation NameLoc, AttributeList *Attr) {
+  // If this is a use of an existing tag, it must have a name.
+  assert((Name != 0 || TK == TK_Definition) &&
+         "Nameless record must be a definition!");
+  
+  Decl::Kind Kind;
+  switch (TagType) {
+  default: assert(0 && "Unknown tag type!");
+  case DeclSpec::TST_struct: Kind = Decl::Struct; break;
+  case DeclSpec::TST_union:  Kind = Decl::Union; break;
+//case DeclSpec::TST_class:  Kind = Decl::Class; break;
+  case DeclSpec::TST_enum:   Kind = Decl::Enum; break;
+  }
+  
+  // If this is a named struct, check to see if there was a previous forward
+  // declaration or definition.
+  if (TagDecl *PrevDecl = 
+          dyn_cast_or_null<TagDecl>(LookupScopedDecl(Name, Decl::IDNS_Tag,
+                                                     NameLoc, S))) {
+    
+    // If this is a use of a previous tag, or if the tag is already declared in
+    // the same scope (so that the definition/declaration completes or
+    // rementions the tag), reuse the decl.
+    if (TK == TK_Reference || S->isDeclScope(PrevDecl)) {
+      // Make sure that this wasn't declared as an enum and now used as a struct
+      // or something similar.
+      if (PrevDecl->getKind() != Kind) {
+        Diag(KWLoc, diag::err_use_with_wrong_tag, Name->getName());
+        Diag(PrevDecl->getLocation(), diag::err_previous_use);
+      }
+      
+      // If this is a use or a forward declaration, we're good.
+      if (TK != TK_Definition)
+        return PrevDecl;
+
+      // Diagnose attempts to redefine a tag.
+      if (PrevDecl->isDefinition()) {
+        Diag(NameLoc, diag::err_redefinition, Name->getName());
+        Diag(PrevDecl->getLocation(), diag::err_previous_definition);
+        // If this is a redefinition, recover by making this struct be
+        // anonymous, which will make any later references get the previous
+        // definition.
+        Name = 0;
+      } else {
+        // Okay, this is definition of a previously declared or referenced tag.
+        // Move the location of the decl to be the definition site.
+        PrevDecl->setLocation(NameLoc);
+        return PrevDecl;
+      }
+    }
+    // If we get here, this is a definition of a new struct type in a nested
+    // scope, e.g. "struct foo; void bar() { struct foo; }", just create a new
+    // type.
+  }
+  
+  // If there is an identifier, use the location of the identifier as the
+  // location of the decl, otherwise use the location of the struct/union
+  // keyword.
+  SourceLocation Loc = NameLoc.isValid() ? NameLoc : KWLoc;
+  
+  // Otherwise, if this is the first time we've seen this tag, create the decl.
+  TagDecl *New;
+  switch (Kind) {
+  default: assert(0 && "Unknown tag kind!");
+  case Decl::Enum:
+    // FIXME: Tag decls should be chained to any simultaneous vardecls, e.g.:
+    // enum X { A, B, C } D;    D should chain to X.
+    New = new EnumDecl(Loc, Name, 0);
+    // If this is an undefined enum, warn.
+    if (TK != TK_Definition) Diag(Loc, diag::ext_forward_ref_enum);
+    break;
+  case Decl::Union:
+  case Decl::Struct:
+  case Decl::Class:
+    // FIXME: Tag decls should be chained to any simultaneous vardecls, e.g.:
+    // struct X { int A; } D;    D should chain to X.
+    New = new RecordDecl(Kind, Loc, Name, 0);
+    break;
+  }    
+  
+  // If this has an identifier, add it to the scope stack.
+  if (Name) {
+    New->setNext(Name->getFETokenInfo<Decl>());
+    Name->setFETokenInfo(New);
+    S->AddDecl(New);
+  }
+  
+  return New;
+}
+
+/// ParseField - Each field of a struct/union/class is passed into this in order
+/// to create a FieldDecl object for it.
+Sema::DeclTy *Sema::ParseField(Scope *S, DeclTy *TagDecl,
+                               SourceLocation DeclStart, 
+                               Declarator &D, ExprTy *BitfieldWidth) {
+  IdentifierInfo *II = D.getIdentifier();
+  Expr *BitWidth = (Expr*)BitfieldWidth;
+  
+  SourceLocation Loc = DeclStart;
+  if (II) Loc = D.getIdentifierLoc();
+  
+  // FIXME: Unnamed fields can be handled in various different ways, for
+  // example, unnamed unions inject all members into the struct namespace!
+  
+  
+  if (BitWidth) {
+    // TODO: Validate.
+    //printf("WARNING: BITFIELDS IGNORED!\n");
+    
+    // 6.7.2.1p3
+    // 6.7.2.1p4
+    
+  } else {
+    // Not a bitfield.
+
+    // validate II.
+    
+  }
+  
+  QualType T = GetTypeForDeclarator(D, S);
+  if (T.isNull()) return 0;
+  
+  // C99 6.7.2.1p8: A member of a structure or union may have any type other
+  // than a variably modified type.
+  if (ArrayType *ary = dyn_cast<ArrayType>(T.getCanonicalType())) {
+    if (VerifyConstantArrayType(ary, Loc))
+      return 0;
+  }
+  
+  // FIXME: Chain fielddecls together.
+  return new FieldDecl(Loc, II, T, 0);
+}
+
+void Sema::ParseRecordBody(SourceLocation RecLoc, DeclTy *RecDecl,
+                           DeclTy **Fields, unsigned NumFields) {
+  RecordDecl *Record = cast<RecordDecl>(static_cast<Decl*>(RecDecl));
+  if (Record->isDefinition()) {
+    // Diagnose code like:
+    //     struct S { struct S {} X; };
+    // We discover this when we complete the outer S.  Reject and ignore the
+    // outer S.
+    Diag(Record->getLocation(), diag::err_nested_redefinition,
+         Record->getKindName());
+    Diag(RecLoc, diag::err_previous_definition);
+    return;
+  }
+
+  // Verify that all the fields are okay.
+  unsigned NumNamedMembers = 0;
+  llvm::SmallVector<FieldDecl*, 32> RecFields;
+  llvm::SmallSet<const IdentifierInfo*, 32> FieldIDs;
+  
+  for (unsigned i = 0; i != NumFields; ++i) {
+    FieldDecl *FD = cast_or_null<FieldDecl>(static_cast<Decl*>(Fields[i]));
+    if (!FD) continue;  // Already issued a diagnostic.
+    
+    // Get the type for the field.
+    Type *FDTy = FD->getType().getCanonicalType().getTypePtr();
+    
+    // C99 6.7.2.1p2 - A field may not be a function type.
+    if (isa<FunctionType>(FDTy)) {
+      Diag(FD->getLocation(), diag::err_field_declared_as_function,
+           FD->getName());
+      delete FD;
+      continue;
+    }
+
+    // C99 6.7.2.1p2 - A field may not be an incomplete type except...
+    if (FDTy->isIncompleteType()) {
+      if (i != NumFields-1 ||                   // ... that the last member ...
+          Record->getKind() != Decl::Struct ||  // ... of a structure ...
+          !isa<ArrayType>(FDTy)) {         //... may have incomplete array type.
+        Diag(FD->getLocation(), diag::err_field_incomplete, FD->getName());
+        delete FD;
+        continue;
+      }
+      if (NumNamedMembers < 1) {      //... must have more than named member ...
+        Diag(FD->getLocation(), diag::err_flexible_array_empty_struct,
+             FD->getName());
+        delete FD;
+        continue;
+      }
+      
+      // Okay, we have a legal flexible array member at the end of the struct.
+      Record->setHasFlexibleArrayMember(true);
+    }
+    
+    
+    /// C99 6.7.2.1p2 - a struct ending in a flexible array member cannot be the
+    /// field of another structure or the element of an array.
+    if (RecordType *FDTTy = dyn_cast<RecordType>(FDTy)) {
+      if (FDTTy->getDecl()->hasFlexibleArrayMember()) {
+        // If this is a member of a union, then entire union becomes "flexible".
+        if (Record->getKind() == Decl::Union) {
+          Record->setHasFlexibleArrayMember(true);
+        } else {
+          // If this is a struct/class and this is not the last element, reject
+          // it.  Note that GCC supports variable sized arrays in the middle of
+          // structures.
+          if (i != NumFields-1) {
+            Diag(FD->getLocation(), diag::err_variable_sized_type_in_struct,
+                 FD->getName());
+            delete FD;
+            continue;
+          }
+
+          // We support flexible arrays at the end of structs in other structs
+          // as an extension.
+          Diag(FD->getLocation(), diag::ext_flexible_array_in_struct,
+               FD->getName());
+          Record->setHasFlexibleArrayMember(true);
+        }
+      }
+    }
+    
+    // Keep track of the number of named members.
+    if (IdentifierInfo *II = FD->getIdentifier()) {
+      // Detect duplicate member names.
+      if (!FieldIDs.insert(II)) {
+        Diag(FD->getLocation(), diag::err_duplicate_member, II->getName());
+        // Find the previous decl.
+        SourceLocation PrevLoc;
+        for (unsigned i = 0, e = RecFields.size(); ; ++i) {
+          assert(i != e && "Didn't find previous def!");
+          if (RecFields[i]->getIdentifier() == II) {
+            PrevLoc = RecFields[i]->getLocation();
+            break;
+          }
+        }
+        Diag(PrevLoc, diag::err_previous_definition);
+        delete FD;
+        continue;
+      }
+      ++NumNamedMembers;
+    }
+    
+    // Remember good fields.
+    RecFields.push_back(FD);
+  }
+ 
+  
+  // Okay, we successfully defined 'Record'.
+  Record->defineBody(&RecFields[0], RecFields.size());
+}
+
+Sema::DeclTy *Sema::ParseEnumConstant(Scope *S, DeclTy *theEnumDecl,
+                                      DeclTy *lastEnumConst,
+                                      SourceLocation IdLoc, IdentifierInfo *Id,
+                                      SourceLocation EqualLoc, ExprTy *val) {
+  theEnumDecl = theEnumDecl;  // silence unused warning.
+  EnumConstantDecl *LastEnumConst =
+    cast_or_null<EnumConstantDecl>(static_cast<Decl*>(lastEnumConst));
+  Expr *Val = static_cast<Expr*>(val);
+
+  // Verify that there isn't already something declared with this name in this
+  // scope.
+  if (Decl *PrevDecl = LookupScopedDecl(Id, Decl::IDNS_Ordinary, IdLoc, S)) {
+    if (S->isDeclScope(PrevDecl)) {
+      if (isa<EnumConstantDecl>(PrevDecl))
+        Diag(IdLoc, diag::err_redefinition_of_enumerator, Id->getName());
+      else
+        Diag(IdLoc, diag::err_redefinition, Id->getName());
+      Diag(PrevDecl->getLocation(), diag::err_previous_definition);
+      // FIXME: Don't leak memory: delete Val;
+      return 0;
+    }
+  }
+
+  llvm::APSInt EnumVal(32);
+  QualType EltTy;
+  if (Val) {
+    // C99 6.7.2.2p2: Make sure we have an integer constant expression.
+    SourceLocation ExpLoc;
+    if (!Val->isIntegerConstantExpr(EnumVal, &ExpLoc)) {
+      Diag(ExpLoc, diag::err_enum_value_not_integer_constant_expr, 
+           Id->getName());
+      // FIXME: Don't leak memory: delete Val;
+      return 0;
+    }
+    EltTy = Val->getType();
+  } else if (LastEnumConst) {
+    // Assign the last value + 1.
+    EnumVal = LastEnumConst->getInitVal();
+    ++EnumVal;
+    // FIXME: detect overflow!
+    EltTy = LastEnumConst->getType();
+  } else {
+    // First value, set to zero.
+    EltTy = Context.IntTy;
+    // FIXME: Resize EnumVal to the size of int.
+  }
+  
+  // TODO: Default promotions to int/uint.
+  
+  // TODO: If the result value doesn't fit in an int, it must be a long or long
+  // long value.  ISO C does not support this, but GCC does as an extension,
+  // emit a warning.
+  
+  EnumConstantDecl *New = new EnumConstantDecl(IdLoc, Id, EltTy, Val, EnumVal,
+                                               LastEnumConst);
+  
+  // Register this decl in the current scope stack.
+  New->setNext(Id->getFETokenInfo<Decl>());
+  Id->setFETokenInfo(New);
+  S->AddDecl(New);
+  return New;
+}
+
+void Sema::ParseEnumBody(SourceLocation EnumLoc, DeclTy *EnumDeclX,
+                         DeclTy **Elements, unsigned NumElements) {
+  EnumDecl *Enum = cast<EnumDecl>(static_cast<Decl*>(EnumDeclX));
+  assert(!Enum->isDefinition() && "Enum redefinitions can't reach here");
+  
+  // Verify that all the values are okay, and reverse the list.
+  EnumConstantDecl *EltList = 0;
+  for (unsigned i = 0; i != NumElements; ++i) {
+    EnumConstantDecl *ECD =
+      cast_or_null<EnumConstantDecl>(static_cast<Decl*>(Elements[i]));
+    if (!ECD) continue;  // Already issued a diagnostic.
+
+    ECD->setNextDeclarator(EltList);
+    EltList = ECD;
+  }
+  
+  Enum->defineElements(EltList);
+}
+
+void Sema::AddTopLevelDecl(Decl *current, Decl *last) {
+  if (!current) return;
+
+  // If this is a top-level decl that is chained to some other (e.g. int A,B,C;)
+  // remember this in the LastInGroupList list.
+  if (last)
+    LastInGroupList.push_back((Decl*)last);
+}
+
+void Sema::HandleDeclAttribute(Decl *New, AttributeList *rawAttr) {
+  if (strcmp(rawAttr->getAttributeName()->getName(), "vector_size") == 0) {
+    if (ValueDecl *vDecl = dyn_cast<ValueDecl>(New)) {
+      QualType newType = HandleVectorTypeAttribute(vDecl->getType(), rawAttr);
+      if (!newType.isNull()) // install the new vector type into the decl
+        vDecl->setType(newType);
+    } 
+    if (TypedefDecl *tDecl = dyn_cast<TypedefDecl>(New)) {
+      QualType newType = HandleVectorTypeAttribute(tDecl->getUnderlyingType(), 
+                                                   rawAttr);
+      if (!newType.isNull()) // install the new vector type into the decl
+        tDecl->setUnderlyingType(newType);
+    }
+  }
+  // FIXME: add other attributes...
+}
+
+void Sema::HandleDeclAttributes(Decl *New, AttributeList *declspec_prefix,
+                                AttributeList *declarator_postfix) {
+  while (declspec_prefix) {
+    HandleDeclAttribute(New, declspec_prefix);
+    declspec_prefix = declspec_prefix->getNext();
+  }
+  while (declarator_postfix) {
+    HandleDeclAttribute(New, declarator_postfix);
+    declarator_postfix = declarator_postfix->getNext();
+  }
+}
+
+QualType Sema::HandleVectorTypeAttribute(QualType curType, 
+                                      AttributeList *rawAttr) {
+  // check the attribute arugments.
+  if (rawAttr->getNumArgs() != 1) {
+    Diag(rawAttr->getAttributeLoc(), diag::err_attribute_wrong_number_arguments,
+         std::string("1"));
+    return QualType();
+  }
+  Expr *sizeExpr = static_cast<Expr *>(rawAttr->getArg(0));
+  llvm::APSInt vecSize(32);
+  if (!sizeExpr->isIntegerConstantExpr(vecSize)) {
+    Diag(rawAttr->getAttributeLoc(), diag::err_attribute_vector_size_not_int,
+         sizeExpr->getSourceRange());
+    return QualType();
+  }
+  // navigate to the base type - we need to provide for vector pointers, 
+  // vector arrays, and functions returning vectors.
+  Type *canonType = curType.getCanonicalType().getTypePtr();
+  
+  while (canonType->isPointerType() || canonType->isArrayType() ||
+         canonType->isFunctionType()) {
+    if (PointerType *PT = dyn_cast<PointerType>(canonType))
+      canonType = PT->getPointeeType().getTypePtr();
+    else if (ArrayType *AT = dyn_cast<ArrayType>(canonType))
+      canonType = AT->getElementType().getTypePtr();
+    else if (FunctionType *FT = dyn_cast<FunctionType>(canonType))
+      canonType = FT->getResultType().getTypePtr();
+  }
+  // the base type must be integer or float.
+  if (!(canonType->isIntegerType() || canonType->isRealFloatingType())) {
+    Diag(rawAttr->getAttributeLoc(), diag::err_attribute_invalid_vector_type,
+         curType.getCanonicalType().getAsString());
+    return QualType();
+  }
+  BuiltinType *baseType = cast<BuiltinType>(canonType);
+  unsigned typeSize = baseType->getSize();
+  // vecSize is specified in bytes - convert to bits.
+  unsigned vectorSize = vecSize.getZExtValue() * 8; 
+  
+  // the vector size needs to be an integral multiple of the type size.
+  if (vectorSize % typeSize) {
+    Diag(rawAttr->getAttributeLoc(), diag::err_attribute_invalid_size,
+         sizeExpr->getSourceRange());
+    return QualType();
+  }
+  if (vectorSize == 0) {
+    Diag(rawAttr->getAttributeLoc(), diag::err_attribute_zero_size,
+         sizeExpr->getSourceRange());
+    return QualType();
+  }
+  // Since OpenCU requires 3 element vectors (OpenCU 5.1.2), we don't restrict
+  // the number of elements to be a power of two (unlike GCC).
+  // Instantiate the vector type, the number of elements is > 0.
+  return Context.convertToVectorType(curType, vectorSize/typeSize);
+}
+
diff --git a/Sema/SemaExpr.cpp b/Sema/SemaExpr.cpp
new file mode 100644
index 0000000..4f0935a
--- /dev/null
+++ b/Sema/SemaExpr.cpp
@@ -0,0 +1,1364 @@
+//===--- SemaExpr.cpp - Semantic Analysis for Expressions -----------------===//
+//
+//                     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 expressions.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Sema.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/Expr.h"
+#include "clang/Lex/Preprocessor.h"
+#include "clang/Lex/LiteralSupport.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/LangOptions.h"
+#include "clang/Basic/TargetInfo.h"
+#include "llvm/ADT/SmallString.h"
+using namespace clang;
+
+/// ParseStringLiteral - The specified tokens were lexed as pasted string
+/// fragments (e.g. "foo" "bar" L"baz").  The result string has to handle string
+/// concatenation ([C99 5.1.1.2, translation phase #6]), so it may come from
+/// multiple tokens.  However, the common case is that StringToks points to one
+/// string.
+/// 
+Action::ExprResult
+Sema::ParseStringLiteral(const LexerToken *StringToks, unsigned NumStringToks) {
+  assert(NumStringToks && "Must have at least one string!");
+
+  StringLiteralParser Literal(StringToks, NumStringToks, PP, Context.Target);
+  if (Literal.hadError)
+    return ExprResult(true);
+
+  llvm::SmallVector<SourceLocation, 4> StringTokLocs;
+  for (unsigned i = 0; i != NumStringToks; ++i)
+    StringTokLocs.push_back(StringToks[i].getLocation());
+  
+  // FIXME: handle wchar_t
+  QualType t = Context.getPointerType(Context.CharTy);
+  
+  // Pass &StringTokLocs[0], StringTokLocs.size() to factory!
+  return new StringLiteral(Literal.GetString(), Literal.GetStringLength(), 
+                           Literal.AnyWide, t, StringToks[0].getLocation(),
+                           StringToks[NumStringToks-1].getLocation());
+}
+
+
+/// ParseIdentifierExpr - The parser read an identifier in expression context,
+/// validate it per-C99 6.5.1.  HasTrailingLParen indicates whether this
+/// identifier is used in an function call context.
+Sema::ExprResult Sema::ParseIdentifierExpr(Scope *S, SourceLocation Loc,
+                                           IdentifierInfo &II,
+                                           bool HasTrailingLParen) {
+  // Could be enum-constant or decl.
+  Decl *D = LookupScopedDecl(&II, Decl::IDNS_Ordinary, Loc, S);
+  if (D == 0) {
+    // Otherwise, this could be an implicitly declared function reference (legal
+    // in C90, extension in C99).
+    if (HasTrailingLParen &&
+        // Not in C++.
+        !getLangOptions().CPlusPlus)
+      D = ImplicitlyDefineFunction(Loc, II, S);
+    else {
+      // If this name wasn't predeclared and if this is not a function call,
+      // diagnose the problem.
+      return Diag(Loc, diag::err_undeclared_var_use, II.getName());
+    }
+  }
+  
+  if (ValueDecl *VD = dyn_cast<ValueDecl>(D))
+    return new DeclRefExpr(VD, VD->getType(), Loc);
+  if (isa<TypedefDecl>(D))
+    return Diag(Loc, diag::err_unexpected_typedef, II.getName());
+
+  assert(0 && "Invalid decl");
+}
+
+Sema::ExprResult Sema::ParseSimplePrimaryExpr(SourceLocation Loc,
+                                              tok::TokenKind Kind) {
+  switch (Kind) {
+  default:
+    assert(0 && "Unknown simple primary expr!");
+  // TODO: MOVE this to be some other callback.
+  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]
+    return 0;
+  }
+}
+
+Sema::ExprResult Sema::ParseCharacterConstant(const LexerToken &Tok) {
+  llvm::SmallString<16> CharBuffer;
+  CharBuffer.resize(Tok.getLength());
+  const char *ThisTokBegin = &CharBuffer[0];
+  unsigned ActualLength = PP.getSpelling(Tok, ThisTokBegin);
+  
+  CharLiteralParser Literal(ThisTokBegin, ThisTokBegin+ActualLength,
+                            Tok.getLocation(), PP);
+  if (Literal.hadError())
+    return ExprResult(true);
+  return new CharacterLiteral(Literal.getValue(), Context.IntTy, 
+                              Tok.getLocation());
+}
+
+Action::ExprResult Sema::ParseNumericConstant(const LexerToken &Tok) {
+  // fast path for a single digit (which is quite common). A single digit 
+  // cannot have a trigraph, escaped newline, radix prefix, or type suffix.
+  if (Tok.getLength() == 1) {
+    const char *t = PP.getSourceManager().getCharacterData(Tok.getLocation());
+    
+    unsigned IntSize = Context.Target.getIntWidth(Tok.getLocation());
+    return ExprResult(new IntegerLiteral(llvm::APInt(IntSize, *t-'0'),
+                                         Context.IntTy, 
+                                         Tok.getLocation()));
+  }
+  llvm::SmallString<512> IntegerBuffer;
+  IntegerBuffer.resize(Tok.getLength());
+  const char *ThisTokBegin = &IntegerBuffer[0];
+  
+  // Get the spelling of the token, which eliminates trigraphs, etc.
+  unsigned ActualLength = PP.getSpelling(Tok, ThisTokBegin);
+  NumericLiteralParser Literal(ThisTokBegin, ThisTokBegin+ActualLength, 
+                               Tok.getLocation(), PP);
+  if (Literal.hadError)
+    return ExprResult(true);
+  
+  if (Literal.isIntegerLiteral()) {
+    QualType t;
+
+    // Get the value in the widest-possible width.
+    llvm::APInt ResultVal(Context.Target.getIntMaxTWidth(Tok.getLocation()), 0);
+   
+    if (Literal.GetIntegerValue(ResultVal)) {
+      // If this value didn't fit into uintmax_t, warn and force to ull.
+      Diag(Tok.getLocation(), diag::warn_integer_too_large);
+      t = Context.UnsignedLongLongTy;
+      assert(Context.getIntegerBitwidth(t, Tok.getLocation()) == 
+             ResultVal.getBitWidth() && "long long is not intmax_t?");
+    } else {
+      // If this value fits into a ULL, try to figure out what else it fits into
+      // according to the rules of C99 6.4.4.1p5.
+      
+      // Octal, Hexadecimal, and integers with a U suffix are allowed to
+      // be an unsigned int.
+      bool AllowUnsigned = Literal.isUnsigned || Literal.getRadix() != 10;
+
+      // Check from smallest to largest, picking the smallest type we can.
+      if (!Literal.isLong) {  // Are int/unsigned possibilities?
+        unsigned IntSize = Context.Target.getIntWidth(Tok.getLocation());
+        // Does it fit in a unsigned int?
+        if (ResultVal.isIntN(IntSize)) {
+          // Does it fit in a signed int?
+          if (!Literal.isUnsigned && ResultVal[IntSize-1] == 0)
+            t = Context.IntTy;
+          else if (AllowUnsigned)
+            t = Context.UnsignedIntTy;
+        }
+        
+        if (!t.isNull())
+          ResultVal.trunc(IntSize);
+      }
+      
+      // Are long/unsigned long possibilities?
+      if (t.isNull() && !Literal.isLongLong) {
+        unsigned LongSize = Context.Target.getLongWidth(Tok.getLocation());
+     
+        // Does it fit in a unsigned long?
+        if (ResultVal.isIntN(LongSize)) {
+          // Does it fit in a signed long?
+          if (!Literal.isUnsigned && ResultVal[LongSize-1] == 0)
+            t = Context.LongTy;
+          else if (AllowUnsigned)
+            t = Context.UnsignedLongTy;
+        }
+        if (!t.isNull())
+          ResultVal.trunc(LongSize);
+      }      
+      
+      // Finally, check long long if needed.
+      if (t.isNull()) {
+        unsigned LongLongSize =
+          Context.Target.getLongLongWidth(Tok.getLocation());
+        
+        // Does it fit in a unsigned long long?
+        if (ResultVal.isIntN(LongLongSize)) {
+          // Does it fit in a signed long long?
+          if (!Literal.isUnsigned && ResultVal[LongLongSize-1] == 0)
+            t = Context.LongLongTy;
+          else if (AllowUnsigned)
+            t = Context.UnsignedLongLongTy;
+        }
+      }
+      
+      // If we still couldn't decide a type, we probably have something that
+      // does not fit in a signed long long, but has no U suffix.
+      if (t.isNull()) {
+        Diag(Tok.getLocation(), diag::warn_integer_too_large_for_signed);
+        t = Context.UnsignedLongLongTy;
+      }
+    }
+
+    return new IntegerLiteral(ResultVal, t, Tok.getLocation());
+  } else if (Literal.isFloatingLiteral()) {
+    // FIXME: handle float values > 32 (including compute the real type...).
+    return new FloatingLiteral(Literal.GetFloatValue(), Context.FloatTy, 
+                               Tok.getLocation());
+  }
+  return ExprResult(true);
+}
+
+Action::ExprResult Sema::ParseParenExpr(SourceLocation L, SourceLocation R,
+                                        ExprTy *Val) {
+  Expr *e = (Expr *)Val;
+  assert((e != 0) && "ParseParenExpr() missing expr");
+  return new ParenExpr(L, R, e);
+}
+
+/// The UsualUnaryConversions() function is *not* called by this routine.
+/// See C99 6.3.2.1p[2-4] for more details.
+QualType Sema::CheckSizeOfAlignOfOperand(QualType exprType, 
+                                         SourceLocation OpLoc, bool isSizeof) {
+  // C99 6.5.3.4p1:
+  if (isa<FunctionType>(exprType) && isSizeof)
+    // alignof(function) is allowed.
+    Diag(OpLoc, diag::ext_sizeof_function_type);
+  else if (exprType->isVoidType())
+    Diag(OpLoc, diag::ext_sizeof_void_type, isSizeof ? "sizeof" : "__alignof");
+  else if (exprType->isIncompleteType()) {
+    Diag(OpLoc, isSizeof ? diag::err_sizeof_incomplete_type : 
+                           diag::err_alignof_incomplete_type,
+         exprType.getAsString());
+    return QualType(); // error
+  }
+  // C99 6.5.3.4p4: the type (an unsigned integer type) is size_t.
+  return Context.getSizeType();
+}
+
+Action::ExprResult Sema::
+ParseSizeOfAlignOfTypeExpr(SourceLocation OpLoc, bool isSizeof, 
+                           SourceLocation LPLoc, TypeTy *Ty,
+                           SourceLocation RPLoc) {
+  // If error parsing type, ignore.
+  if (Ty == 0) return true;
+  
+  // Verify that this is a valid expression.
+  QualType ArgTy = QualType::getFromOpaquePtr(Ty);
+  
+  QualType resultType = CheckSizeOfAlignOfOperand(ArgTy, OpLoc, isSizeof);
+
+  if (resultType.isNull())
+    return true;
+  return new SizeOfAlignOfTypeExpr(isSizeof, ArgTy, resultType, OpLoc, RPLoc);
+}
+
+
+Action::ExprResult Sema::ParsePostfixUnaryOp(SourceLocation OpLoc, 
+                                             tok::TokenKind Kind,
+                                             ExprTy *Input) {
+  UnaryOperator::Opcode Opc;
+  switch (Kind) {
+  default: assert(0 && "Unknown unary op!");
+  case tok::plusplus:   Opc = UnaryOperator::PostInc; break;
+  case tok::minusminus: Opc = UnaryOperator::PostDec; break;
+  }
+  QualType result = CheckIncrementDecrementOperand((Expr *)Input, OpLoc);
+  if (result.isNull())
+    return true;
+  return new UnaryOperator((Expr *)Input, Opc, result, OpLoc);
+}
+
+Action::ExprResult Sema::
+ParseArraySubscriptExpr(ExprTy *Base, SourceLocation LLoc,
+                        ExprTy *Idx, SourceLocation RLoc) {
+  QualType t1 = ((Expr *)Base)->getType();
+  QualType t2 = ((Expr *)Idx)->getType();
+
+  assert(!t1.isNull() && "no type for array base expression");
+  assert(!t2.isNull() && "no type for array index expression");
+
+  QualType canonT1 = DefaultFunctionArrayConversion(t1).getCanonicalType();
+  QualType canonT2 = DefaultFunctionArrayConversion(t2).getCanonicalType();
+  
+  // C99 6.5.2.1p2: the expression e1[e2] is by definition precisely equivalent
+  // to the expression *((e1)+(e2)). This means the array "Base" may actually be 
+  // in the subscript position. As a result, we need to derive the array base 
+  // and index from the expression types.
+  
+  Expr *baseExpr, *indexExpr;
+  QualType baseType, indexType;
+  if (isa<PointerType>(canonT1) || isa<VectorType>(canonT1)) {
+    baseType = canonT1;
+    indexType = canonT2;
+    baseExpr = static_cast<Expr *>(Base);
+    indexExpr = static_cast<Expr *>(Idx);
+  } else if (isa<PointerType>(canonT2)) { // uncommon
+    baseType = canonT2;
+    indexType = canonT1;
+    baseExpr = static_cast<Expr *>(Idx);
+    indexExpr = static_cast<Expr *>(Base);
+  } else {
+    return Diag(static_cast<Expr *>(Base)->getLocStart(), 
+                diag::err_typecheck_subscript_value, 
+                static_cast<Expr *>(Base)->getSourceRange());
+  }              
+  // C99 6.5.2.1p1
+  if (!indexType->isIntegerType()) {
+    return Diag(indexExpr->getLocStart(), diag::err_typecheck_subscript,
+                indexExpr->getSourceRange());
+  }
+  QualType resultType;
+  if (PointerType *ary = dyn_cast<PointerType>(baseType)) {
+    // FIXME: need to deal with const...
+    resultType = ary->getPointeeType();
+    // in practice, the following check catches trying to index a pointer
+    // to a function (e.g. void (*)(int)). Functions are not objects in c99.
+    if (!resultType->isObjectType()) {
+      return Diag(baseExpr->getLocStart(), 
+                  diag::err_typecheck_subscript_not_object,
+                  baseType.getAsString(), baseExpr->getSourceRange());
+    }
+  } else if (VectorType *vec = dyn_cast<VectorType>(baseType))
+    resultType = vec->getElementType();
+
+  return new ArraySubscriptExpr((Expr*)Base, (Expr*)Idx, resultType, RLoc);
+}
+
+Action::ExprResult Sema::
+ParseMemberReferenceExpr(ExprTy *Base, SourceLocation OpLoc,
+                         tok::TokenKind OpKind, SourceLocation MemberLoc,
+                         IdentifierInfo &Member) {
+  QualType qualifiedType = ((Expr *)Base)->getType();
+  
+  assert(!qualifiedType.isNull() && "no type for member expression");
+  
+  QualType canonType = qualifiedType.getCanonicalType();
+
+  if (OpKind == tok::arrow) {
+    if (PointerType *PT = dyn_cast<PointerType>(canonType)) {
+      qualifiedType = PT->getPointeeType();
+      canonType = qualifiedType.getCanonicalType();
+    } else
+      return Diag(OpLoc, diag::err_typecheck_member_reference_arrow);
+  }
+  if (!isa<RecordType>(canonType))
+    return Diag(OpLoc, diag::err_typecheck_member_reference_structUnion);
+  
+  // get the struct/union definition from the type.
+  RecordDecl *RD = cast<RecordType>(canonType)->getDecl();
+    
+  if (canonType->isIncompleteType())
+    return Diag(OpLoc, diag::err_typecheck_incomplete_tag, RD->getName());
+    
+  FieldDecl *MemberDecl = RD->getMember(&Member);
+  if (!MemberDecl)
+    return Diag(OpLoc, diag::err_typecheck_no_member, Member.getName());
+    
+  return new MemberExpr((Expr*)Base, OpKind == tok::arrow, 
+                        MemberDecl, MemberLoc);
+}
+
+/// ParseCallExpr - Handle a call to Fn with the specified array of arguments.
+/// This provides the location of the left/right parens and a list of comma
+/// locations.
+Action::ExprResult Sema::
+ParseCallExpr(ExprTy *Fn, SourceLocation LParenLoc,
+              ExprTy **Args, unsigned NumArgsInCall,
+              SourceLocation *CommaLocs, SourceLocation RParenLoc) {
+  Expr *funcExpr = (Expr *)Fn;
+  assert(funcExpr && "no function call expression");
+  
+  QualType qType = UsualUnaryConversions(funcExpr->getType());
+  assert(!qType.isNull() && "no type for function call expression");
+
+  // C99 6.5.2.2p1 - "The expression that denotes the called function shall have
+  // type pointer to function".
+  const PointerType *PT = dyn_cast<PointerType>(qType);
+  if (PT == 0) PT = dyn_cast<PointerType>(qType.getCanonicalType());
+  
+  if (PT == 0)
+    return Diag(funcExpr->getLocStart(), diag::err_typecheck_call_not_function,
+                SourceRange(funcExpr->getLocStart(), RParenLoc));
+  
+  const FunctionType *funcT = dyn_cast<FunctionType>(PT->getPointeeType());
+  if (funcT == 0)
+    funcT = dyn_cast<FunctionType>(PT->getPointeeType().getCanonicalType());
+  
+  if (funcT == 0)
+    return Diag(funcExpr->getLocStart(), diag::err_typecheck_call_not_function,
+                SourceRange(funcExpr->getLocStart(), RParenLoc));
+    
+  // If a prototype isn't declared, the parser implicitly defines a func decl
+  QualType resultType = funcT->getResultType();
+    
+  if (const FunctionTypeProto *proto = dyn_cast<FunctionTypeProto>(funcT)) {
+    // C99 6.5.2.2p7 - the arguments are implicitly converted, as if by 
+    // assignment, to the types of the corresponding parameter, ...
+    
+    unsigned NumArgsInProto = proto->getNumArgs();
+    unsigned NumArgsToCheck = NumArgsInCall;
+    
+    if (NumArgsInCall < NumArgsInProto)
+      Diag(RParenLoc, diag::err_typecheck_call_too_few_args,
+           funcExpr->getSourceRange());
+    else if (NumArgsInCall > NumArgsInProto) {
+      if (!proto->isVariadic()) {
+        Diag(((Expr **)Args)[NumArgsInProto+1]->getLocStart(), 
+             diag::err_typecheck_call_too_many_args, funcExpr->getSourceRange(),
+             ((Expr **)Args)[NumArgsInProto+1]->getSourceRange());
+      }
+      NumArgsToCheck = NumArgsInProto;
+    }
+    // Continue to check argument types (even if we have too few/many args).
+    for (unsigned i = 0; i < NumArgsToCheck; i++) {
+      Expr *argExpr = ((Expr **)Args)[i];
+      assert(argExpr && "ParseCallExpr(): missing argument expression");
+      
+      QualType lhsType = proto->getArgType(i);
+      QualType rhsType = argExpr->getType();
+      
+      if (lhsType == rhsType) // common case, fast path...
+        continue;
+        
+      AssignmentCheckResult result = CheckAssignmentConstraints(lhsType,
+                                                                rhsType);
+      SourceLocation l = argExpr->getLocStart();
+
+      // decode the result (notice that AST's are still created for extensions).
+      switch (result) {
+      case Compatible:
+        break;
+      case PointerFromInt:
+        // check for null pointer constant (C99 6.3.2.3p3)
+        if (!argExpr->isNullPointerConstant()) {
+          Diag(l, diag::ext_typecheck_passing_pointer_int, 
+               lhsType.getAsString(), rhsType.getAsString(),
+               funcExpr->getSourceRange(), argExpr->getSourceRange());
+        }
+        break;
+      case IntFromPointer:
+        Diag(l, diag::ext_typecheck_passing_pointer_int, 
+             lhsType.getAsString(), rhsType.getAsString(),
+             funcExpr->getSourceRange(), argExpr->getSourceRange());
+        break;
+      case IncompatiblePointer:
+        Diag(l, diag::ext_typecheck_passing_incompatible_pointer, 
+             rhsType.getAsString(), lhsType.getAsString(),
+             funcExpr->getSourceRange(), argExpr->getSourceRange());
+        break;
+      case CompatiblePointerDiscardsQualifiers:
+        Diag(l, diag::ext_typecheck_passing_discards_qualifiers,
+             rhsType.getAsString(), lhsType.getAsString(),
+             funcExpr->getSourceRange(), argExpr->getSourceRange());
+        break;
+      case Incompatible:
+        return Diag(l, diag::err_typecheck_passing_incompatible,
+                 rhsType.getAsString(), lhsType.getAsString(),
+                 funcExpr->getSourceRange(), argExpr->getSourceRange());
+      }
+    }
+    // Even if the types checked, bail if we had the wrong number of arguments.
+    if ((NumArgsInCall != NumArgsInProto) && !proto->isVariadic())
+      return true;
+  }
+  return new CallExpr((Expr*)Fn, (Expr**)Args, NumArgsInCall, resultType,
+                      RParenLoc);
+}
+
+Action::ExprResult Sema::
+ParseCastExpr(SourceLocation LParenLoc, TypeTy *Ty,
+              SourceLocation RParenLoc, ExprTy *Op) {
+  // If error parsing type, ignore.
+  assert((Ty != 0) && "ParseCastExpr(): missing type");
+  // FIXME: Sema for cast is completely missing.
+  return new CastExpr(QualType::getFromOpaquePtr(Ty), (Expr*)Op, LParenLoc);
+}
+
+inline QualType Sema::CheckConditionalOperands( // C99 6.5.15
+  Expr *Cond, Expr *LHS, Expr *RHS, SourceLocation questionLoc) {
+  QualType cond = Cond->getType();
+  QualType lhs = LHS->getType();
+  QualType rhs = RHS->getType();
+  
+  assert(!cond.isNull() && "ParseConditionalOp(): no conditional type");
+  assert(!lhs.isNull() && "ParseConditionalOp(): no lhs type");
+  assert(!rhs.isNull() && "ParseConditionalOp(): no rhs type");
+
+  cond = UsualUnaryConversions(cond);
+  lhs = UsualUnaryConversions(lhs);
+  rhs = UsualUnaryConversions(rhs);
+  
+  // first, check the condition.
+  if (!cond->isScalarType()) { // C99 6.5.15p2
+    Diag(Cond->getLocStart(), diag::err_typecheck_cond_expect_scalar, 
+         cond.getAsString());
+    return QualType();
+  }
+  // now check the two expressions.
+  if (lhs->isArithmeticType() && rhs->isArithmeticType()) // C99 6.5.15p3,5
+    return UsualArithmeticConversions(lhs, rhs);
+    
+  if ((lhs->isStructureType() && rhs->isStructureType()) || // C99 6.5.15p3
+      (lhs->isUnionType() && rhs->isUnionType())) {
+    TagType *lTag = cast<TagType>(lhs.getCanonicalType());
+    TagType *rTag = cast<TagType>(rhs.getCanonicalType());
+    
+    if (lTag->getDecl()->getIdentifier() == rTag->getDecl()->getIdentifier()) 
+      return lhs;
+    else {
+      Diag(questionLoc, diag::err_typecheck_cond_incompatible_operands,
+           lhs.getAsString(), rhs.getAsString(),
+           LHS->getSourceRange(), RHS->getSourceRange());
+      return QualType();
+    }
+  }
+  if (lhs->isPointerType() && RHS->isNullPointerConstant()) // C99 6.5.15p3
+    return lhs;
+  if (rhs->isPointerType() && LHS->isNullPointerConstant())
+    return rhs;
+    
+  if (lhs->isPointerType() && rhs->isPointerType()) { // C99 6.5.15p3,6
+    QualType lhptee, rhptee;
+    
+    // get the "pointed to" type
+    lhptee = cast<PointerType>(lhs.getCanonicalType())->getPointeeType();
+    rhptee = cast<PointerType>(rhs.getCanonicalType())->getPointeeType();
+
+    // ignore qualifiers on void (C99 6.5.15p3, clause 6)
+    if (lhptee.getUnqualifiedType()->isVoidType() &&
+        (rhptee->isObjectType() || rhptee->isIncompleteType()))
+      return lhs;
+    if (rhptee.getUnqualifiedType()->isVoidType() &&
+        (lhptee->isObjectType() || lhptee->isIncompleteType()))
+      return rhs;
+
+    // FIXME: C99 6.5.15p6: If both operands are pointers to compatible types
+    // *or* to differently qualified versions of compatible types, the result
+    // type is a pointer to an appropriately qualified version of the 
+    // *composite* type.
+    if (!Type::typesAreCompatible(lhptee.getUnqualifiedType(), 
+                                  rhptee.getUnqualifiedType())) {
+      Diag(questionLoc, diag::ext_typecheck_cond_incompatible_pointers,
+           lhs.getAsString(), rhs.getAsString(),
+           LHS->getSourceRange(), RHS->getSourceRange());
+      return lhs; // FIXME: this is an _ext - is this return o.k?
+    }
+  }
+  if (lhs->isVoidType() && rhs->isVoidType()) // C99 6.5.15p3
+    return lhs;
+    
+  Diag(questionLoc, diag::err_typecheck_cond_incompatible_operands,
+       lhs.getAsString(), rhs.getAsString(),
+       LHS->getSourceRange(), RHS->getSourceRange());
+  return QualType();
+}
+
+/// ParseConditionalOp - Parse a ?: operation.  Note that 'LHS' may be null
+/// in the case of a the GNU conditional expr extension.
+Action::ExprResult Sema::ParseConditionalOp(SourceLocation QuestionLoc, 
+                                            SourceLocation ColonLoc,
+                                            ExprTy *Cond, ExprTy *LHS,
+                                            ExprTy *RHS) {
+  QualType result = CheckConditionalOperands((Expr *)Cond, (Expr *)LHS, 
+                                             (Expr *)RHS, QuestionLoc);
+  if (result.isNull())
+    return true;
+  return new ConditionalOperator((Expr*)Cond, (Expr*)LHS, (Expr*)RHS, result);
+}
+
+inline QualType Sema::DefaultFunctionArrayConversion(QualType t) {
+  if (t->isFunctionType()) // C99 6.3.2.1p4
+    return Context.getPointerType(t);
+  if (const ArrayType *ary = dyn_cast<ArrayType>(t.getCanonicalType()))
+    return Context.getPointerType(ary->getElementType()); // C99 6.3.2.1p3
+  return t;
+}
+
+/// UsualUnaryConversion - Performs various conversions that are common to most
+/// operators (C99 6.3). The conversions of array and function types are 
+/// sometimes surpressed. For example, the array->pointer conversion doesn't
+/// apply if the array is an argument to the sizeof or address (&) operators.
+/// In these instances, this routine should *not* be called.
+QualType Sema::UsualUnaryConversions(QualType t) {
+  assert(!t.isNull() && "UsualUnaryConversions - missing type");
+  
+  if (t->isPromotableIntegerType()) // C99 6.3.1.1p2
+    return Context.IntTy;
+  return DefaultFunctionArrayConversion(t);
+}
+
+/// UsualArithmeticConversions - Performs various conversions that are common to 
+/// binary operators (C99 6.3.1.8). If both operands aren't arithmetic, this
+/// routine returns the first non-arithmetic type found. The client is 
+/// responsible for emitting appropriate error diagnostics.
+QualType Sema::UsualArithmeticConversions(QualType &lhs, QualType &rhs) {
+  lhs = UsualUnaryConversions(lhs);
+  rhs = UsualUnaryConversions(rhs);
+  
+  // If both types are identical, no conversion is needed.
+  if (lhs == rhs) 
+    return lhs;
+  
+  // If either side is a non-arithmetic type (e.g. a pointer), we are done.
+  // The caller can deal with this (e.g. pointer + int).
+  if (!lhs->isArithmeticType())
+    return lhs;
+  if (!rhs->isArithmeticType())
+    return rhs;
+    
+  // At this point, we have two different arithmetic types. 
+  
+  // Handle complex types first (C99 6.3.1.8p1).
+  if (lhs->isComplexType() || rhs->isComplexType()) {
+    // if we have an integer operand, the result is the complex type.
+    if (rhs->isIntegerType())
+      return lhs;
+    if (lhs->isIntegerType())
+      return rhs;
+
+    return Context.maxComplexType(lhs, rhs);
+  }
+  
+  // Now handle "real" floating types (i.e. float, double, long double).
+  if (lhs->isRealFloatingType() || rhs->isRealFloatingType()) {
+    // if we have an integer operand, the result is the real floating type.
+    if (rhs->isIntegerType())
+      return lhs;
+    if (lhs->isIntegerType())
+      return rhs;
+
+    // we have two real floating types, float/complex combos were handled above.
+    return Context.maxFloatingType(lhs, rhs);
+  }
+  return Context.maxIntegerType(lhs, rhs);
+}
+
+// CheckPointerTypesForAssignment - This is a very tricky routine (despite
+// being closely modeled after the C99 spec:-). The odd characteristic of this 
+// routine is it effectively iqnores the qualifiers on the top level pointee.
+// This circumvents the usual type rules specified in 6.2.7p1 & 6.7.5.[1-3].
+// FIXME: add a couple examples in this comment.
+Sema::AssignmentCheckResult 
+Sema::CheckPointerTypesForAssignment(QualType lhsType, QualType rhsType) {
+  QualType lhptee, rhptee;
+  
+  // get the "pointed to" type (ignoring qualifiers at the top level)
+  lhptee = cast<PointerType>(lhsType.getCanonicalType())->getPointeeType();
+  rhptee = cast<PointerType>(rhsType.getCanonicalType())->getPointeeType();
+  
+  // make sure we operate on the canonical type
+  lhptee = lhptee.getCanonicalType();
+  rhptee = rhptee.getCanonicalType();
+
+  AssignmentCheckResult r = Compatible;
+  
+  // C99 6.5.16.1p1: This following citation is common to constraints 
+  // 3 & 4 (below). ...and the type *pointed to* by the left has all the 
+  // qualifiers of the type *pointed to* by the right; 
+  if ((lhptee.getQualifiers() & rhptee.getQualifiers()) != 
+       rhptee.getQualifiers())
+    r = CompatiblePointerDiscardsQualifiers;
+
+  // C99 6.5.16.1p1 (constraint 4): If one operand is a pointer to an object or 
+  // incomplete type and the other is a pointer to a qualified or unqualified 
+  // version of void...
+  if (lhptee.getUnqualifiedType()->isVoidType() &&
+      (rhptee->isObjectType() || rhptee->isIncompleteType()))
+    ;
+  else if (rhptee.getUnqualifiedType()->isVoidType() &&
+      (lhptee->isObjectType() || lhptee->isIncompleteType()))
+    ;
+  // C99 6.5.16.1p1 (constraint 3): both operands are pointers to qualified or 
+  // unqualified versions of compatible types, ...
+  else if (!Type::typesAreCompatible(lhptee.getUnqualifiedType(), 
+                                     rhptee.getUnqualifiedType()))
+    r = IncompatiblePointer; // this "trumps" PointerAssignDiscardsQualifiers
+  return r;
+}
+
+/// CheckAssignmentConstraints (C99 6.5.16) - This routine currently 
+/// has code to accommodate several GCC extensions when type checking 
+/// pointers. Here are some objectionable examples that GCC considers warnings:
+///
+///  int a, *pint;
+///  short *pshort;
+///  struct foo *pfoo;
+///
+///  pint = pshort; // warning: assignment from incompatible pointer type
+///  a = pint; // warning: assignment makes integer from pointer without a cast
+///  pint = a; // warning: assignment makes pointer from integer without a cast
+///  pint = pfoo; // warning: assignment from incompatible pointer type
+///
+/// As a result, the code for dealing with pointers is more complex than the
+/// C99 spec dictates. 
+/// Note: the warning above turn into errors when -pedantic-errors is enabled. 
+///
+Sema::AssignmentCheckResult
+Sema::CheckAssignmentConstraints(QualType lhsType, QualType rhsType) {
+  // This check seems unnatural, however it is necessary to insure the proper
+  // conversion of functions/arrays. If the conversion were done for all
+  // DeclExpr's (created by ParseIdentifierExpr), it would mess up the unary
+  // expressions that surpress this implicit conversion (&, sizeof).
+  rhsType = DefaultFunctionArrayConversion(rhsType);
+    
+  if (lhsType->isArithmeticType() && rhsType->isArithmeticType()) {
+    if (lhsType->isVectorType() || rhsType->isVectorType()) {
+      if (lhsType.getCanonicalType() != rhsType.getCanonicalType())
+        return Incompatible;
+    }
+    return Compatible;
+  } else if (lhsType->isPointerType()) {
+    if (rhsType->isIntegerType())
+      return PointerFromInt;
+      
+    if (rhsType->isPointerType())
+      return CheckPointerTypesForAssignment(lhsType, rhsType);
+  } else if (rhsType->isPointerType()) {
+    // C99 6.5.16.1p1: the left operand is _Bool and the right is a pointer.
+    if ((lhsType->isIntegerType()) && (lhsType != Context.BoolTy))
+      return IntFromPointer;
+
+    if (lhsType->isPointerType()) 
+      return CheckPointerTypesForAssignment(lhsType, rhsType);
+  } else if (isa<TagType>(lhsType) && isa<TagType>(rhsType)) {
+    if (Type::tagTypesAreCompatible(lhsType, rhsType))
+      return Compatible;
+  } else if (lhsType->isReferenceType() || rhsType->isReferenceType()) {
+    if (Type::referenceTypesAreCompatible(lhsType, rhsType))
+      return Compatible;
+  }
+  return Incompatible;
+}
+
+inline void Sema::InvalidOperands(SourceLocation loc, Expr *lex, Expr *rex) {
+  Diag(loc, diag::err_typecheck_invalid_operands, 
+       lex->getType().getAsString(), rex->getType().getAsString(),
+       lex->getSourceRange(), rex->getSourceRange());
+}
+
+inline QualType Sema::CheckVectorOperands(SourceLocation loc, Expr *lex, 
+                                                              Expr *rex) {
+  QualType lhsType = lex->getType(), rhsType = rex->getType();
+  
+  // make sure the vector types are identical. 
+  if (lhsType == rhsType)
+    return lhsType;
+  // You cannot convert between vector values of different size.
+  Diag(loc, diag::err_typecheck_vector_not_convertable, 
+       lex->getType().getAsString(), rex->getType().getAsString(),
+       lex->getSourceRange(), rex->getSourceRange());
+  return QualType();
+}    
+
+inline QualType Sema::CheckMultiplyDivideOperands(
+  Expr *lex, Expr *rex, SourceLocation loc) 
+{
+  QualType lhsType = lex->getType(), rhsType = rex->getType();
+  
+  if (lhsType->isVectorType() || rhsType->isVectorType())
+    return CheckVectorOperands(loc, lex, rex);
+  QualType resType = UsualArithmeticConversions(lhsType, rhsType);
+  
+  if (resType->isArithmeticType())
+    return resType;
+  InvalidOperands(loc, lex, rex);
+  return QualType();
+}
+
+inline QualType Sema::CheckRemainderOperands(
+  Expr *lex, Expr *rex, SourceLocation loc) 
+{
+  QualType lhsType = lex->getType(), rhsType = rex->getType();
+  QualType resType = UsualArithmeticConversions(lhsType, rhsType);
+  
+  if (resType->isIntegerType())
+    return resType;
+  InvalidOperands(loc, lex, rex);
+  return QualType();
+}
+
+inline QualType Sema::CheckAdditionOperands( // C99 6.5.6
+  Expr *lex, Expr *rex, SourceLocation loc) 
+{
+  QualType lhsType = lex->getType(), rhsType = rex->getType();
+
+  if (lhsType->isVectorType() || rhsType->isVectorType())
+    return CheckVectorOperands(loc, lex, rex);    
+  QualType resType = UsualArithmeticConversions(lhsType, rhsType);
+
+  // handle the common case first (both operands are arithmetic).
+  if (resType->isArithmeticType())
+    return resType;
+
+  if ((lhsType->isPointerType() && rhsType->isIntegerType()) ||
+      (lhsType->isIntegerType() && rhsType->isPointerType()))
+    return resType;
+  InvalidOperands(loc, lex, rex);
+  return QualType();
+}
+
+inline QualType Sema::CheckSubtractionOperands( // C99 6.5.6
+  Expr *lex, Expr *rex, SourceLocation loc) 
+{
+  QualType lhsType = lex->getType(), rhsType = rex->getType();
+
+  if (lhsType->isVectorType() || rhsType->isVectorType())
+    return CheckVectorOperands(loc, lex, rex);
+  QualType resType = UsualArithmeticConversions(lhsType, rhsType);
+  
+  // handle the common case first (both operands are arithmetic).
+  if (resType->isArithmeticType())
+    return resType;
+  if ((lhsType->isPointerType() && rhsType->isIntegerType()) ||
+      (lhsType->isPointerType() && rhsType->isPointerType()))
+    return resType;
+  InvalidOperands(loc, lex, rex);
+  return QualType();
+}
+
+inline QualType Sema::CheckShiftOperands( // C99 6.5.7
+  Expr *lex, Expr *rex, SourceLocation loc)
+{
+  // FIXME: Shifts don't perform usual arithmetic conversions.  This is wrong
+  // for int << longlong -> the result type should be int, not long long.
+  QualType lhsType = lex->getType(), rhsType = rex->getType();
+  QualType resType = UsualArithmeticConversions(lhsType, rhsType);
+  
+  if (resType->isIntegerType())
+    return resType;
+  InvalidOperands(loc, lex, rex);
+  return QualType();
+}
+
+inline QualType Sema::CheckRelationalOperands( // C99 6.5.8
+  Expr *lex, Expr *rex, SourceLocation loc)
+{
+  QualType lType = UsualUnaryConversions(lex->getType());
+  QualType rType = UsualUnaryConversions(rex->getType());
+  
+  if (lType->isRealType() && rType->isRealType())
+    return Context.IntTy;
+  
+  if (lType->isPointerType()) {
+    if (rType->isPointerType())
+      return Context.IntTy;
+    if (rType->isIntegerType()) {
+      if (!rex->isNullPointerConstant())
+        Diag(loc, diag::ext_typecheck_comparison_of_pointer_integer,
+             lex->getSourceRange(), rex->getSourceRange());
+      return Context.IntTy; // the previous diagnostic is a GCC extension.
+    }
+  } else if (rType->isPointerType()) {
+    if (lType->isIntegerType()) {
+      if (!lex->isNullPointerConstant())
+        Diag(loc, diag::ext_typecheck_comparison_of_pointer_integer,
+             lex->getSourceRange(), rex->getSourceRange());
+      return Context.IntTy; // the previous diagnostic is a GCC extension.
+    }
+  }
+  InvalidOperands(loc, lex, rex);
+  return QualType();
+}
+
+inline QualType Sema::CheckEqualityOperands( // C99 6.5.9
+  Expr *lex, Expr *rex, SourceLocation loc)
+{
+  QualType lType = UsualUnaryConversions(lex->getType());
+  QualType rType = UsualUnaryConversions(rex->getType());
+  
+  if (lType->isArithmeticType() && rType->isArithmeticType())
+    return Context.IntTy;
+    
+  if (lType->isPointerType()) {
+    if (rType->isPointerType())
+      return Context.IntTy;
+    if (rType->isIntegerType()) {
+      if (!rex->isNullPointerConstant())
+        Diag(loc, diag::ext_typecheck_comparison_of_pointer_integer,
+             lex->getSourceRange(), rex->getSourceRange());
+      return Context.IntTy; // the previous diagnostic is a GCC extension.
+    }
+  } else if (rType->isPointerType()) {
+    if (lType->isIntegerType()) {
+      if (!lex->isNullPointerConstant())
+        Diag(loc, diag::ext_typecheck_comparison_of_pointer_integer,
+             lex->getSourceRange(), rex->getSourceRange());
+      return Context.IntTy; // the previous diagnostic is a GCC extension.
+    }
+  }
+  InvalidOperands(loc, lex, rex);
+  return QualType();
+}
+
+inline QualType Sema::CheckBitwiseOperands(
+  Expr *lex, Expr *rex, SourceLocation loc) 
+{
+  QualType lhsType = lex->getType(), rhsType = rex->getType();
+  
+  if (lhsType->isVectorType() || rhsType->isVectorType())
+    return CheckVectorOperands(loc, lex, rex);
+  QualType resType = UsualArithmeticConversions(lhsType, rhsType);
+  
+  if (resType->isIntegerType())
+    return resType;
+  InvalidOperands(loc, lex, rex);
+  return QualType();
+}
+
+inline QualType Sema::CheckLogicalOperands( // C99 6.5.[13,14]
+  Expr *lex, Expr *rex, SourceLocation loc) 
+{
+  QualType lhsType = UsualUnaryConversions(lex->getType());
+  QualType rhsType = UsualUnaryConversions(rex->getType());
+  
+  if (lhsType->isScalarType() || rhsType->isScalarType())
+    return Context.IntTy;
+  InvalidOperands(loc, lex, rex);
+  return QualType();
+}
+
+inline QualType Sema::CheckAssignmentOperands( // C99 6.5.16.1
+  Expr *lex, Expr *rex, SourceLocation loc, QualType compoundType) 
+{
+  QualType lhsType = lex->getType();
+  QualType rhsType = compoundType.isNull() ? rex->getType() : compoundType;
+  bool hadError = false;
+  Expr::isModifiableLvalueResult mlval = lex->isModifiableLvalue(); 
+
+  switch (mlval) { // C99 6.5.16p2
+    case Expr::MLV_Valid: 
+      break;
+    case Expr::MLV_ConstQualified:
+      Diag(loc, diag::err_typecheck_assign_const, lex->getSourceRange());
+      hadError = true;
+      break;
+    case Expr::MLV_ArrayType: 
+      Diag(loc, diag::err_typecheck_array_not_modifiable_lvalue,
+           lhsType.getAsString(), lex->getSourceRange());
+      return QualType(); 
+    case Expr::MLV_NotObjectType: 
+      Diag(loc, diag::err_typecheck_non_object_not_modifiable_lvalue,
+           lhsType.getAsString(), lex->getSourceRange());
+      return QualType();
+    case Expr::MLV_InvalidExpression:
+      Diag(loc, diag::err_typecheck_expression_not_modifiable_lvalue,
+           lex->getSourceRange());
+      return QualType();
+    case Expr::MLV_IncompleteType:
+    case Expr::MLV_IncompleteVoidType:
+      Diag(loc, diag::err_typecheck_incomplete_type_not_modifiable_lvalue,
+           lhsType.getAsString(), lex->getSourceRange());
+      return QualType();
+  }
+  if (lhsType == rhsType) // common case, fast path...
+    return lhsType;
+  
+  AssignmentCheckResult result = CheckAssignmentConstraints(lhsType, rhsType);
+
+  // decode the result (notice that extensions still return a type).
+  switch (result) {
+  case Compatible:
+    break;
+  case Incompatible:
+    Diag(loc, diag::err_typecheck_assign_incompatible, 
+         lhsType.getAsString(), rhsType.getAsString(),
+         lex->getSourceRange(), rex->getSourceRange());
+    hadError = true;
+    break;
+  case PointerFromInt:
+    // check for null pointer constant (C99 6.3.2.3p3)
+    if (compoundType.isNull() && !rex->isNullPointerConstant()) {
+      Diag(loc, diag::ext_typecheck_assign_pointer_int,
+           lhsType.getAsString(), rhsType.getAsString(),
+           lex->getSourceRange(), rex->getSourceRange());
+    }
+    break;
+  case IntFromPointer: 
+    Diag(loc, diag::ext_typecheck_assign_pointer_int, 
+         lhsType.getAsString(), rhsType.getAsString(),
+         lex->getSourceRange(), rex->getSourceRange());
+    break;
+  case IncompatiblePointer:
+    Diag(loc, diag::ext_typecheck_assign_incompatible_pointer,
+         lhsType.getAsString(), rhsType.getAsString(),
+         lex->getSourceRange(), rex->getSourceRange());
+    break;
+  case CompatiblePointerDiscardsQualifiers:
+    Diag(loc, diag::ext_typecheck_assign_discards_qualifiers,
+         lhsType.getAsString(), rhsType.getAsString(),
+         lex->getSourceRange(), rex->getSourceRange());
+    break;
+  }
+  // C99 6.5.16p3: The type of an assignment expression is the type of the
+  // left operand unless the left operand has qualified type, in which case
+  // it is the unqualified version of the type of the left operand. 
+  // C99 6.5.16.1p2: In simple assignment, the value of the right operand
+  // is converted to the type of the assignment expression (above).
+  // C++ 5.17p1: the type of the assignment expression is that of its left oprdu.
+  return hadError ? QualType() : lhsType.getUnqualifiedType();
+}
+
+inline QualType Sema::CheckCommaOperands( // C99 6.5.17
+  Expr *lex, Expr *rex, SourceLocation loc) {
+  return UsualUnaryConversions(rex->getType());
+}
+
+QualType Sema::CheckIncrementDecrementOperand(Expr *op, SourceLocation OpLoc) {
+  QualType lhsType = op->getType(), rhsType = Context.IntTy;
+  QualType resType = UsualArithmeticConversions(lhsType, rhsType);
+  assert(!resType.isNull() && "no type for increment/decrement expression");
+
+  // C99 6.5.2.4p1
+  if (const PointerType *pt = dyn_cast<PointerType>(resType)) {
+    if (!pt->getPointeeType()->isObjectType()) { // C99 6.5.2.4p2, 6.5.6p2
+      Diag(OpLoc, diag::err_typecheck_arithmetic_incomplete_type,
+           resType.getAsString(), op->getSourceRange());
+      return QualType();
+    }
+  } else if (!resType->isRealType()) { 
+    // FIXME: Allow Complex as a GCC extension.
+    Diag(OpLoc, diag::err_typecheck_illegal_increment_decrement,
+         resType.getAsString(), op->getSourceRange());
+    return QualType(); 
+  }
+  // At this point, we know we have a real or pointer type. Now make sure
+  // the operand is a modifiable lvalue.
+  Expr::isModifiableLvalueResult mlval = op->isModifiableLvalue();
+  if (mlval != Expr::MLV_Valid) {
+    // FIXME: emit a more precise diagnostic...
+    Diag(OpLoc, diag::err_typecheck_invalid_lvalue_incr_decr,
+         op->getSourceRange());
+    return QualType();
+  }
+  return resType;
+}
+
+/// getPrimaryDeclaration - Helper function for CheckAddressOfOperand().
+/// This routine allows us to typecheck complex/recursive expressions
+/// where the declaration is needed for type checking. Here are some
+/// examples: &s.xx, &s.zz[1].yy, &(1+2), &(XX), &"123"[2].
+static Decl *getPrimaryDeclaration(Expr *e) {
+  switch (e->getStmtClass()) {
+  case Stmt::DeclRefExprClass:
+    return cast<DeclRefExpr>(e)->getDecl();
+  case Stmt::MemberExprClass:
+    return getPrimaryDeclaration(cast<MemberExpr>(e)->getBase());
+  case Stmt::ArraySubscriptExprClass:
+    return getPrimaryDeclaration(cast<ArraySubscriptExpr>(e)->getBase());
+  case Stmt::CallExprClass:
+    return getPrimaryDeclaration(cast<CallExpr>(e)->getCallee());
+  case Stmt::UnaryOperatorClass:
+    return getPrimaryDeclaration(cast<UnaryOperator>(e)->getSubExpr());
+  case Stmt::ParenExprClass:
+    return getPrimaryDeclaration(cast<ParenExpr>(e)->getSubExpr());
+  default:
+    return 0;
+  }
+}
+
+/// CheckAddressOfOperand - The operand of & must be either a function
+/// designator or an lvalue designating an object. If it is an lvalue, the 
+/// object cannot be declared with storage class register or be a bit field.
+/// Note: The usual conversions are *not* applied to the operand of the & 
+/// operator (C99 6.3.2.1p[2-4]), and its result is never an lvalue.
+QualType Sema::CheckAddressOfOperand(Expr *op, SourceLocation OpLoc) {
+  Decl *dcl = getPrimaryDeclaration(op);
+  Expr::isLvalueResult lval = op->isLvalue();
+  
+  if (lval != Expr::LV_Valid) { // C99 6.5.3.2p1
+    if (dcl && isa<FunctionDecl>(dcl)) // allow function designators
+      ;  
+    else { // FIXME: emit more specific diag...
+      Diag(OpLoc, diag::err_typecheck_invalid_lvalue_addrof, 
+           op->getSourceRange());
+      return QualType();
+    }
+  } else if (dcl) {
+    // We have an lvalue with a decl. Make sure the decl is not declared 
+    // with the register storage-class specifier.
+    if (const VarDecl *vd = dyn_cast<VarDecl>(dcl)) {
+      if (vd->getStorageClass() == VarDecl::Register) {
+        Diag(OpLoc, diag::err_typecheck_address_of_register, 
+             op->getSourceRange());
+        return QualType();
+      }
+    } else 
+      assert(0 && "Unknown/unexpected decl type");
+    
+    // FIXME: add check for bitfields!
+  }
+  // If the operand has type "type", the result has type "pointer to type".
+  return Context.getPointerType(op->getType());
+}
+
+QualType Sema::CheckIndirectionOperand(Expr *op, SourceLocation OpLoc) {
+  QualType qType = UsualUnaryConversions(op->getType());
+  
+  assert(!qType.isNull() && "no type for * expression");
+
+  if (PointerType *PT = dyn_cast<PointerType>(qType.getCanonicalType())) {
+    QualType ptype = PT->getPointeeType();
+    // C99 6.5.3.2p4. "if it points to an object,...".
+    if (ptype->isIncompleteType()) { // An incomplete type is not an object
+      // GCC compat: special case 'void *' (treat as warning).
+      if (ptype->isVoidType()) {
+        Diag(OpLoc, diag::ext_typecheck_deref_ptr_to_void, 
+             qType.getAsString(), op->getSourceRange());
+      } else {
+        Diag(OpLoc, diag::err_typecheck_deref_incomplete_type, 
+             ptype.getAsString(), op->getSourceRange());
+        return QualType();
+      }
+    }
+    return ptype;
+  }
+  Diag(OpLoc, diag::err_typecheck_indirection_requires_pointer, 
+       qType.getAsString(), op->getSourceRange());
+  return QualType();
+}
+
+static inline BinaryOperator::Opcode ConvertTokenKindToBinaryOpcode(
+  tok::TokenKind Kind) {
+  BinaryOperator::Opcode Opc;
+  switch (Kind) {
+  default: assert(0 && "Unknown binop!");
+  case tok::star:                 Opc = BinaryOperator::Mul; break;
+  case tok::slash:                Opc = BinaryOperator::Div; break;
+  case tok::percent:              Opc = BinaryOperator::Rem; break;
+  case tok::plus:                 Opc = BinaryOperator::Add; break;
+  case tok::minus:                Opc = BinaryOperator::Sub; break;
+  case tok::lessless:             Opc = BinaryOperator::Shl; break;
+  case tok::greatergreater:       Opc = BinaryOperator::Shr; break;
+  case tok::lessequal:            Opc = BinaryOperator::LE; break;
+  case tok::less:                 Opc = BinaryOperator::LT; break;
+  case tok::greaterequal:         Opc = BinaryOperator::GE; break;
+  case tok::greater:              Opc = BinaryOperator::GT; break;
+  case tok::exclaimequal:         Opc = BinaryOperator::NE; break;
+  case tok::equalequal:           Opc = BinaryOperator::EQ; break;
+  case tok::amp:                  Opc = BinaryOperator::And; break;
+  case tok::caret:                Opc = BinaryOperator::Xor; break;
+  case tok::pipe:                 Opc = BinaryOperator::Or; break;
+  case tok::ampamp:               Opc = BinaryOperator::LAnd; break;
+  case tok::pipepipe:             Opc = BinaryOperator::LOr; break;
+  case tok::equal:                Opc = BinaryOperator::Assign; break;
+  case tok::starequal:            Opc = BinaryOperator::MulAssign; break;
+  case tok::slashequal:           Opc = BinaryOperator::DivAssign; break;
+  case tok::percentequal:         Opc = BinaryOperator::RemAssign; break;
+  case tok::plusequal:            Opc = BinaryOperator::AddAssign; break;
+  case tok::minusequal:           Opc = BinaryOperator::SubAssign; break;
+  case tok::lesslessequal:        Opc = BinaryOperator::ShlAssign; break;
+  case tok::greatergreaterequal:  Opc = BinaryOperator::ShrAssign; break;
+  case tok::ampequal:             Opc = BinaryOperator::AndAssign; break;
+  case tok::caretequal:           Opc = BinaryOperator::XorAssign; break;
+  case tok::pipeequal:            Opc = BinaryOperator::OrAssign; break;
+  case tok::comma:                Opc = BinaryOperator::Comma; break;
+  }
+  return Opc;
+}
+
+static inline UnaryOperator::Opcode ConvertTokenKindToUnaryOpcode(
+  tok::TokenKind Kind) {
+  UnaryOperator::Opcode Opc;
+  switch (Kind) {
+  default: assert(0 && "Unknown unary op!");
+  case tok::plusplus:     Opc = UnaryOperator::PreInc; break;
+  case tok::minusminus:   Opc = UnaryOperator::PreDec; break;
+  case tok::amp:          Opc = UnaryOperator::AddrOf; break;
+  case tok::star:         Opc = UnaryOperator::Deref; break;
+  case tok::plus:         Opc = UnaryOperator::Plus; break;
+  case tok::minus:        Opc = UnaryOperator::Minus; break;
+  case tok::tilde:        Opc = UnaryOperator::Not; break;
+  case tok::exclaim:      Opc = UnaryOperator::LNot; break;
+  case tok::kw_sizeof:    Opc = UnaryOperator::SizeOf; break;
+  case tok::kw___alignof: Opc = UnaryOperator::AlignOf; break;
+  case tok::kw___real:    Opc = UnaryOperator::Real; break;
+  case tok::kw___imag:    Opc = UnaryOperator::Imag; break;
+  case tok::kw___extension__: Opc = UnaryOperator::Extension; break;
+  }
+  return Opc;
+}
+
+// Binary Operators.  'Tok' is the token for the operator.
+Action::ExprResult Sema::ParseBinOp(SourceLocation TokLoc, tok::TokenKind Kind,
+                                    ExprTy *LHS, ExprTy *RHS) {
+  BinaryOperator::Opcode Opc = ConvertTokenKindToBinaryOpcode(Kind);
+  Expr *lhs = (Expr *)LHS, *rhs = (Expr*)RHS;
+
+  assert((lhs != 0) && "ParseBinOp(): missing left expression");
+  assert((rhs != 0) && "ParseBinOp(): missing right expression");
+
+  QualType ResultTy;  // Result type of the binary operator.
+  QualType CompTy;    // Computation type for compound assignments (e.g. '+=')
+  
+  switch (Opc) {
+  default:
+    assert(0 && "Unknown binary expr!");
+  case BinaryOperator::Assign:
+    ResultTy = CheckAssignmentOperands(lhs, rhs, TokLoc, QualType());
+    break;
+  case BinaryOperator::Mul: 
+  case BinaryOperator::Div:
+    ResultTy = CheckMultiplyDivideOperands(lhs, rhs, TokLoc);
+    break;
+  case BinaryOperator::Rem:
+    ResultTy = CheckRemainderOperands(lhs, rhs, TokLoc);
+    break;
+  case BinaryOperator::Add:
+    ResultTy = CheckAdditionOperands(lhs, rhs, TokLoc);
+    break;
+  case BinaryOperator::Sub:
+    ResultTy = CheckSubtractionOperands(lhs, rhs, TokLoc);
+    break;
+  case BinaryOperator::Shl: 
+  case BinaryOperator::Shr:
+    ResultTy = CheckShiftOperands(lhs, rhs, TokLoc);
+    break;
+  case BinaryOperator::LE:
+  case BinaryOperator::LT:
+  case BinaryOperator::GE:
+  case BinaryOperator::GT:
+    ResultTy = CheckRelationalOperands(lhs, rhs, TokLoc);
+    break;
+  case BinaryOperator::EQ:
+  case BinaryOperator::NE:
+    ResultTy = CheckEqualityOperands(lhs, rhs, TokLoc);
+    break;
+  case BinaryOperator::And:
+  case BinaryOperator::Xor:
+  case BinaryOperator::Or:
+    ResultTy = CheckBitwiseOperands(lhs, rhs, TokLoc);
+    break;
+  case BinaryOperator::LAnd:
+  case BinaryOperator::LOr:
+    ResultTy = CheckLogicalOperands(lhs, rhs, TokLoc);
+    break;
+  case BinaryOperator::MulAssign:
+  case BinaryOperator::DivAssign:
+    CompTy = CheckMultiplyDivideOperands(lhs, rhs, TokLoc);
+    if (!CompTy.isNull())
+      ResultTy = CheckAssignmentOperands(lhs, rhs, TokLoc, CompTy);
+    break;
+  case BinaryOperator::RemAssign:
+    CompTy = CheckRemainderOperands(lhs, rhs, TokLoc);
+    if (!CompTy.isNull())
+      ResultTy = CheckAssignmentOperands(lhs, rhs, TokLoc, CompTy);
+    break;
+  case BinaryOperator::AddAssign:
+    CompTy = CheckAdditionOperands(lhs, rhs, TokLoc);
+    if (!CompTy.isNull())
+      ResultTy = CheckAssignmentOperands(lhs, rhs, TokLoc, CompTy);
+    break;
+  case BinaryOperator::SubAssign:
+    CompTy = CheckSubtractionOperands(lhs, rhs, TokLoc);
+    if (!CompTy.isNull())
+      ResultTy = CheckAssignmentOperands(lhs, rhs, TokLoc, CompTy);
+    break;
+  case BinaryOperator::ShlAssign:
+  case BinaryOperator::ShrAssign:
+    CompTy = CheckShiftOperands(lhs, rhs, TokLoc);
+    if (!CompTy.isNull())
+      ResultTy = CheckAssignmentOperands(lhs, rhs, TokLoc, CompTy);
+    break;
+  case BinaryOperator::AndAssign:
+  case BinaryOperator::XorAssign:
+  case BinaryOperator::OrAssign:
+    CompTy = CheckBitwiseOperands(lhs, rhs, TokLoc);
+    if (!CompTy.isNull())
+      ResultTy = CheckAssignmentOperands(lhs, rhs, TokLoc, CompTy);
+    break;
+  case BinaryOperator::Comma:
+    ResultTy = CheckCommaOperands(lhs, rhs, TokLoc);
+    break;
+  }
+  if (ResultTy.isNull())
+    return true;
+  if (CompTy.isNull())
+    return new BinaryOperator(lhs, rhs, Opc, ResultTy);
+  else
+    return new CompoundAssignOperator(lhs, rhs, Opc, ResultTy, CompTy);
+}
+
+// Unary Operators.  'Tok' is the token for the operator.
+Action::ExprResult Sema::ParseUnaryOp(SourceLocation OpLoc, tok::TokenKind Op,
+                                      ExprTy *input) {
+  Expr *Input = (Expr*)input;
+  UnaryOperator::Opcode Opc = ConvertTokenKindToUnaryOpcode(Op);
+  QualType resultType;
+  switch (Opc) {
+  default:
+    assert(0 && "Unimplemented unary expr!");
+  case UnaryOperator::PreInc:
+  case UnaryOperator::PreDec:
+    resultType = CheckIncrementDecrementOperand(Input, OpLoc);
+    break;
+  case UnaryOperator::AddrOf: 
+    resultType = CheckAddressOfOperand(Input, OpLoc);
+    break;
+  case UnaryOperator::Deref: 
+    resultType = CheckIndirectionOperand(Input, OpLoc);
+    break;
+  case UnaryOperator::Plus:
+  case UnaryOperator::Minus:
+    resultType = UsualUnaryConversions(Input->getType());
+    if (!resultType->isArithmeticType())  // C99 6.5.3.3p1
+      return Diag(OpLoc, diag::err_typecheck_unary_expr, 
+                  resultType.getAsString());
+    break;
+  case UnaryOperator::Not: // bitwise complement
+    if (Input->getType()->isVectorType())
+      resultType = Input->getType();
+    else {
+      resultType = UsualUnaryConversions(Input->getType());
+      if (!resultType->isIntegerType())  // C99 6.5.3.3p1
+        return Diag(OpLoc, diag::err_typecheck_unary_expr,
+                    resultType.getAsString());
+    }
+    break;
+  case UnaryOperator::LNot: // logical negation
+    // Unlike +/-/~, integer promotions aren't done here (C99 6.5.3.3p5).
+    resultType = DefaultFunctionArrayConversion(Input->getType());
+    if (!resultType->isScalarType()) // C99 6.5.3.3p1
+      return Diag(OpLoc, diag::err_typecheck_unary_expr,
+                  resultType.getAsString());
+    // LNot always has type int. C99 6.5.3.3p5.
+    resultType = Context.IntTy;
+    break;
+  case UnaryOperator::SizeOf:
+    resultType = CheckSizeOfAlignOfOperand(Input->getType(), OpLoc, true);
+    break;
+  case UnaryOperator::AlignOf:
+    resultType = CheckSizeOfAlignOfOperand(Input->getType(), OpLoc, false);
+    break;
+  case UnaryOperator::Extension:
+    // FIXME: does __extension__ cause any promotions? I would think not.
+    resultType = Input->getType();
+    break;
+  }
+  if (resultType.isNull())
+    return true;
+  return new UnaryOperator(Input, Opc, resultType, OpLoc);
+}
+
+/// ParseAddrLabel - Parse the GNU address of label extension: "&&foo".
+Sema::ExprResult Sema::ParseAddrLabel(SourceLocation OpLoc, 
+                                      SourceLocation LabLoc,
+                                      IdentifierInfo *LabelII) {
+  // Look up the record for this label identifier.
+  LabelStmt *&LabelDecl = LabelMap[LabelII];
+  
+  // If we haven't seen this label yet, create a forward reference.
+  if (LabelDecl == 0)
+    LabelDecl = new LabelStmt(LabLoc, LabelII, 0);
+  
+  // Create the AST node.  The address of a label always has type 'void*'.
+  return new AddrLabel(OpLoc, LabLoc, LabelDecl,
+                       Context.getPointerType(Context.VoidTy));
+}
+
diff --git a/Sema/SemaExprCXX.cpp b/Sema/SemaExprCXX.cpp
new file mode 100644
index 0000000..74be79a
--- /dev/null
+++ b/Sema/SemaExprCXX.cpp
@@ -0,0 +1,44 @@
+//===--- SemaExprCXX.cpp - Semantic Analysis for Expressions --------------===//
+//
+//                     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 semantic analysis for C++ expressions.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Sema.h"
+#include "clang/AST/ExprCXX.h"
+using namespace clang;
+
+/// ParseCXXCasts - Parse {dynamic,static,reinterpret,const}_cast's.
+Action::ExprResult
+Sema::ParseCXXCasts(SourceLocation OpLoc, tok::TokenKind Kind,
+                    SourceLocation LAngleBracketLoc, TypeTy *Ty,
+                    SourceLocation RAngleBracketLoc,
+                    SourceLocation LParenLoc, ExprTy *E,
+                    SourceLocation RParenLoc) {
+  CXXCastExpr::Opcode Op;
+
+  switch (Kind) {
+  default: assert(0 && "Unknown C++ cast!");
+  case tok::kw_const_cast:       Op = CXXCastExpr::ConstCast;       break;
+  case tok::kw_dynamic_cast:     Op = CXXCastExpr::DynamicCast;     break;
+  case tok::kw_reinterpret_cast: Op = CXXCastExpr::ReinterpretCast; break;
+  case tok::kw_static_cast:      Op = CXXCastExpr::StaticCast;      break;
+  }
+  
+  return new CXXCastExpr(Op, QualType::getFromOpaquePtr(Ty), (Expr*)E, OpLoc);
+}
+
+/// ParseCXXBoolLiteral - Parse {true,false} literals.
+Action::ExprResult
+Sema::ParseCXXBoolLiteral(SourceLocation OpLoc, tok::TokenKind Kind) {
+  assert((Kind != tok::kw_true || Kind != tok::kw_false) &&
+         "Unknown C++ Boolean value!");
+  return new CXXBoolLiteralExpr(Kind == tok::kw_true, OpLoc);
+}
diff --git a/Sema/SemaStmt.cpp b/Sema/SemaStmt.cpp
new file mode 100644
index 0000000..5a5ab45
--- /dev/null
+++ b/Sema/SemaStmt.cpp
@@ -0,0 +1,294 @@
+//===--- SemaStmt.cpp - Semantic Analysis for Statements ------------------===//
+//
+//                     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 statements.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Sema.h"
+#include "clang/AST/Stmt.h"
+#include "clang/AST/Expr.h"
+#include "clang/Parse/Scope.h"
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/LangOptions.h"
+#include "clang/Lex/IdentifierTable.h"
+using namespace clang;
+
+Sema::StmtResult Sema::ParseExprStmt(ExprTy *expr) {
+  Expr *E = static_cast<Expr*>(expr);
+  
+  // Exprs are statements, so there is no need to do a conversion here. However,
+  // diagnose some potentially bad code.
+  if (!E->hasLocalSideEffect())
+    Diag(E->getExprLoc(), diag::warn_unused_expr, E->getSourceRange());
+  
+  return E;
+}
+
+
+Sema::StmtResult Sema::ParseNullStmt(SourceLocation SemiLoc) {
+  return new NullStmt(SemiLoc);
+}
+
+Sema::StmtResult Sema::ParseDeclStmt(DeclTy *decl) {
+  if (decl)
+    return new DeclStmt(static_cast<Decl *>(decl));
+  else 
+    return true; // error
+}
+
+Action::StmtResult 
+Sema::ParseCompoundStmt(SourceLocation L, SourceLocation R,
+                        StmtTy **Elts, unsigned NumElts) {
+  return new CompoundStmt((Stmt**)Elts, NumElts);
+}
+
+Action::StmtResult
+Sema::ParseCaseStmt(SourceLocation CaseLoc, ExprTy *lhsval,
+                    SourceLocation DotDotDotLoc, ExprTy *RHSVal,
+                    SourceLocation ColonLoc, StmtTy *SubStmt) {
+  Expr *LHSVal = ((Expr *)lhsval);
+  assert((LHSVal != 0) && "missing expression in case statement");
+    
+  SourceLocation ExpLoc;
+  // C99 6.8.4.2p3: The expression shall be an integer constant.
+  if (!LHSVal->isIntegerConstantExpr(&ExpLoc))
+    return Diag(ExpLoc, diag::err_case_label_not_integer_constant_expr,
+                LHSVal->getSourceRange());
+
+  // FIXME: SEMA for RHS of case range.
+
+  return new CaseStmt(LHSVal, (Expr*)RHSVal, (Stmt*)SubStmt);
+}
+
+Action::StmtResult
+Sema::ParseDefaultStmt(SourceLocation DefaultLoc,
+                       SourceLocation ColonLoc, StmtTy *SubStmt) {
+  return new DefaultStmt((Stmt*)SubStmt);
+}
+
+Action::StmtResult
+Sema::ParseLabelStmt(SourceLocation IdentLoc, IdentifierInfo *II,
+                     SourceLocation ColonLoc, StmtTy *SubStmt) {
+  // Look up the record for this label identifier.
+  LabelStmt *&LabelDecl = LabelMap[II];
+  
+  // If not forward referenced or defined already, just create a new LabelStmt.
+  if (LabelDecl == 0)
+    return LabelDecl = new LabelStmt(IdentLoc, II, (Stmt*)SubStmt);
+  
+  assert(LabelDecl->getID() == II && "Label mismatch!");
+  
+  // Otherwise, this label was either forward reference or multiply defined.  If
+  // multiply defined, reject it now.
+  if (LabelDecl->getSubStmt()) {
+    Diag(IdentLoc, diag::err_redefinition_of_label, LabelDecl->getName());
+    Diag(LabelDecl->getIdentLoc(), diag::err_previous_definition);
+    return (Stmt*)SubStmt;
+  }
+  
+  // Otherwise, this label was forward declared, and we just found its real
+  // definition.  Fill in the forward definition and return it.
+  LabelDecl->setIdentLoc(IdentLoc);
+  LabelDecl->setSubStmt((Stmt*)SubStmt);
+  return LabelDecl;
+}
+
+Action::StmtResult 
+Sema::ParseIfStmt(SourceLocation IfLoc, ExprTy *CondVal,
+                  StmtTy *ThenVal, SourceLocation ElseLoc,
+                  StmtTy *ElseVal) {
+  Expr *condExpr = (Expr *)CondVal;
+  assert(condExpr && "ParseIfStmt(): missing expression");
+  
+  QualType condType = DefaultFunctionArrayConversion(condExpr->getType());
+  assert(!condType.isNull() && "ParseIfStmt(): missing expression type");
+  
+  if (!condType->isScalarType()) // C99 6.8.4.1p1
+    return Diag(IfLoc, diag::err_typecheck_statement_requires_scalar,
+             condType.getAsString(), condExpr->getSourceRange());
+
+  return new IfStmt(condExpr, (Stmt*)ThenVal, (Stmt*)ElseVal);
+}
+
+Action::StmtResult
+Sema::ParseSwitchStmt(SourceLocation SwitchLoc, ExprTy *Cond, StmtTy *Body) {
+  return new SwitchStmt((Expr*)Cond, (Stmt*)Body);
+}
+
+Action::StmtResult
+Sema::ParseWhileStmt(SourceLocation WhileLoc, ExprTy *Cond, StmtTy *Body) {
+  Expr *condExpr = (Expr *)Cond;
+  assert(condExpr && "ParseWhileStmt(): missing expression");
+  
+  QualType condType = DefaultFunctionArrayConversion(condExpr->getType());
+  assert(!condType.isNull() && "ParseWhileStmt(): missing expression type");
+  
+  if (!condType->isScalarType()) // C99 6.8.5p2
+    return Diag(WhileLoc, diag::err_typecheck_statement_requires_scalar,
+             condType.getAsString(), condExpr->getSourceRange());
+
+  return new WhileStmt(condExpr, (Stmt*)Body);
+}
+
+Action::StmtResult
+Sema::ParseDoStmt(SourceLocation DoLoc, StmtTy *Body,
+                  SourceLocation WhileLoc, ExprTy *Cond) {
+  Expr *condExpr = (Expr *)Cond;
+  assert(condExpr && "ParseDoStmt(): missing expression");
+  
+  QualType condType = DefaultFunctionArrayConversion(condExpr->getType());
+  assert(!condType.isNull() && "ParseDoStmt(): missing expression type");
+  
+  if (!condType->isScalarType()) // C99 6.8.5p2
+    return Diag(DoLoc, diag::err_typecheck_statement_requires_scalar,
+             condType.getAsString(), condExpr->getSourceRange());
+
+  return new DoStmt((Stmt*)Body, condExpr);
+}
+
+Action::StmtResult 
+Sema::ParseForStmt(SourceLocation ForLoc, SourceLocation LParenLoc, 
+                   StmtTy *First, ExprTy *Second, ExprTy *Third,
+                   SourceLocation RParenLoc, StmtTy *Body) {
+  if (First) {
+    // C99 6.8.5p3: FIXME. Need to hack Parser::ParseForStatement() and
+    // declaration support to create a DeclStmt node. Once this is done, 
+    // we can test for DeclStmt vs. Expr (already a sub-class of Stmt).
+  }
+  if (Second) {
+    Expr *testExpr = (Expr *)Second;
+    QualType testType = DefaultFunctionArrayConversion(testExpr->getType());
+    assert(!testType.isNull() && "ParseForStmt(): missing test expression type");
+    
+    if (!testType->isScalarType()) // C99 6.8.5p2
+      return Diag(ForLoc, diag::err_typecheck_statement_requires_scalar,
+               testType.getAsString(), testExpr->getSourceRange());
+  }
+  return new ForStmt((Stmt*)First, (Expr*)Second, (Expr*)Third, (Stmt*)Body);
+}
+
+
+Action::StmtResult 
+Sema::ParseGotoStmt(SourceLocation GotoLoc, SourceLocation LabelLoc,
+                    IdentifierInfo *LabelII) {
+  // Look up the record for this label identifier.
+  LabelStmt *&LabelDecl = LabelMap[LabelII];
+
+  // If we haven't seen this label yet, create a forward reference.
+  if (LabelDecl == 0)
+    LabelDecl = new LabelStmt(LabelLoc, LabelII, 0);
+  
+  return new GotoStmt(LabelDecl);
+}
+
+Action::StmtResult 
+Sema::ParseIndirectGotoStmt(SourceLocation GotoLoc,SourceLocation StarLoc,
+                            ExprTy *DestExp) {
+  // FIXME: Verify that the operand is convertible to void*.
+  
+  return new IndirectGotoStmt((Expr*)DestExp);
+}
+
+Action::StmtResult 
+Sema::ParseContinueStmt(SourceLocation ContinueLoc, Scope *CurScope) {
+  Scope *S = CurScope->getContinueParent();
+  if (!S) {
+    // C99 6.8.6.2p1: A break shall appear only in or as a loop body.
+    Diag(ContinueLoc, diag::err_continue_not_in_loop);
+    return true;
+  }
+  
+  // FIXME: Remember that this continue goes with this loop.
+  return new ContinueStmt();
+}
+
+Action::StmtResult 
+Sema::ParseBreakStmt(SourceLocation BreakLoc, Scope *CurScope) {
+  Scope *S = CurScope->getBreakParent();
+  if (!S) {
+    // C99 6.8.6.3p1: A break shall appear only in or as a switch/loop body.
+    Diag(BreakLoc, diag::err_break_not_in_loop_or_switch);
+    return true;
+  }
+  
+  // FIXME: Remember that this break goes with this loop/switch.
+  return new BreakStmt();
+}
+
+
+Action::StmtResult
+Sema::ParseReturnStmt(SourceLocation ReturnLoc, ExprTy *RetValExp) {
+  QualType lhsType = CurFunctionDecl->getResultType();
+
+  if (lhsType->isVoidType()) {
+    if (RetValExp) // C99 6.8.6.4p1 (ext_ since GCC warns)
+      Diag(ReturnLoc, diag::ext_return_has_expr, 
+           CurFunctionDecl->getIdentifier()->getName(),
+           ((Expr *)RetValExp)->getSourceRange());
+    return new ReturnStmt((Expr*)RetValExp);
+  } else {
+    if (!RetValExp) {
+      const char *funcName = CurFunctionDecl->getIdentifier()->getName();
+      if (getLangOptions().C99)  // C99 6.8.6.4p1 (ext_ since GCC warns)
+        Diag(ReturnLoc, diag::ext_return_missing_expr, funcName);
+      else  // C90 6.6.6.4p4
+        Diag(ReturnLoc, diag::warn_return_missing_expr, funcName);
+      return new ReturnStmt((Expr*)0);
+    }
+  }
+  // we have a non-void function with an expression, continue checking
+  QualType rhsType = ((Expr *)RetValExp)->getType();
+
+  if (lhsType == rhsType) // common case, fast path...
+    return new ReturnStmt((Expr*)RetValExp);
+
+  // C99 6.8.6.4p3(136): The return statement is not an assignment. The 
+  // overlap restriction of subclause 6.5.16.1 does not apply to the case of 
+  // function return.  
+  AssignmentCheckResult result = CheckAssignmentConstraints(lhsType, rhsType);
+  bool hadError = false;
+  
+  // decode the result (notice that extensions still return a type).
+  switch (result) {
+  case Compatible:
+    break;
+  case Incompatible:
+    Diag(ReturnLoc, diag::err_typecheck_return_incompatible, 
+         lhsType.getAsString(), rhsType.getAsString(),
+         ((Expr *)RetValExp)->getSourceRange());
+    hadError = true;
+    break;
+  case PointerFromInt:
+    // check for null pointer constant (C99 6.3.2.3p3)
+    if (!((Expr *)RetValExp)->isNullPointerConstant()) {
+      Diag(ReturnLoc, diag::ext_typecheck_return_pointer_int,
+           lhsType.getAsString(), rhsType.getAsString(),
+           ((Expr *)RetValExp)->getSourceRange());
+    }
+    break;
+  case IntFromPointer:
+    Diag(ReturnLoc, diag::ext_typecheck_return_pointer_int,
+         lhsType.getAsString(), rhsType.getAsString(),
+         ((Expr *)RetValExp)->getSourceRange());
+    break;
+  case IncompatiblePointer:
+    Diag(ReturnLoc, diag::ext_typecheck_return_incompatible_pointer,
+         lhsType.getAsString(), rhsType.getAsString(),
+         ((Expr *)RetValExp)->getSourceRange());
+    break;
+  case CompatiblePointerDiscardsQualifiers:
+    Diag(ReturnLoc, diag::ext_typecheck_return_discards_qualifiers,
+         lhsType.getAsString(), rhsType.getAsString(),
+         ((Expr *)RetValExp)->getSourceRange());
+    break;
+  }
+  return new ReturnStmt((Expr*)RetValExp);
+}
+
diff --git a/Sema/SemaType.cpp b/Sema/SemaType.cpp
new file mode 100644
index 0000000..cdb767f
--- /dev/null
+++ b/Sema/SemaType.cpp
@@ -0,0 +1,262 @@
+//===--- SemaType.cpp - Semantic Analysis for Types -----------------------===//
+//
+//                     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 type-related semantic analysis.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Sema.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/Decl.h"
+#include "clang/Parse/DeclSpec.h"
+#include "clang/Lex/IdentifierTable.h"
+using namespace clang;
+
+/// ConvertDeclSpecToType - Convert the specified declspec to the appropriate
+/// type object.  This returns null on error.
+static QualType ConvertDeclSpecToType(const DeclSpec &DS, ASTContext &Ctx) {
+  // FIXME: Should move the logic from DeclSpec::Finish to here for validity
+  // checking.
+  
+  switch (DS.getTypeSpecType()) {
+  default: return QualType(); // FIXME: Handle unimp cases!
+  case DeclSpec::TST_void: return Ctx.VoidTy;
+  case DeclSpec::TST_char:
+    if (DS.getTypeSpecSign() == DeclSpec::TSS_unspecified)
+      return Ctx.CharTy;
+    else if (DS.getTypeSpecSign() == DeclSpec::TSS_signed)
+      return Ctx.SignedCharTy;
+    else {
+      assert(DS.getTypeSpecSign() == DeclSpec::TSS_unsigned &&
+             "Unknown TSS value");
+      return Ctx.UnsignedCharTy;
+    }
+  case DeclSpec::TST_int:
+    if (DS.getTypeSpecSign() != DeclSpec::TSS_unsigned) {
+      switch (DS.getTypeSpecWidth()) {
+      case DeclSpec::TSW_unspecified: return Ctx.IntTy;
+      case DeclSpec::TSW_short:       return Ctx.ShortTy;
+      case DeclSpec::TSW_long:        return Ctx.LongTy;
+      case DeclSpec::TSW_longlong:    return Ctx.LongLongTy;
+      }
+    } else {
+      switch (DS.getTypeSpecWidth()) {
+      case DeclSpec::TSW_unspecified: return Ctx.UnsignedIntTy;
+      case DeclSpec::TSW_short:       return Ctx.UnsignedShortTy;
+      case DeclSpec::TSW_long:        return Ctx.UnsignedLongTy;
+      case DeclSpec::TSW_longlong:    return Ctx.UnsignedLongLongTy;
+      }
+    }
+  case DeclSpec::TST_float:
+    if (DS.getTypeSpecComplex() == DeclSpec::TSC_unspecified)
+      return Ctx.FloatTy;
+    assert(DS.getTypeSpecComplex() == DeclSpec::TSC_complex &&
+           "FIXME: imaginary types not supported yet!");
+    return Ctx.FloatComplexTy;
+    
+  case DeclSpec::TST_double: {
+    bool isLong = DS.getTypeSpecWidth() == DeclSpec::TSW_long;
+    if (DS.getTypeSpecComplex() == DeclSpec::TSC_unspecified)
+      return isLong ? Ctx.LongDoubleTy : Ctx.DoubleTy;
+    assert(DS.getTypeSpecComplex() == DeclSpec::TSC_complex &&
+           "FIXME: imaginary types not supported yet!");
+    return isLong ? Ctx.LongDoubleComplexTy : Ctx.DoubleComplexTy;
+  }
+  case DeclSpec::TST_bool:         // _Bool or bool
+    return Ctx.BoolTy;
+  case DeclSpec::TST_decimal32:    // _Decimal32
+  case DeclSpec::TST_decimal64:    // _Decimal64
+  case DeclSpec::TST_decimal128:   // _Decimal128
+    assert(0 && "FIXME: GNU decimal extensions not supported yet!"); 
+  case DeclSpec::TST_enum:
+  case DeclSpec::TST_union:
+  case DeclSpec::TST_struct: {
+    Decl *D = static_cast<Decl *>(DS.getTypeRep());
+    assert(D && "Didn't get a decl for a enum/union/struct?");
+    assert(DS.getTypeSpecWidth() == 0 && DS.getTypeSpecComplex() == 0 &&
+           DS.getTypeSpecSign() == 0 &&
+           "Can't handle qualifiers on typedef names yet!");
+    // TypeQuals handled by caller.
+    return Ctx.getTagDeclType(cast<TagDecl>(D));
+  }    
+  case DeclSpec::TST_typedef: {
+    Decl *D = static_cast<Decl *>(DS.getTypeRep());
+    assert(D && "Didn't get a decl for a typedef?");
+    assert(DS.getTypeSpecWidth() == 0 && DS.getTypeSpecComplex() == 0 &&
+           DS.getTypeSpecSign() == 0 &&
+           "Can't handle qualifiers on typedef names yet!");
+    // TypeQuals handled by caller.
+    return Ctx.getTypedefType(cast<TypedefDecl>(D));
+  }
+  }
+}
+
+/// GetTypeForDeclarator - Convert the type for the specified declarator to Type
+/// instances.
+QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S) {
+  QualType T = ConvertDeclSpecToType(D.getDeclSpec(), Context);
+
+  // If there was an error parsing declspecs, return a null type pointer.
+  if (T.isNull()) return T;
+  
+  // Apply const/volatile/restrict qualifiers to T.
+  T = T.getQualifiedType(D.getDeclSpec().getTypeQualifiers());
+  
+  // Walk the DeclTypeInfo, building the recursive type as we go.  DeclTypeInfos
+  // are ordered from the identifier out, which is opposite of what we want :).
+  for (unsigned i = 0, e = D.getNumTypeObjects(); i != e; ++i) {
+    const DeclaratorChunk &DeclType = D.getTypeObject(e-i-1);
+    switch (DeclType.Kind) {
+    default: assert(0 && "Unknown decltype!");
+    case DeclaratorChunk::Pointer:
+      if (isa<ReferenceType>(T.getCanonicalType().getTypePtr())) {
+        // C++ 8.3.2p4: There shall be no ... pointers to references ...
+        Diag(D.getIdentifierLoc(), diag::err_illegal_decl_pointer_to_reference,
+             D.getIdentifier()->getName());
+        return QualType();
+      }
+
+      // Apply the pointer typequals to the pointer object.
+      T = Context.getPointerType(T).getQualifiedType(DeclType.Ptr.TypeQuals);
+      break;
+    case DeclaratorChunk::Reference:
+      if (isa<ReferenceType>(T.getCanonicalType().getTypePtr())) {
+        // C++ 8.3.2p4: There shall be no references to references ...
+        Diag(D.getIdentifierLoc(),
+             diag::err_illegal_decl_reference_to_reference,
+             D.getIdentifier()->getName());
+        return QualType();
+      }
+
+      T = Context.getReferenceType(T);
+      break;
+    case DeclaratorChunk::Array: {
+      const DeclaratorChunk::ArrayTypeInfo &ATI = DeclType.Arr;
+      ArrayType::ArraySizeModifier ASM;
+      if (ATI.isStar)
+        ASM = ArrayType::Star;
+      else if (ATI.hasStatic)
+        ASM = ArrayType::Static;
+      else
+        ASM = ArrayType::Normal;
+      
+      Type *CanonicalT = T.getCanonicalType().getTypePtr();
+      
+      // C99 6.7.5.2p1: If the element type is an incomplete or function type, 
+      // reject it (e.g. void ary[7], struct foo ary[7], void ary[7]())
+      if (T->isIncompleteType()) { 
+        Diag(D.getIdentifierLoc(), diag::err_illegal_decl_array_incomplete_type,
+             T.getAsString());
+        return QualType();
+      } else if (isa<FunctionType>(CanonicalT)) {
+        Diag(D.getIdentifierLoc(), diag::err_illegal_decl_array_of_functions,
+             D.getIdentifier()->getName());
+        return QualType();
+      } else if (isa<ReferenceType>(CanonicalT)) {
+        // C++ 8.3.2p4: There shall be no ... arrays of references ...
+        Diag(D.getIdentifierLoc(), diag::err_illegal_decl_array_of_references,
+             D.getIdentifier()->getName());
+        return QualType();
+      } else if (RecordType *EltTy = dyn_cast<RecordType>(CanonicalT)) {
+        // If the element type is a struct or union that contains a variadic
+        // array, reject it: C99 6.7.2.1p2.
+        if (EltTy->getDecl()->hasFlexibleArrayMember()) {
+          Diag(DeclType.Loc, diag::err_flexible_array_in_array,
+               T.getAsString());
+          return QualType();
+        }
+      }
+      T = Context.getArrayType(T, ASM, ATI.TypeQuals, 
+                               static_cast<Expr *>(ATI.NumElts));
+      break;
+    }
+    case DeclaratorChunk::Function:
+      // If the function declarator has a prototype (i.e. it is not () and
+      // does not have a K&R-style identifier list), then the arguments are part
+      // of the type, otherwise the argument list is ().
+      const DeclaratorChunk::FunctionTypeInfo &FTI = DeclType.Fun;
+      if (!FTI.hasPrototype) {
+        // Simple void foo(), where the incoming T is the result type.
+        T = Context.getFunctionTypeNoProto(T);
+
+        // C99 6.7.5.3p3: Reject int(x,y,z) when it's not a function definition.
+        if (FTI.NumArgs != 0)
+          Diag(FTI.ArgInfo[0].IdentLoc, diag::err_ident_list_in_fn_declaration);
+        
+      } else {
+        // Otherwise, we have a function with an argument list that is
+        // potentially variadic.
+        llvm::SmallVector<QualType, 16> ArgTys;
+        
+        for (unsigned i = 0, e = FTI.NumArgs; i != e; ++i) {
+          QualType ArgTy = QualType::getFromOpaquePtr(FTI.ArgInfo[i].TypeInfo);
+          if (ArgTy.isNull())
+            return QualType();  // Error occurred parsing argument type.
+          
+          // Look for 'void'.  void is allowed only as a single argument to a
+          // function with no other parameters (C99 6.7.5.3p10).  We record
+          // int(void) as a FunctionTypeProto with an empty argument list.
+          if (ArgTy->isVoidType()) {
+            // If this is something like 'float(int, void)', reject it.  'void'
+            // is an incomplete type (C99 6.2.5p19) and function decls cannot
+            // have arguments of incomplete type.
+            if (FTI.NumArgs != 1 || FTI.isVariadic) {
+              Diag(DeclType.Loc, diag::err_void_only_param);
+              return QualType();
+            }
+            // Reject, but continue to parse 'int(void abc)'.
+            if (FTI.ArgInfo[i].Ident)
+              Diag(FTI.ArgInfo[i].IdentLoc,
+                   diag::err_void_param_with_identifier);
+            
+            // Reject, but continue to parse 'float(const void)'.
+            if (ArgTy.getQualifiers())
+              Diag(DeclType.Loc, diag::err_void_param_qualified);
+            
+            // Do not add 'void' to the ArgTys list.
+            break;
+          }
+          
+          ArgTys.push_back(ArgTy);
+        }
+        T = Context.getFunctionType(T, &ArgTys[0], ArgTys.size(),
+                                    FTI.isVariadic);
+      }
+      break;
+    }
+  }
+  
+  return T;
+}
+
+Sema::TypeResult Sema::ParseTypeName(Scope *S, Declarator &D) {
+  // C99 6.7.6: Type names have no identifier.  This is already validated by
+  // the parser.
+  assert(D.getIdentifier() == 0 && "Type name should have no identifier!");
+  
+  QualType T = GetTypeForDeclarator(D, S);
+  
+  // If the type of the declarator was invalid, this is an invalid typename.
+  if (T.isNull())
+    return true;
+  
+  return T.getAsOpaquePtr();
+}
+
+Sema::TypeResult Sema::ParseParamDeclaratorType(Scope *S, Declarator &D) {
+  // Note: parameters have identifiers, but we don't care about them here, we
+  // just want the type converted.
+  QualType T = GetTypeForDeclarator(D, S);
+  
+  // If the type of the declarator was invalid, this is an invalid typename.
+  if (T.isNull())
+    return true;
+  
+  return T.getAsOpaquePtr();
+}