Check in LLVM r95781.
diff --git a/lib/Sema/CMakeLists.txt b/lib/Sema/CMakeLists.txt
new file mode 100644
index 0000000..5be6712
--- /dev/null
+++ b/lib/Sema/CMakeLists.txt
@@ -0,0 +1,35 @@
+set(LLVM_NO_RTTI 1)
+
+add_clang_library(clangSema
+  CodeCompleteConsumer.cpp
+  IdentifierResolver.cpp
+  JumpDiagnostics.cpp
+  ParseAST.cpp
+  Sema.cpp
+  SemaAccess.cpp
+  SemaAttr.cpp
+  SemaCXXCast.cpp
+  SemaCXXScopeSpec.cpp
+  SemaChecking.cpp
+  SemaCodeComplete.cpp
+  SemaDecl.cpp
+  SemaDeclAttr.cpp
+  SemaDeclCXX.cpp
+  SemaDeclObjC.cpp
+  SemaExceptionSpec.cpp
+  SemaExpr.cpp
+  SemaExprCXX.cpp
+  SemaExprObjC.cpp
+  SemaInit.cpp
+  SemaLookup.cpp
+  SemaOverload.cpp
+  SemaStmt.cpp
+  SemaTemplate.cpp
+  SemaTemplateDeduction.cpp
+  SemaTemplateInstantiate.cpp
+  SemaTemplateInstantiateDecl.cpp
+  SemaType.cpp
+  TargetAttributesSema.cpp
+  )
+
+add_dependencies(clangSema ClangDiagnosticSema)
diff --git a/lib/Sema/CXXFieldCollector.h b/lib/Sema/CXXFieldCollector.h
new file mode 100644
index 0000000..69d1351
--- /dev/null
+++ b/lib/Sema/CXXFieldCollector.h
@@ -0,0 +1,76 @@
+//===- CXXFieldCollector.h - Utility class for C++ class semantic analysis ===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+//  This file provides CXXFieldCollector that is used during parsing & semantic
+//  analysis of C++ classes.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_SEMA_CXXFIELDCOLLECTOR_H
+#define LLVM_CLANG_SEMA_CXXFIELDCOLLECTOR_H
+
+#include "llvm/ADT/SmallVector.h"
+
+namespace clang {
+  class FieldDecl;
+
+/// CXXFieldCollector - Used to keep track of CXXFieldDecls during parsing of
+/// C++ classes.
+class CXXFieldCollector {
+  /// Fields - Contains all FieldDecls collected during parsing of a C++
+  /// class. When a nested class is entered, its fields are appended to the
+  /// fields of its parent class, when it is exited its fields are removed.
+  llvm::SmallVector<FieldDecl*, 32> Fields;
+
+  /// FieldCount - Each entry represents the number of fields collected during
+  /// the parsing of a C++ class. When a nested class is entered, a new field
+  /// count is pushed, when it is exited, the field count is popped.
+  llvm::SmallVector<size_t, 4> FieldCount;
+
+  // Example:
+  //
+  // class C {
+  //   int x,y;
+  //   class NC {
+  //     int q;
+  //     // At this point, Fields contains [x,y,q] decls and FieldCount contains
+  //     // [2,1].
+  //   };
+  //   int z;
+  //   // At this point, Fields contains [x,y,z] decls and FieldCount contains
+  //   // [3].
+  // };
+
+public:
+  /// StartClass - Called by Sema::ActOnStartCXXClassDef.
+  void StartClass() { FieldCount.push_back(0); }
+
+  /// Add - Called by Sema::ActOnCXXMemberDeclarator.
+  void Add(FieldDecl *D) {
+    Fields.push_back(D);
+    ++FieldCount.back();
+  }
+
+  /// getCurNumField - The number of fields added to the currently parsed class.
+  size_t getCurNumFields() const { return FieldCount.back(); }
+
+  /// getCurFields - Pointer to array of fields added to the currently parsed
+  /// class.
+  FieldDecl **getCurFields() { return &*(Fields.end() - getCurNumFields()); }
+
+  /// FinishClass - Called by Sema::ActOnFinishCXXClassDef.
+  void FinishClass() {
+    Fields.resize(Fields.size() - getCurNumFields());
+    FieldCount.pop_back();
+  }
+};
+
+} // end namespace clang
+
+#endif
diff --git a/lib/Sema/CodeCompleteConsumer.cpp b/lib/Sema/CodeCompleteConsumer.cpp
new file mode 100644
index 0000000..8c4caaf
--- /dev/null
+++ b/lib/Sema/CodeCompleteConsumer.cpp
@@ -0,0 +1,625 @@
+//===--- CodeCompleteConsumer.cpp - Code Completion Interface ---*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+//  This file implements the CodeCompleteConsumer class.
+//
+//===----------------------------------------------------------------------===//
+#include "clang/Sema/CodeCompleteConsumer.h"
+#include "clang/AST/DeclCXX.h"
+#include "clang/Parse/Scope.h"
+#include "clang/Lex/Preprocessor.h"
+#include "clang-c/Index.h"
+#include "Sema.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/StringSwitch.h"
+#include "llvm/Support/raw_ostream.h"
+#include <algorithm>
+#include <cstring>
+#include <functional>
+
+using namespace clang;
+using llvm::StringRef;
+
+//===----------------------------------------------------------------------===//
+// Code completion string implementation
+//===----------------------------------------------------------------------===//
+CodeCompletionString::Chunk::Chunk(ChunkKind Kind, llvm::StringRef Text) 
+  : Kind(Kind), Text("")
+{
+  switch (Kind) {
+  case CK_TypedText:
+  case CK_Text:
+  case CK_Placeholder:
+  case CK_Informative:
+  case CK_ResultType:
+  case CK_CurrentParameter: {
+    char *New = new char [Text.size() + 1];
+    std::memcpy(New, Text.data(), Text.size());
+    New[Text.size()] = '\0';
+    this->Text = New;
+    break;
+  }
+
+  case CK_Optional:
+    llvm_unreachable("Optional strings cannot be created from text");
+    break;
+      
+  case CK_LeftParen:
+    this->Text = "(";
+    break;
+
+  case CK_RightParen:
+    this->Text = ")";
+    break;
+
+  case CK_LeftBracket:
+    this->Text = "[";
+    break;
+    
+  case CK_RightBracket:
+    this->Text = "]";
+    break;
+    
+  case CK_LeftBrace:
+    this->Text = "{";
+    break;
+
+  case CK_RightBrace:
+    this->Text = "}";
+    break;
+
+  case CK_LeftAngle:
+    this->Text = "<";
+    break;
+    
+  case CK_RightAngle:
+    this->Text = ">";
+    break;
+      
+  case CK_Comma:
+    this->Text = ", ";
+    break;
+
+  case CK_Colon:
+    this->Text = ": ";
+    break;
+
+  case CK_SemiColon:
+    this->Text = ";";
+    break;
+
+  case CK_Equal:
+    this->Text = " = ";
+    break;
+
+  case CK_HorizontalSpace:
+    this->Text = " ";
+    break;
+
+  case CK_VerticalSpace:
+    this->Text = "\n";
+    break;
+  }
+}
+
+CodeCompletionString::Chunk
+CodeCompletionString::Chunk::CreateText(StringRef Text) {
+  return Chunk(CK_Text, Text);
+}
+
+CodeCompletionString::Chunk 
+CodeCompletionString::Chunk::CreateOptional(
+                                 std::auto_ptr<CodeCompletionString> Optional) {
+  Chunk Result;
+  Result.Kind = CK_Optional;
+  Result.Optional = Optional.release();
+  return Result;
+}
+
+CodeCompletionString::Chunk 
+CodeCompletionString::Chunk::CreatePlaceholder(StringRef Placeholder) {
+  return Chunk(CK_Placeholder, Placeholder);
+}
+
+CodeCompletionString::Chunk 
+CodeCompletionString::Chunk::CreateInformative(StringRef Informative) {
+  return Chunk(CK_Informative, Informative);
+}
+
+CodeCompletionString::Chunk 
+CodeCompletionString::Chunk::CreateResultType(StringRef ResultType) {
+  return Chunk(CK_ResultType, ResultType);
+}
+
+CodeCompletionString::Chunk 
+CodeCompletionString::Chunk::CreateCurrentParameter(
+                                                StringRef CurrentParameter) {
+  return Chunk(CK_CurrentParameter, CurrentParameter);
+}
+
+CodeCompletionString::Chunk CodeCompletionString::Chunk::Clone() const {
+  switch (Kind) {
+  case CK_TypedText:
+  case CK_Text:
+  case CK_Placeholder:
+  case CK_Informative:
+  case CK_ResultType:
+  case CK_CurrentParameter:
+  case CK_LeftParen:
+  case CK_RightParen:
+  case CK_LeftBracket:
+  case CK_RightBracket:
+  case CK_LeftBrace:
+  case CK_RightBrace:
+  case CK_LeftAngle:
+  case CK_RightAngle:
+  case CK_Comma:
+  case CK_Colon:
+  case CK_SemiColon:
+  case CK_Equal:
+  case CK_HorizontalSpace:
+  case CK_VerticalSpace:
+    return Chunk(Kind, Text);
+      
+  case CK_Optional: {
+    std::auto_ptr<CodeCompletionString> Opt(Optional->Clone());
+    return CreateOptional(Opt);
+  }
+  }
+
+  // Silence GCC warning.
+  return Chunk();
+}
+
+void
+CodeCompletionString::Chunk::Destroy() {
+  switch (Kind) {
+  case CK_Optional: 
+    delete Optional; 
+    break;
+      
+  case CK_TypedText:
+  case CK_Text: 
+  case CK_Placeholder:
+  case CK_Informative:
+  case CK_ResultType:
+  case CK_CurrentParameter:
+    delete [] Text;
+    break;
+
+  case CK_LeftParen:
+  case CK_RightParen:
+  case CK_LeftBracket:
+  case CK_RightBracket:
+  case CK_LeftBrace:
+  case CK_RightBrace:
+  case CK_LeftAngle:
+  case CK_RightAngle:
+  case CK_Comma:
+  case CK_Colon:
+  case CK_SemiColon:
+  case CK_Equal:
+  case CK_HorizontalSpace:
+  case CK_VerticalSpace:
+    break;
+  }
+}
+
+CodeCompletionString::~CodeCompletionString() {
+  std::for_each(Chunks.begin(), Chunks.end(), 
+                std::mem_fun_ref(&Chunk::Destroy));
+}
+
+std::string CodeCompletionString::getAsString() const {
+  std::string Result;
+  llvm::raw_string_ostream OS(Result);
+                          
+  for (iterator C = begin(), CEnd = end(); C != CEnd; ++C) {
+    switch (C->Kind) {
+    case CK_Optional: OS << "{#" << C->Optional->getAsString() << "#}"; break;
+    case CK_Placeholder: OS << "<#" << C->Text << "#>"; break;
+        
+    case CK_Informative: 
+    case CK_ResultType:
+      OS << "[#" << C->Text << "#]"; 
+      break;
+        
+    case CK_CurrentParameter: OS << "<#" << C->Text << "#>"; break;
+    default: OS << C->Text; break;
+    }
+  }
+  OS.flush();
+  return Result;
+}
+
+const char *CodeCompletionString::getTypedText() const {
+  for (iterator C = begin(), CEnd = end(); C != CEnd; ++C)
+    if (C->Kind == CK_TypedText)
+      return C->Text;
+  
+  return 0;
+}
+
+CodeCompletionString *CodeCompletionString::Clone() const {
+  CodeCompletionString *Result = new CodeCompletionString;
+  for (iterator C = begin(), CEnd = end(); C != CEnd; ++C)
+    Result->AddChunk(C->Clone());
+  return Result;
+}
+
+static void WriteUnsigned(llvm::raw_ostream &OS, unsigned Value) {
+  OS.write((const char *)&Value, sizeof(unsigned));
+}
+
+static bool ReadUnsigned(const char *&Memory, const char *MemoryEnd,
+                         unsigned &Value) {
+  if (Memory + sizeof(unsigned) > MemoryEnd)
+    return true;
+
+  memmove(&Value, Memory, sizeof(unsigned));
+  Memory += sizeof(unsigned);
+  return false;
+}
+
+void CodeCompletionString::Serialize(llvm::raw_ostream &OS) const {
+  // Write the number of chunks.
+  WriteUnsigned(OS, size());
+
+  for (iterator C = begin(), CEnd = end(); C != CEnd; ++C) {
+    WriteUnsigned(OS, C->Kind);
+
+    switch (C->Kind) {
+    case CK_TypedText:
+    case CK_Text:
+    case CK_Placeholder:
+    case CK_Informative:
+    case CK_ResultType:
+    case CK_CurrentParameter: {
+      const char *Text = C->Text;
+      unsigned StrLen = strlen(Text);
+      WriteUnsigned(OS, StrLen);
+      OS.write(Text, StrLen);
+      break;
+    }
+
+    case CK_Optional:
+      C->Optional->Serialize(OS);
+      break;
+
+    case CK_LeftParen:
+    case CK_RightParen:
+    case CK_LeftBracket:
+    case CK_RightBracket:
+    case CK_LeftBrace:
+    case CK_RightBrace:
+    case CK_LeftAngle:
+    case CK_RightAngle:
+    case CK_Comma:
+    case CK_Colon:
+    case CK_SemiColon:
+    case CK_Equal:
+    case CK_HorizontalSpace:
+    case CK_VerticalSpace:
+      break;
+    }
+  }
+}
+
+CodeCompletionString *CodeCompletionString::Deserialize(const char *&Str,
+                                                        const char *StrEnd) {
+  if (Str == StrEnd || *Str == 0)
+    return 0;
+
+  CodeCompletionString *Result = new CodeCompletionString;
+  unsigned NumBlocks;
+  if (ReadUnsigned(Str, StrEnd, NumBlocks))
+    return Result;
+
+  for (unsigned I = 0; I != NumBlocks; ++I) {
+    if (Str + 1 >= StrEnd)
+      break;
+
+    // Parse the next kind.
+    unsigned KindValue;
+    if (ReadUnsigned(Str, StrEnd, KindValue))
+      return Result;
+
+    switch (ChunkKind Kind = (ChunkKind)KindValue) {
+    case CK_TypedText:
+    case CK_Text:
+    case CK_Placeholder:
+    case CK_Informative:
+    case CK_ResultType:
+    case CK_CurrentParameter: {
+      unsigned StrLen;
+      if (ReadUnsigned(Str, StrEnd, StrLen) || (Str + StrLen > StrEnd))
+        return Result;
+
+      Result->AddChunk(Chunk(Kind, StringRef(Str, StrLen)));
+      Str += StrLen;
+      break;
+    }
+
+    case CK_Optional: {
+      std::auto_ptr<CodeCompletionString> Optional(Deserialize(Str, StrEnd));
+      Result->AddOptionalChunk(Optional);
+      break;
+    }
+
+    case CK_LeftParen:
+    case CK_RightParen:
+    case CK_LeftBracket:
+    case CK_RightBracket:
+    case CK_LeftBrace:
+    case CK_RightBrace:
+    case CK_LeftAngle:
+    case CK_RightAngle:
+    case CK_Comma:
+    case CK_Colon:
+    case CK_SemiColon:
+    case CK_Equal:
+    case CK_HorizontalSpace:
+    case CK_VerticalSpace:
+      Result->AddChunk(Chunk(Kind));
+      break;      
+    }
+  };
+  
+  return Result;
+}
+
+void CodeCompleteConsumer::Result::Destroy() {
+  if (Kind == RK_Pattern) {
+    delete Pattern;
+    Pattern = 0;
+  }
+}
+
+//===----------------------------------------------------------------------===//
+// Code completion overload candidate implementation
+//===----------------------------------------------------------------------===//
+FunctionDecl *
+CodeCompleteConsumer::OverloadCandidate::getFunction() const {
+  if (getKind() == CK_Function)
+    return Function;
+  else if (getKind() == CK_FunctionTemplate)
+    return FunctionTemplate->getTemplatedDecl();
+  else
+    return 0;
+}
+
+const FunctionType *
+CodeCompleteConsumer::OverloadCandidate::getFunctionType() const {
+  switch (Kind) {
+  case CK_Function:
+    return Function->getType()->getAs<FunctionType>();
+      
+  case CK_FunctionTemplate:
+    return FunctionTemplate->getTemplatedDecl()->getType()
+             ->getAs<FunctionType>();
+      
+  case CK_FunctionType:
+    return Type;
+  }
+  
+  return 0;
+}
+
+//===----------------------------------------------------------------------===//
+// Code completion consumer implementation
+//===----------------------------------------------------------------------===//
+
+CodeCompleteConsumer::~CodeCompleteConsumer() { }
+
+void 
+PrintingCodeCompleteConsumer::ProcessCodeCompleteResults(Sema &SemaRef,
+                                                         Result *Results, 
+                                                         unsigned NumResults) {
+  // Print the results.
+  for (unsigned I = 0; I != NumResults; ++I) {
+    OS << "COMPLETION: ";
+    switch (Results[I].Kind) {
+    case Result::RK_Declaration:
+      OS << Results[I].Declaration->getNameAsString() ;
+      if (Results[I].Hidden)
+        OS << " (Hidden)";
+      if (CodeCompletionString *CCS 
+            = Results[I].CreateCodeCompletionString(SemaRef)) {
+        OS << " : " << CCS->getAsString();
+        delete CCS;
+      }
+        
+      OS << '\n';
+      break;
+      
+    case Result::RK_Keyword:
+      OS << Results[I].Keyword << '\n';
+      break;
+        
+    case Result::RK_Macro: {
+      OS << Results[I].Macro->getName();
+      if (CodeCompletionString *CCS 
+            = Results[I].CreateCodeCompletionString(SemaRef)) {
+        OS << " : " << CCS->getAsString();
+        delete CCS;
+      }
+      OS << '\n';
+      break;
+    }
+        
+    case Result::RK_Pattern: {
+      OS << "Pattern : " 
+         << Results[I].Pattern->getAsString() << '\n';
+      break;
+    }
+    }
+  }
+  
+  // Once we've printed the code-completion results, suppress remaining
+  // diagnostics.
+  // FIXME: Move this somewhere else!
+  SemaRef.PP.getDiagnostics().setSuppressAllDiagnostics();
+}
+
+void 
+PrintingCodeCompleteConsumer::ProcessOverloadCandidates(Sema &SemaRef,
+                                                        unsigned CurrentArg,
+                                              OverloadCandidate *Candidates,
+                                                     unsigned NumCandidates) {
+  for (unsigned I = 0; I != NumCandidates; ++I) {
+    if (CodeCompletionString *CCS
+          = Candidates[I].CreateSignatureString(CurrentArg, SemaRef)) {
+      OS << "OVERLOAD: " << CCS->getAsString() << "\n";
+      delete CCS;
+    }
+  }
+
+  // Once we've printed the code-completion results, suppress remaining
+  // diagnostics.
+  // FIXME: Move this somewhere else!
+  SemaRef.PP.getDiagnostics().setSuppressAllDiagnostics();
+}
+
+void 
+CIndexCodeCompleteConsumer::ProcessCodeCompleteResults(Sema &SemaRef,
+                                                       Result *Results, 
+                                                       unsigned NumResults) {
+  // Print the results.
+  for (unsigned I = 0; I != NumResults; ++I) {
+    CXCursorKind Kind = CXCursor_NotImplemented;
+
+    switch (Results[I].Kind) {
+    case Result::RK_Declaration:
+      switch (Results[I].Declaration->getKind()) {
+      case Decl::Record:
+      case Decl::CXXRecord:
+      case Decl::ClassTemplateSpecialization: {
+        RecordDecl *Record = cast<RecordDecl>(Results[I].Declaration);
+        if (Record->isStruct())
+          Kind = CXCursor_StructDecl;
+        else if (Record->isUnion())
+          Kind = CXCursor_UnionDecl;
+        else
+          Kind = CXCursor_ClassDecl;
+        break;
+      }
+        
+      case Decl::ObjCMethod: {
+        ObjCMethodDecl *Method = cast<ObjCMethodDecl>(Results[I].Declaration);
+        if (Method->isInstanceMethod())
+            Kind = CXCursor_ObjCInstanceMethodDecl;
+        else
+          Kind = CXCursor_ObjCClassMethodDecl;
+        break;
+      }
+        
+      case Decl::Typedef:
+        Kind = CXCursor_TypedefDecl;
+        break;
+        
+      case Decl::Enum:
+        Kind = CXCursor_EnumDecl;
+        break;
+        
+      case Decl::Field:
+        Kind = CXCursor_FieldDecl;
+        break;
+        
+      case Decl::EnumConstant:
+        Kind = CXCursor_EnumConstantDecl;
+        break;
+        
+      case Decl::Function:
+      case Decl::CXXMethod:
+      case Decl::CXXConstructor:
+      case Decl::CXXDestructor:
+      case Decl::CXXConversion:
+        Kind = CXCursor_FunctionDecl;
+        break;
+        
+      case Decl::Var:
+        Kind = CXCursor_VarDecl;
+        break;
+        
+      case Decl::ParmVar:
+        Kind = CXCursor_ParmDecl;
+        break;
+        
+      case Decl::ObjCInterface:
+        Kind = CXCursor_ObjCInterfaceDecl;
+        break;
+        
+      case Decl::ObjCCategory:
+        Kind = CXCursor_ObjCCategoryDecl;
+        break;
+        
+      case Decl::ObjCProtocol:
+        Kind = CXCursor_ObjCProtocolDecl;
+        break;
+        
+      case Decl::ObjCProperty:
+        Kind = CXCursor_ObjCPropertyDecl;
+        break;
+        
+      case Decl::ObjCIvar:
+        Kind = CXCursor_ObjCIvarDecl;
+        break;
+        
+      case Decl::ObjCImplementation:
+        Kind = CXCursor_ObjCImplementationDecl;
+        break;
+        
+      case Decl::ObjCCategoryImpl:
+        Kind = CXCursor_ObjCCategoryImplDecl;
+        break;
+        
+      default:
+        break;
+      }
+      break;
+        
+    case Result::RK_Keyword:
+    case Result::RK_Macro:
+    case Result::RK_Pattern:
+      Kind = CXCursor_NotImplemented;
+      break;
+    }
+
+    WriteUnsigned(OS, Kind);
+    CodeCompletionString *CCS = Results[I].CreateCodeCompletionString(SemaRef);
+    assert(CCS && "No code-completion string?");
+    CCS->Serialize(OS);
+    delete CCS;
+  }
+  
+  // Once we've printed the code-completion results, suppress remaining
+  // diagnostics.
+  // FIXME: Move this somewhere else!
+  SemaRef.PP.getDiagnostics().setSuppressAllDiagnostics();
+}
+
+void 
+CIndexCodeCompleteConsumer::ProcessOverloadCandidates(Sema &SemaRef,
+                                                      unsigned CurrentArg,
+                                                OverloadCandidate *Candidates,
+                                                       unsigned NumCandidates) {
+  for (unsigned I = 0; I != NumCandidates; ++I) {
+    WriteUnsigned(OS, CXCursor_NotImplemented);
+    CodeCompletionString *CCS
+      = Candidates[I].CreateSignatureString(CurrentArg, SemaRef);
+    assert(CCS && "No code-completion string?");
+    CCS->Serialize(OS);
+    delete CCS;
+  }
+  
+  // Once we've printed the code-completion results, suppress remaining
+  // diagnostics.
+  // FIXME: Move this somewhere else!
+  SemaRef.PP.getDiagnostics().setSuppressAllDiagnostics();
+}
diff --git a/lib/Sema/IdentifierResolver.cpp b/lib/Sema/IdentifierResolver.cpp
new file mode 100644
index 0000000..bff4751
--- /dev/null
+++ b/lib/Sema/IdentifierResolver.cpp
@@ -0,0 +1,251 @@
+//===- IdentifierResolver.cpp - Lexical Scope Name lookup -------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the IdentifierResolver class, which is used for lexical
+// scoped lookup, based on declaration names.
+//
+//===----------------------------------------------------------------------===//
+
+#include "IdentifierResolver.h"
+#include "clang/Basic/LangOptions.h"
+#include <list>
+#include <vector>
+
+using namespace clang;
+
+//===----------------------------------------------------------------------===//
+// IdDeclInfoMap class
+//===----------------------------------------------------------------------===//
+
+/// IdDeclInfoMap - Associates IdDeclInfos with declaration names.
+/// Allocates 'pools' (vectors of IdDeclInfos) to avoid allocating each
+/// individual IdDeclInfo to heap.
+class IdentifierResolver::IdDeclInfoMap {
+  static const unsigned int VECTOR_SIZE = 512;
+  // Holds vectors of IdDeclInfos that serve as 'pools'.
+  // New vectors are added when the current one is full.
+  std::list< std::vector<IdDeclInfo> > IDIVecs;
+  unsigned int CurIndex;
+
+public:
+  IdDeclInfoMap() : CurIndex(VECTOR_SIZE) {}
+
+  /// Returns the IdDeclInfo associated to the DeclarationName.
+  /// It creates a new IdDeclInfo if one was not created before for this id.
+  IdDeclInfo &operator[](DeclarationName Name);
+};
+
+
+//===----------------------------------------------------------------------===//
+// IdDeclInfo Implementation
+//===----------------------------------------------------------------------===//
+
+/// RemoveDecl - Remove the decl from the scope chain.
+/// The decl must already be part of the decl chain.
+void IdentifierResolver::IdDeclInfo::RemoveDecl(NamedDecl *D) {
+  for (DeclsTy::iterator I = Decls.end(); I != Decls.begin(); --I) {
+    if (D == *(I-1)) {
+      Decls.erase(I-1);
+      return;
+    }
+  }
+
+  assert(0 && "Didn't find this decl on its identifier's chain!");
+}
+
+bool
+IdentifierResolver::IdDeclInfo::ReplaceDecl(NamedDecl *Old, NamedDecl *New) {
+  for (DeclsTy::iterator I = Decls.end(); I != Decls.begin(); --I) {
+    if (Old == *(I-1)) {
+      *(I - 1) = New;
+      return true;
+    }
+  }
+
+  return false;
+}
+
+
+//===----------------------------------------------------------------------===//
+// IdentifierResolver Implementation
+//===----------------------------------------------------------------------===//
+
+IdentifierResolver::IdentifierResolver(const LangOptions &langOpt)
+    : LangOpt(langOpt), IdDeclInfos(new IdDeclInfoMap) {
+}
+IdentifierResolver::~IdentifierResolver() {
+  delete IdDeclInfos;
+}
+
+/// isDeclInScope - If 'Ctx' is a function/method, isDeclInScope returns true
+/// if 'D' is in Scope 'S', otherwise 'S' is ignored and isDeclInScope returns
+/// true if 'D' belongs to the given declaration context.
+bool IdentifierResolver::isDeclInScope(Decl *D, DeclContext *Ctx,
+                                       ASTContext &Context, Scope *S) const {
+  Ctx = Ctx->getLookupContext();
+
+  if (Ctx->isFunctionOrMethod()) {
+    // Ignore the scopes associated within transparent declaration contexts.
+    while (S->getEntity() &&
+           ((DeclContext *)S->getEntity())->isTransparentContext())
+      S = S->getParent();
+
+    if (S->isDeclScope(Action::DeclPtrTy::make(D)))
+      return true;
+    if (LangOpt.CPlusPlus) {
+      // C++ 3.3.2p3:
+      // The name declared in a catch exception-declaration is local to the
+      // handler and shall not be redeclared in the outermost block of the
+      // handler.
+      // C++ 3.3.2p4:
+      // Names declared in the for-init-statement, and in the condition of if,
+      // while, for, and switch statements are local to the if, while, for, or
+      // switch statement (including the controlled statement), and shall not be
+      // redeclared in a subsequent condition of that statement nor in the
+      // outermost block (or, for the if statement, any of the outermost blocks)
+      // of the controlled statement.
+      //
+      assert(S->getParent() && "No TUScope?");
+      if (S->getParent()->getFlags() & Scope::ControlScope)
+        return S->getParent()->isDeclScope(Action::DeclPtrTy::make(D));
+    }
+    return false;
+  }
+
+  return D->getDeclContext()->getLookupContext()->Equals(Ctx);
+}
+
+/// AddDecl - Link the decl to its shadowed decl chain.
+void IdentifierResolver::AddDecl(NamedDecl *D) {
+  DeclarationName Name = D->getDeclName();
+  void *Ptr = Name.getFETokenInfo<void>();
+
+  if (!Ptr) {
+    Name.setFETokenInfo(D);
+    return;
+  }
+
+  IdDeclInfo *IDI;
+
+  if (isDeclPtr(Ptr)) {
+    Name.setFETokenInfo(NULL);
+    IDI = &(*IdDeclInfos)[Name];
+    NamedDecl *PrevD = static_cast<NamedDecl*>(Ptr);
+    IDI->AddDecl(PrevD);
+  } else
+    IDI = toIdDeclInfo(Ptr);
+
+  IDI->AddDecl(D);
+}
+
+/// RemoveDecl - Unlink the decl from its shadowed decl chain.
+/// The decl must already be part of the decl chain.
+void IdentifierResolver::RemoveDecl(NamedDecl *D) {
+  assert(D && "null param passed");
+  DeclarationName Name = D->getDeclName();
+  void *Ptr = Name.getFETokenInfo<void>();
+
+  assert(Ptr && "Didn't find this decl on its identifier's chain!");
+
+  if (isDeclPtr(Ptr)) {
+    assert(D == Ptr && "Didn't find this decl on its identifier's chain!");
+    Name.setFETokenInfo(NULL);
+    return;
+  }
+
+  return toIdDeclInfo(Ptr)->RemoveDecl(D);
+}
+
+bool IdentifierResolver::ReplaceDecl(NamedDecl *Old, NamedDecl *New) {
+  assert(Old->getDeclName() == New->getDeclName() &&
+         "Cannot replace a decl with another decl of a different name");
+
+  DeclarationName Name = Old->getDeclName();
+  void *Ptr = Name.getFETokenInfo<void>();
+
+  if (!Ptr)
+    return false;
+
+  if (isDeclPtr(Ptr)) {
+    if (Ptr == Old) {
+      Name.setFETokenInfo(New);
+      return true;
+    }
+    return false;
+  }
+
+  return toIdDeclInfo(Ptr)->ReplaceDecl(Old, New);
+}
+
+/// begin - Returns an iterator for decls with name 'Name'.
+IdentifierResolver::iterator
+IdentifierResolver::begin(DeclarationName Name) {
+  void *Ptr = Name.getFETokenInfo<void>();
+  if (!Ptr) return end();
+
+  if (isDeclPtr(Ptr))
+    return iterator(static_cast<NamedDecl*>(Ptr));
+
+  IdDeclInfo *IDI = toIdDeclInfo(Ptr);
+
+  IdDeclInfo::DeclsTy::iterator I = IDI->decls_end();
+  if (I != IDI->decls_begin())
+    return iterator(I-1);
+  // No decls found.
+  return end();
+}
+
+void IdentifierResolver::AddDeclToIdentifierChain(IdentifierInfo *II,
+                                                  NamedDecl *D) {
+  void *Ptr = II->getFETokenInfo<void>();
+
+  if (!Ptr) {
+    II->setFETokenInfo(D);
+    return;
+  }
+
+  IdDeclInfo *IDI;
+
+  if (isDeclPtr(Ptr)) {
+    II->setFETokenInfo(NULL);
+    IDI = &(*IdDeclInfos)[II];
+    NamedDecl *PrevD = static_cast<NamedDecl*>(Ptr);
+    IDI->AddDecl(PrevD);
+  } else
+    IDI = toIdDeclInfo(Ptr);
+
+  IDI->AddDecl(D);
+}
+
+//===----------------------------------------------------------------------===//
+// IdDeclInfoMap Implementation
+//===----------------------------------------------------------------------===//
+
+/// Returns the IdDeclInfo associated to the DeclarationName.
+/// It creates a new IdDeclInfo if one was not created before for this id.
+IdentifierResolver::IdDeclInfo &
+IdentifierResolver::IdDeclInfoMap::operator[](DeclarationName Name) {
+  void *Ptr = Name.getFETokenInfo<void>();
+
+  if (Ptr) return *toIdDeclInfo(Ptr);
+
+  if (CurIndex == VECTOR_SIZE) {
+    // Add a IdDeclInfo vector 'pool'
+    IDIVecs.push_back(std::vector<IdDeclInfo>());
+    // Fill the vector
+    IDIVecs.back().resize(VECTOR_SIZE);
+    CurIndex = 0;
+  }
+  IdDeclInfo *IDI = &IDIVecs.back()[CurIndex];
+  Name.setFETokenInfo(reinterpret_cast<void*>(
+                              reinterpret_cast<uintptr_t>(IDI) | 0x1)
+                                                                     );
+  ++CurIndex;
+  return *IDI;
+}
diff --git a/lib/Sema/IdentifierResolver.h b/lib/Sema/IdentifierResolver.h
new file mode 100644
index 0000000..59bd834
--- /dev/null
+++ b/lib/Sema/IdentifierResolver.h
@@ -0,0 +1,203 @@
+//===- IdentifierResolver.h - Lexical Scope Name lookup ---------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the IdentifierResolver class, which is used for lexical
+// scoped lookup, based on declaration names.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_AST_SEMA_IDENTIFIERRESOLVER_H
+#define LLVM_CLANG_AST_SEMA_IDENTIFIERRESOLVER_H
+
+#include "clang/Basic/IdentifierTable.h"
+#include "clang/Parse/Scope.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclarationName.h"
+#include "clang/AST/DeclCXX.h"
+
+namespace clang {
+
+/// IdentifierResolver - Keeps track of shadowed decls on enclosing
+/// scopes.  It manages the shadowing chains of declaration names and
+/// implements efficent decl lookup based on a declaration name.
+class IdentifierResolver {
+
+  /// IdDeclInfo - Keeps track of information about decls associated
+  /// to a particular declaration name. IdDeclInfos are lazily
+  /// constructed and assigned to a declaration name the first time a
+  /// decl with that declaration name is shadowed in some scope.
+  class IdDeclInfo {
+  public:
+    typedef llvm::SmallVector<NamedDecl*, 2> DeclsTy;
+
+    inline DeclsTy::iterator decls_begin() { return Decls.begin(); }
+    inline DeclsTy::iterator decls_end() { return Decls.end(); }
+
+    void AddDecl(NamedDecl *D) { Decls.push_back(D); }
+
+    /// RemoveDecl - Remove the decl from the scope chain.
+    /// The decl must already be part of the decl chain.
+    void RemoveDecl(NamedDecl *D);
+
+    /// Replaces the Old declaration with the New declaration. If the
+    /// replacement is successful, returns true. If the old
+    /// declaration was not found, returns false.
+    bool ReplaceDecl(NamedDecl *Old, NamedDecl *New);
+
+  private:
+    DeclsTy Decls;
+  };
+
+public:
+
+  /// iterator - Iterate over the decls of a specified declaration name.
+  /// It will walk or not the parent declaration contexts depending on how
+  /// it was instantiated.
+  class iterator {
+  public:
+    typedef NamedDecl *             value_type;
+    typedef NamedDecl *             reference;
+    typedef NamedDecl *             pointer;
+    typedef std::input_iterator_tag iterator_category;
+    typedef std::ptrdiff_t          difference_type;
+
+    /// Ptr - There are 3 forms that 'Ptr' represents:
+    /// 1) A single NamedDecl. (Ptr & 0x1 == 0)
+    /// 2) A IdDeclInfo::DeclsTy::iterator that traverses only the decls of the
+    ///    same declaration context. (Ptr & 0x3 == 0x1)
+    /// 3) A IdDeclInfo::DeclsTy::iterator that traverses the decls of parent
+    ///    declaration contexts too. (Ptr & 0x3 == 0x3)
+    uintptr_t Ptr;
+    typedef IdDeclInfo::DeclsTy::iterator BaseIter;
+
+    /// A single NamedDecl. (Ptr & 0x1 == 0)
+    iterator(NamedDecl *D) {
+      Ptr = reinterpret_cast<uintptr_t>(D);
+      assert((Ptr & 0x1) == 0 && "Invalid Ptr!");
+    }
+    /// A IdDeclInfo::DeclsTy::iterator that walks or not the parent declaration
+    /// contexts depending on 'LookInParentCtx'.
+    iterator(BaseIter I) {
+      Ptr = reinterpret_cast<uintptr_t>(I) | 0x1;
+    }
+
+    bool isIterator() const { return (Ptr & 0x1); }
+
+    BaseIter getIterator() const {
+      assert(isIterator() && "Ptr not an iterator!");
+      return reinterpret_cast<BaseIter>(Ptr & ~0x3);
+    }
+
+    friend class IdentifierResolver;
+  public:
+    iterator() : Ptr(0) {}
+
+    NamedDecl *operator*() const {
+      if (isIterator())
+        return *getIterator();
+      else
+        return reinterpret_cast<NamedDecl*>(Ptr);
+    }
+
+    bool operator==(const iterator &RHS) const {
+      return Ptr == RHS.Ptr;
+    }
+    bool operator!=(const iterator &RHS) const {
+      return Ptr != RHS.Ptr;
+    }
+
+    // Preincrement.
+    iterator& operator++() {
+      if (!isIterator()) // common case.
+        Ptr = 0;
+      else {
+        NamedDecl *D = **this;
+        void *InfoPtr = D->getDeclName().getFETokenInfo<void>();
+        assert(!isDeclPtr(InfoPtr) && "Decl with wrong id ?");
+        IdDeclInfo *Info = toIdDeclInfo(InfoPtr);
+
+        BaseIter I = getIterator();
+        if (I != Info->decls_begin())
+          *this = iterator(I-1);
+        else // No more decls.
+          *this = iterator();
+      }
+      return *this;
+    }
+
+    uintptr_t getAsOpaqueValue() const { return Ptr; }
+
+    static iterator getFromOpaqueValue(uintptr_t P) {
+      iterator Result;
+      Result.Ptr = P;
+      return Result;
+    }
+  };
+
+  /// begin - Returns an iterator for decls with the name 'Name'.
+  static iterator begin(DeclarationName Name);
+
+  /// end - Returns an iterator that has 'finished'.
+  static iterator end() {
+    return iterator();
+  }
+
+  /// isDeclInScope - If 'Ctx' is a function/method, isDeclInScope returns true
+  /// if 'D' is in Scope 'S', otherwise 'S' is ignored and isDeclInScope returns
+  /// true if 'D' belongs to the given declaration context.
+  bool isDeclInScope(Decl *D, DeclContext *Ctx, ASTContext &Context,
+                     Scope *S = 0) const;
+
+  /// AddDecl - Link the decl to its shadowed decl chain.
+  void AddDecl(NamedDecl *D);
+
+  /// RemoveDecl - Unlink the decl from its shadowed decl chain.
+  /// The decl must already be part of the decl chain.
+  void RemoveDecl(NamedDecl *D);
+
+  /// Replace the decl Old with the new declaration New on its
+  /// identifier chain. Returns true if the old declaration was found
+  /// (and, therefore, replaced).
+  bool ReplaceDecl(NamedDecl *Old, NamedDecl *New);
+
+  /// \brief Link the declaration into the chain of declarations for
+  /// the given identifier.
+  ///
+  /// This is a lower-level routine used by the PCH reader to link a
+  /// declaration into a specific IdentifierInfo before the
+  /// declaration actually has a name.
+  void AddDeclToIdentifierChain(IdentifierInfo *II, NamedDecl *D);
+
+  explicit IdentifierResolver(const LangOptions &LangOpt);
+  ~IdentifierResolver();
+
+private:
+  const LangOptions &LangOpt;
+
+  class IdDeclInfoMap;
+  IdDeclInfoMap *IdDeclInfos;
+
+  /// FETokenInfo contains a Decl pointer if lower bit == 0.
+  static inline bool isDeclPtr(void *Ptr) {
+    return (reinterpret_cast<uintptr_t>(Ptr) & 0x1) == 0;
+  }
+
+  /// FETokenInfo contains a IdDeclInfo pointer if lower bit == 1.
+  static inline IdDeclInfo *toIdDeclInfo(void *Ptr) {
+    assert((reinterpret_cast<uintptr_t>(Ptr) & 0x1) == 1
+          && "Ptr not a IdDeclInfo* !");
+    return reinterpret_cast<IdDeclInfo*>(
+                    reinterpret_cast<uintptr_t>(Ptr) & ~0x1
+                                                            );
+  }
+};
+
+} // end namespace clang
+
+#endif
diff --git a/lib/Sema/JumpDiagnostics.cpp b/lib/Sema/JumpDiagnostics.cpp
new file mode 100644
index 0000000..2b37e9d
--- /dev/null
+++ b/lib/Sema/JumpDiagnostics.cpp
@@ -0,0 +1,329 @@
+//===--- JumpDiagnostics.cpp - Analyze Jump Targets for VLA issues --------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the JumpScopeChecker class, which is used to diagnose
+// jumps that enter a VLA scope in an invalid way.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Sema.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/StmtObjC.h"
+#include "clang/AST/StmtCXX.h"
+using namespace clang;
+
+namespace {
+
+/// JumpScopeChecker - This object is used by Sema to diagnose invalid jumps
+/// into VLA and other protected scopes.  For example, this rejects:
+///    goto L;
+///    int a[n];
+///  L:
+///
+class JumpScopeChecker {
+  Sema &S;
+
+  /// GotoScope - This is a record that we use to keep track of all of the
+  /// scopes that are introduced by VLAs and other things that scope jumps like
+  /// gotos.  This scope tree has nothing to do with the source scope tree,
+  /// because you can have multiple VLA scopes per compound statement, and most
+  /// compound statements don't introduce any scopes.
+  struct GotoScope {
+    /// ParentScope - The index in ScopeMap of the parent scope.  This is 0 for
+    /// the parent scope is the function body.
+    unsigned ParentScope;
+
+    /// Diag - The diagnostic to emit if there is a jump into this scope.
+    unsigned Diag;
+
+    /// Loc - Location to emit the diagnostic.
+    SourceLocation Loc;
+
+    GotoScope(unsigned parentScope, unsigned diag, SourceLocation L)
+    : ParentScope(parentScope), Diag(diag), Loc(L) {}
+  };
+
+  llvm::SmallVector<GotoScope, 48> Scopes;
+  llvm::DenseMap<Stmt*, unsigned> LabelAndGotoScopes;
+  llvm::SmallVector<Stmt*, 16> Jumps;
+public:
+  JumpScopeChecker(Stmt *Body, Sema &S);
+private:
+  void BuildScopeInformation(Stmt *S, unsigned ParentScope);
+  void VerifyJumps();
+  void CheckJump(Stmt *From, Stmt *To,
+                 SourceLocation DiagLoc, unsigned JumpDiag);
+};
+} // end anonymous namespace
+
+
+JumpScopeChecker::JumpScopeChecker(Stmt *Body, Sema &s) : S(s) {
+  // Add a scope entry for function scope.
+  Scopes.push_back(GotoScope(~0U, ~0U, SourceLocation()));
+
+  // Build information for the top level compound statement, so that we have a
+  // defined scope record for every "goto" and label.
+  BuildScopeInformation(Body, 0);
+
+  // Check that all jumps we saw are kosher.
+  VerifyJumps();
+}
+
+/// GetDiagForGotoScopeDecl - If this decl induces a new goto scope, return a
+/// diagnostic that should be emitted if control goes over it. If not, return 0.
+static unsigned GetDiagForGotoScopeDecl(const Decl *D) {
+  if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
+    if (VD->getType()->isVariablyModifiedType())
+      return diag::note_protected_by_vla;
+    if (VD->hasAttr<CleanupAttr>())
+      return diag::note_protected_by_cleanup;
+    if (VD->hasAttr<BlocksAttr>())
+      return diag::note_protected_by___block;
+  } else if (const TypedefDecl *TD = dyn_cast<TypedefDecl>(D)) {
+    if (TD->getUnderlyingType()->isVariablyModifiedType())
+      return diag::note_protected_by_vla_typedef;
+  }
+
+  return 0;
+}
+
+
+/// BuildScopeInformation - The statements from CI to CE are known to form a
+/// coherent VLA scope with a specified parent node.  Walk through the
+/// statements, adding any labels or gotos to LabelAndGotoScopes and recursively
+/// walking the AST as needed.
+void JumpScopeChecker::BuildScopeInformation(Stmt *S, unsigned ParentScope) {
+
+  // If we found a label, remember that it is in ParentScope scope.
+  if (isa<LabelStmt>(S) || isa<DefaultStmt>(S) || isa<CaseStmt>(S)) {
+    LabelAndGotoScopes[S] = ParentScope;
+  } else if (isa<GotoStmt>(S) || isa<SwitchStmt>(S) ||
+             isa<IndirectGotoStmt>(S) || isa<AddrLabelExpr>(S)) {
+    // Remember both what scope a goto is in as well as the fact that we have
+    // it.  This makes the second scan not have to walk the AST again.
+    LabelAndGotoScopes[S] = ParentScope;
+    Jumps.push_back(S);
+  }
+
+  for (Stmt::child_iterator CI = S->child_begin(), E = S->child_end(); CI != E;
+       ++CI) {
+    Stmt *SubStmt = *CI;
+    if (SubStmt == 0) continue;
+
+    // FIXME: diagnose jumps past initialization: required in C++, warning in C.
+    //   goto L; int X = 4;   L: ;
+
+    // If this is a declstmt with a VLA definition, it defines a scope from here
+    // to the end of the containing context.
+    if (DeclStmt *DS = dyn_cast<DeclStmt>(SubStmt)) {
+      // The decl statement creates a scope if any of the decls in it are VLAs or
+      // have the cleanup attribute.
+      for (DeclStmt::decl_iterator I = DS->decl_begin(), E = DS->decl_end();
+           I != E; ++I) {
+        // If this decl causes a new scope, push and switch to it.
+        if (unsigned Diag = GetDiagForGotoScopeDecl(*I)) {
+          Scopes.push_back(GotoScope(ParentScope, Diag, (*I)->getLocation()));
+          ParentScope = Scopes.size()-1;
+        }
+
+        // If the decl has an initializer, walk it with the potentially new
+        // scope we just installed.
+        if (VarDecl *VD = dyn_cast<VarDecl>(*I))
+          if (Expr *Init = VD->getInit())
+            BuildScopeInformation(Init, ParentScope);
+      }
+      continue;
+    }
+
+    // Disallow jumps into any part of an @try statement by pushing a scope and
+    // walking all sub-stmts in that scope.
+    if (ObjCAtTryStmt *AT = dyn_cast<ObjCAtTryStmt>(SubStmt)) {
+      // Recursively walk the AST for the @try part.
+      Scopes.push_back(GotoScope(ParentScope,diag::note_protected_by_objc_try,
+                                 AT->getAtTryLoc()));
+      if (Stmt *TryPart = AT->getTryBody())
+        BuildScopeInformation(TryPart, Scopes.size()-1);
+
+      // Jump from the catch to the finally or try is not valid.
+      for (ObjCAtCatchStmt *AC = AT->getCatchStmts(); AC;
+           AC = AC->getNextCatchStmt()) {
+        Scopes.push_back(GotoScope(ParentScope,
+                                   diag::note_protected_by_objc_catch,
+                                   AC->getAtCatchLoc()));
+        // @catches are nested and it isn't
+        BuildScopeInformation(AC->getCatchBody(), Scopes.size()-1);
+      }
+
+      // Jump from the finally to the try or catch is not valid.
+      if (ObjCAtFinallyStmt *AF = AT->getFinallyStmt()) {
+        Scopes.push_back(GotoScope(ParentScope,
+                                   diag::note_protected_by_objc_finally,
+                                   AF->getAtFinallyLoc()));
+        BuildScopeInformation(AF, Scopes.size()-1);
+      }
+
+      continue;
+    }
+
+    // Disallow jumps into the protected statement of an @synchronized, but
+    // allow jumps into the object expression it protects.
+    if (ObjCAtSynchronizedStmt *AS = dyn_cast<ObjCAtSynchronizedStmt>(SubStmt)){
+      // Recursively walk the AST for the @synchronized object expr, it is
+      // evaluated in the normal scope.
+      BuildScopeInformation(AS->getSynchExpr(), ParentScope);
+
+      // Recursively walk the AST for the @synchronized part, protected by a new
+      // scope.
+      Scopes.push_back(GotoScope(ParentScope,
+                                 diag::note_protected_by_objc_synchronized,
+                                 AS->getAtSynchronizedLoc()));
+      BuildScopeInformation(AS->getSynchBody(), Scopes.size()-1);
+      continue;
+    }
+
+    // Disallow jumps into any part of a C++ try statement. This is pretty
+    // much the same as for Obj-C.
+    if (CXXTryStmt *TS = dyn_cast<CXXTryStmt>(SubStmt)) {
+      Scopes.push_back(GotoScope(ParentScope, diag::note_protected_by_cxx_try,
+                                 TS->getSourceRange().getBegin()));
+      if (Stmt *TryBlock = TS->getTryBlock())
+        BuildScopeInformation(TryBlock, Scopes.size()-1);
+
+      // Jump from the catch into the try is not allowed either.
+      for (unsigned I = 0, E = TS->getNumHandlers(); I != E; ++I) {
+        CXXCatchStmt *CS = TS->getHandler(I);
+        Scopes.push_back(GotoScope(ParentScope,
+                                   diag::note_protected_by_cxx_catch,
+                                   CS->getSourceRange().getBegin()));
+        BuildScopeInformation(CS->getHandlerBlock(), Scopes.size()-1);
+      }
+
+      continue;
+    }
+
+    // Recursively walk the AST.
+    BuildScopeInformation(SubStmt, ParentScope);
+  }
+}
+
+/// VerifyJumps - Verify each element of the Jumps array to see if they are
+/// valid, emitting diagnostics if not.
+void JumpScopeChecker::VerifyJumps() {
+  while (!Jumps.empty()) {
+    Stmt *Jump = Jumps.pop_back_val();
+
+    // With a goto,
+    if (GotoStmt *GS = dyn_cast<GotoStmt>(Jump)) {
+      CheckJump(GS, GS->getLabel(), GS->getGotoLoc(),
+                diag::err_goto_into_protected_scope);
+      continue;
+    }
+
+    if (SwitchStmt *SS = dyn_cast<SwitchStmt>(Jump)) {
+      for (SwitchCase *SC = SS->getSwitchCaseList(); SC;
+           SC = SC->getNextSwitchCase()) {
+        assert(LabelAndGotoScopes.count(SC) && "Case not visited?");
+        CheckJump(SS, SC, SC->getLocStart(),
+                  diag::err_switch_into_protected_scope);
+      }
+      continue;
+    }
+
+    unsigned DiagnosticScope;
+
+    // We don't know where an indirect goto goes, require that it be at the
+    // top level of scoping.
+    if (IndirectGotoStmt *IG = dyn_cast<IndirectGotoStmt>(Jump)) {
+      assert(LabelAndGotoScopes.count(Jump) &&
+             "Jump didn't get added to scopes?");
+      unsigned GotoScope = LabelAndGotoScopes[IG];
+      if (GotoScope == 0) continue;  // indirect jump is ok.
+      S.Diag(IG->getGotoLoc(), diag::err_indirect_goto_in_protected_scope);
+      DiagnosticScope = GotoScope;
+    } else {
+      // We model &&Label as a jump for purposes of scope tracking.  We actually
+      // don't care *where* the address of label is, but we require the *label
+      // itself* to be in scope 0.  If it is nested inside of a VLA scope, then
+      // it is possible for an indirect goto to illegally enter the VLA scope by
+      // indirectly jumping to the label.
+      assert(isa<AddrLabelExpr>(Jump) && "Unknown jump type");
+      LabelStmt *TheLabel = cast<AddrLabelExpr>(Jump)->getLabel();
+
+      assert(LabelAndGotoScopes.count(TheLabel) &&
+             "Referenced label didn't get added to scopes?");
+      unsigned LabelScope = LabelAndGotoScopes[TheLabel];
+      if (LabelScope == 0) continue; // Addr of label is ok.
+
+      S.Diag(Jump->getLocStart(), diag::err_addr_of_label_in_protected_scope);
+      DiagnosticScope = LabelScope;
+    }
+
+    // Report all the things that would be skipped over by this &&label or
+    // indirect goto.
+    while (DiagnosticScope != 0) {
+      S.Diag(Scopes[DiagnosticScope].Loc, Scopes[DiagnosticScope].Diag);
+      DiagnosticScope = Scopes[DiagnosticScope].ParentScope;
+    }
+  }
+}
+
+/// CheckJump - Validate that the specified jump statement is valid: that it is
+/// jumping within or out of its current scope, not into a deeper one.
+void JumpScopeChecker::CheckJump(Stmt *From, Stmt *To,
+                                 SourceLocation DiagLoc, unsigned JumpDiag) {
+  assert(LabelAndGotoScopes.count(From) && "Jump didn't get added to scopes?");
+  unsigned FromScope = LabelAndGotoScopes[From];
+
+  assert(LabelAndGotoScopes.count(To) && "Jump didn't get added to scopes?");
+  unsigned ToScope = LabelAndGotoScopes[To];
+
+  // Common case: exactly the same scope, which is fine.
+  if (FromScope == ToScope) return;
+
+  // The only valid mismatch jump case happens when the jump is more deeply
+  // nested inside the jump target.  Do a quick scan to see if the jump is valid
+  // because valid code is more common than invalid code.
+  unsigned TestScope = Scopes[FromScope].ParentScope;
+  while (TestScope != ~0U) {
+    // If we found the jump target, then we're jumping out of our current scope,
+    // which is perfectly fine.
+    if (TestScope == ToScope) return;
+
+    // Otherwise, scan up the hierarchy.
+    TestScope = Scopes[TestScope].ParentScope;
+  }
+
+  // If we get here, then we know we have invalid code.  Diagnose the bad jump,
+  // and then emit a note at each VLA being jumped out of.
+  S.Diag(DiagLoc, JumpDiag);
+
+  // Eliminate the common prefix of the jump and the target.  Start by
+  // linearizing both scopes, reversing them as we go.
+  std::vector<unsigned> FromScopes, ToScopes;
+  for (TestScope = FromScope; TestScope != ~0U;
+       TestScope = Scopes[TestScope].ParentScope)
+    FromScopes.push_back(TestScope);
+  for (TestScope = ToScope; TestScope != ~0U;
+       TestScope = Scopes[TestScope].ParentScope)
+    ToScopes.push_back(TestScope);
+
+  // Remove any common entries (such as the top-level function scope).
+  while (!FromScopes.empty() && FromScopes.back() == ToScopes.back()) {
+    FromScopes.pop_back();
+    ToScopes.pop_back();
+  }
+
+  // Emit diagnostics for whatever is left in ToScopes.
+  for (unsigned i = 0, e = ToScopes.size(); i != e; ++i)
+    S.Diag(Scopes[ToScopes[i]].Loc, Scopes[ToScopes[i]].Diag);
+}
+
+void Sema::DiagnoseInvalidJumps(Stmt *Body) {
+  (void)JumpScopeChecker(Body, *this);
+}
diff --git a/lib/Sema/Lookup.h b/lib/Sema/Lookup.h
new file mode 100644
index 0000000..6b26945
--- /dev/null
+++ b/lib/Sema/Lookup.h
@@ -0,0 +1,630 @@
+//===--- Lookup.h - Classes for name lookup ---------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the LookupResult class, which is integral to
+// Sema's name-lookup subsystem.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_SEMA_LOOKUP_H
+#define LLVM_CLANG_SEMA_LOOKUP_H
+
+#include "Sema.h"
+
+namespace clang {
+
+/// @brief Represents the results of name lookup.
+///
+/// An instance of the LookupResult class captures the results of a
+/// single name lookup, which can return no result (nothing found),
+/// a single declaration, a set of overloaded functions, or an
+/// ambiguity. Use the getKind() method to determine which of these
+/// results occurred for a given lookup.
+class LookupResult {
+public:
+  enum LookupResultKind {
+    /// @brief No entity found met the criteria.
+    NotFound = 0,
+
+    /// @brief No entity found met the criteria within the current 
+    /// instantiation,, but there were dependent base classes of the 
+    /// current instantiation that could not be searched.
+    NotFoundInCurrentInstantiation,
+    
+    /// @brief Name lookup found a single declaration that met the
+    /// criteria.  getFoundDecl() will return this declaration.
+    Found,
+
+    /// @brief Name lookup found a set of overloaded functions that
+    /// met the criteria.
+    FoundOverloaded,
+
+    /// @brief Name lookup found an unresolvable value declaration
+    /// and cannot yet complete.  This only happens in C++ dependent
+    /// contexts with dependent using declarations.
+    FoundUnresolvedValue,
+
+    /// @brief Name lookup results in an ambiguity; use
+    /// getAmbiguityKind to figure out what kind of ambiguity
+    /// we have.
+    Ambiguous
+  };
+
+  enum AmbiguityKind {
+    /// Name lookup results in an ambiguity because multiple
+    /// entities that meet the lookup criteria were found in
+    /// subobjects of different types. For example:
+    /// @code
+    /// struct A { void f(int); }
+    /// struct B { void f(double); }
+    /// struct C : A, B { };
+    /// void test(C c) {
+    ///   c.f(0); // error: A::f and B::f come from subobjects of different
+    ///           // types. overload resolution is not performed.
+    /// }
+    /// @endcode
+    AmbiguousBaseSubobjectTypes,
+
+    /// Name lookup results in an ambiguity because multiple
+    /// nonstatic entities that meet the lookup criteria were found
+    /// in different subobjects of the same type. For example:
+    /// @code
+    /// struct A { int x; };
+    /// struct B : A { };
+    /// struct C : A { };
+    /// struct D : B, C { };
+    /// int test(D d) {
+    ///   return d.x; // error: 'x' is found in two A subobjects (of B and C)
+    /// }
+    /// @endcode
+    AmbiguousBaseSubobjects,
+
+    /// Name lookup results in an ambiguity because multiple definitions
+    /// of entity that meet the lookup criteria were found in different
+    /// declaration contexts.
+    /// @code
+    /// namespace A {
+    ///   int i;
+    ///   namespace B { int i; }
+    ///   int test() {
+    ///     using namespace B;
+    ///     return i; // error 'i' is found in namespace A and A::B
+    ///    }
+    /// }
+    /// @endcode
+    AmbiguousReference,
+
+    /// Name lookup results in an ambiguity because an entity with a
+    /// tag name was hidden by an entity with an ordinary name from
+    /// a different context.
+    /// @code
+    /// namespace A { struct Foo {}; }
+    /// namespace B { void Foo(); }
+    /// namespace C {
+    ///   using namespace A;
+    ///   using namespace B;
+    /// }
+    /// void test() {
+    ///   C::Foo(); // error: tag 'A::Foo' is hidden by an object in a
+    ///             // different namespace
+    /// }
+    /// @endcode
+    AmbiguousTagHiding
+  };
+
+  /// A little identifier for flagging temporary lookup results.
+  enum TemporaryToken {
+    Temporary
+  };
+
+  typedef UnresolvedSetImpl::iterator iterator;
+  typedef bool (*ResultFilter)(NamedDecl*, unsigned IDNS);
+
+  LookupResult(Sema &SemaRef, DeclarationName Name, SourceLocation NameLoc,
+               Sema::LookupNameKind LookupKind,
+               Sema::RedeclarationKind Redecl = Sema::NotForRedeclaration)
+    : ResultKind(NotFound),
+      Paths(0),
+      NamingClass(0),
+      SemaRef(SemaRef),
+      Name(Name),
+      NameLoc(NameLoc),
+      LookupKind(LookupKind),
+      IsAcceptableFn(0),
+      IDNS(0),
+      Redecl(Redecl != Sema::NotForRedeclaration),
+      HideTags(true),
+      Diagnose(Redecl == Sema::NotForRedeclaration)
+  {
+    configure();
+  }
+
+  /// Creates a temporary lookup result, initializing its core data
+  /// using the information from another result.  Diagnostics are always
+  /// disabled.
+  LookupResult(TemporaryToken _, const LookupResult &Other)
+    : ResultKind(NotFound),
+      Paths(0),
+      NamingClass(0),
+      SemaRef(Other.SemaRef),
+      Name(Other.Name),
+      NameLoc(Other.NameLoc),
+      LookupKind(Other.LookupKind),
+      IsAcceptableFn(Other.IsAcceptableFn),
+      IDNS(Other.IDNS),
+      Redecl(Other.Redecl),
+      HideTags(Other.HideTags),
+      Diagnose(false)
+  {}
+
+  ~LookupResult() {
+    if (Diagnose) diagnose();
+    if (Paths) deletePaths(Paths);
+  }
+
+  /// Gets the name to look up.
+  DeclarationName getLookupName() const {
+    return Name;
+  }
+
+  /// \brief Sets the name to look up.
+  void setLookupName(DeclarationName Name) {
+    this->Name = Name;
+  }
+
+  /// Gets the kind of lookup to perform.
+  Sema::LookupNameKind getLookupKind() const {
+    return LookupKind;
+  }
+
+  /// True if this lookup is just looking for an existing declaration.
+  bool isForRedeclaration() const {
+    return Redecl;
+  }
+
+  /// Sets whether tag declarations should be hidden by non-tag
+  /// declarations during resolution.  The default is true.
+  void setHideTags(bool Hide) {
+    HideTags = Hide;
+  }
+
+  bool isAmbiguous() const {
+    return getResultKind() == Ambiguous;
+  }
+
+  /// Determines if this names a single result which is not an
+  /// unresolved value using decl.  If so, it is safe to call
+  /// getFoundDecl().
+  bool isSingleResult() const {
+    return getResultKind() == Found;
+  }
+
+  /// Determines if the results are overloaded.
+  bool isOverloadedResult() const {
+    return getResultKind() == FoundOverloaded;
+  }
+
+  bool isUnresolvableResult() const {
+    return getResultKind() == FoundUnresolvedValue;
+  }
+
+  LookupResultKind getResultKind() const {
+    sanity();
+    return ResultKind;
+  }
+
+  AmbiguityKind getAmbiguityKind() const {
+    assert(isAmbiguous());
+    return Ambiguity;
+  }
+
+  const UnresolvedSetImpl &asUnresolvedSet() const {
+    return Decls;
+  }
+
+  iterator begin() const { return iterator(Decls.begin()); }
+  iterator end() const { return iterator(Decls.end()); }
+
+  /// \brief Return true if no decls were found
+  bool empty() const { return Decls.empty(); }
+
+  /// \brief Return the base paths structure that's associated with
+  /// these results, or null if none is.
+  CXXBasePaths *getBasePaths() const {
+    return Paths;
+  }
+
+  /// \brief Tests whether the given declaration is acceptable.
+  bool isAcceptableDecl(NamedDecl *D) const {
+    assert(IsAcceptableFn);
+    return IsAcceptableFn(D, IDNS);
+  }
+
+  /// \brief Returns the identifier namespace mask for this lookup.
+  unsigned getIdentifierNamespace() const {
+    return IDNS;
+  }
+
+  /// \brief Returns whether these results arose from performing a
+  /// lookup into a class.
+  bool isClassLookup() const {
+    return NamingClass != 0;
+  }
+
+  /// \brief Returns the 'naming class' for this lookup, i.e. the
+  /// class which was looked into to find these results.
+  ///
+  /// C++0x [class.access.base]p5:
+  ///   The access to a member is affected by the class in which the
+  ///   member is named. This naming class is the class in which the
+  ///   member name was looked up and found. [Note: this class can be
+  ///   explicit, e.g., when a qualified-id is used, or implicit,
+  ///   e.g., when a class member access operator (5.2.5) is used
+  ///   (including cases where an implicit "this->" is added). If both
+  ///   a class member access operator and a qualified-id are used to
+  ///   name the member (as in p->T::m), the class naming the member
+  ///   is the class named by the nested-name-specifier of the
+  ///   qualified-id (that is, T). -- end note ]
+  ///
+  /// This is set by the lookup routines when they find results in a class.
+  CXXRecordDecl *getNamingClass() const {
+    return NamingClass;
+  }
+
+  /// \brief Sets the 'naming class' for this lookup.
+  void setNamingClass(CXXRecordDecl *Record) {
+    NamingClass = Record;
+  }
+
+  /// \brief Add a declaration to these results with its natural access.
+  /// Does not test the acceptance criteria.
+  void addDecl(NamedDecl *D) {
+    addDecl(D, D->getAccess());
+  }
+
+  /// \brief Add a declaration to these results with the given access.
+  /// Does not test the acceptance criteria.
+  void addDecl(NamedDecl *D, AccessSpecifier AS) {
+    Decls.addDecl(D, AS);
+    ResultKind = Found;
+  }
+
+  /// \brief Add all the declarations from another set of lookup
+  /// results.
+  void addAllDecls(const LookupResult &Other) {
+    Decls.append(Other.Decls.begin(), Other.Decls.end());
+    ResultKind = Found;
+  }
+
+  /// \brief Determine whether no result was found because we could not
+  /// search into dependent base classes of the current instantiation.
+  bool wasNotFoundInCurrentInstantiation() const {
+    return ResultKind == NotFoundInCurrentInstantiation;
+  }
+  
+  /// \brief Note that while no result was found in the current instantiation,
+  /// there were dependent base classes that could not be searched.
+  void setNotFoundInCurrentInstantiation() {
+    assert(ResultKind == NotFound && Decls.empty());
+    ResultKind = NotFoundInCurrentInstantiation;
+  }
+  
+  /// \brief Resolves the result kind of the lookup, possibly hiding
+  /// decls.
+  ///
+  /// This should be called in any environment where lookup might
+  /// generate multiple lookup results.
+  void resolveKind();
+
+  /// \brief Re-resolves the result kind of the lookup after a set of
+  /// removals has been performed.
+  void resolveKindAfterFilter() {
+    if (Decls.empty()) {
+      if (ResultKind != NotFoundInCurrentInstantiation)
+        ResultKind = NotFound;
+    } else {
+      ResultKind = Found;
+      resolveKind();
+    }
+  }
+
+  template <class DeclClass>
+  DeclClass *getAsSingle() const {
+    if (getResultKind() != Found) return 0;
+    return dyn_cast<DeclClass>(getFoundDecl());
+  }
+
+  /// \brief Fetch the unique decl found by this lookup.  Asserts
+  /// that one was found.
+  ///
+  /// This is intended for users who have examined the result kind
+  /// and are certain that there is only one result.
+  NamedDecl *getFoundDecl() const {
+    assert(getResultKind() == Found
+           && "getFoundDecl called on non-unique result");
+    return (*begin())->getUnderlyingDecl();
+  }
+
+  /// Fetches a representative decl.  Useful for lazy diagnostics.
+  NamedDecl *getRepresentativeDecl() const {
+    assert(!Decls.empty() && "cannot get representative of empty set");
+    return *begin();
+  }
+
+  /// \brief Asks if the result is a single tag decl.
+  bool isSingleTagDecl() const {
+    return getResultKind() == Found && isa<TagDecl>(getFoundDecl());
+  }
+
+  /// \brief Make these results show that the name was found in
+  /// base classes of different types.
+  ///
+  /// The given paths object is copied and invalidated.
+  void setAmbiguousBaseSubobjectTypes(CXXBasePaths &P);
+
+  /// \brief Make these results show that the name was found in
+  /// distinct base classes of the same type.
+  ///
+  /// The given paths object is copied and invalidated.
+  void setAmbiguousBaseSubobjects(CXXBasePaths &P);
+
+  /// \brief Make these results show that the name was found in
+  /// different contexts and a tag decl was hidden by an ordinary
+  /// decl in a different context.
+  void setAmbiguousQualifiedTagHiding() {
+    setAmbiguous(AmbiguousTagHiding);
+  }
+
+  /// \brief Clears out any current state.
+  void clear() {
+    ResultKind = NotFound;
+    Decls.clear();
+    if (Paths) deletePaths(Paths);
+    Paths = NULL;
+  }
+
+  /// \brief Clears out any current state and re-initializes for a
+  /// different kind of lookup.
+  void clear(Sema::LookupNameKind Kind) {
+    clear();
+    LookupKind = Kind;
+    configure();
+  }
+
+  void print(llvm::raw_ostream &);
+
+  /// Suppress the diagnostics that would normally fire because of this
+  /// lookup.  This happens during (e.g.) redeclaration lookups.
+  void suppressDiagnostics() {
+    Diagnose = false;
+  }
+
+  /// Sets a 'context' source range.
+  void setContextRange(SourceRange SR) {
+    NameContextRange = SR;
+  }
+
+  /// Gets the source range of the context of this name; for C++
+  /// qualified lookups, this is the source range of the scope
+  /// specifier.
+  SourceRange getContextRange() const {
+    return NameContextRange;
+  }
+
+  /// Gets the location of the identifier.  This isn't always defined:
+  /// sometimes we're doing lookups on synthesized names.
+  SourceLocation getNameLoc() const {
+    return NameLoc;
+  }
+
+  /// \brief Get the Sema object that this lookup result is searching
+  /// with.
+  Sema &getSema() const { return SemaRef; }
+
+  /// A class for iterating through a result set and possibly
+  /// filtering out results.  The results returned are possibly
+  /// sugared.
+  class Filter {
+    LookupResult &Results;
+    LookupResult::iterator I;
+    bool Changed;
+#ifndef NDEBUG
+    bool CalledDone;
+#endif
+    
+    friend class LookupResult;
+    Filter(LookupResult &Results)
+      : Results(Results), I(Results.begin()), Changed(false)
+#ifndef NDEBUG
+      , CalledDone(false)
+#endif
+    {}
+
+  public:
+#ifndef NDEBUG
+    ~Filter() {
+      assert(CalledDone &&
+             "LookupResult::Filter destroyed without done() call");
+    }
+#endif
+
+    bool hasNext() const {
+      return I != Results.end();
+    }
+
+    NamedDecl *next() {
+      assert(I != Results.end() && "next() called on empty filter");
+      return *I++;
+    }
+
+    /// Erase the last element returned from this iterator.
+    void erase() {
+      Results.Decls.erase(--I);
+      Changed = true;
+    }
+
+    /// Replaces the current entry with the given one, preserving the
+    /// access bits.
+    void replace(NamedDecl *D) {
+      Results.Decls.replace(I-1, D);
+      Changed = true;
+    }
+
+    /// Replaces the current entry with the given one.
+    void replace(NamedDecl *D, AccessSpecifier AS) {
+      Results.Decls.replace(I-1, D, AS);
+      Changed = true;
+    }
+
+    void done() {
+#ifndef NDEBUG
+      assert(!CalledDone && "done() called twice");
+      CalledDone = true;
+#endif
+
+      if (Changed)
+        Results.resolveKindAfterFilter();
+    }
+  };
+
+  /// Create a filter for this result set.
+  Filter makeFilter() {
+    return Filter(*this);
+  }
+
+private:
+  void diagnose() {
+    if (isAmbiguous())
+      SemaRef.DiagnoseAmbiguousLookup(*this);
+    else if (isClassLookup() && SemaRef.getLangOptions().AccessControl)
+      SemaRef.CheckLookupAccess(*this);
+  }
+
+  void setAmbiguous(AmbiguityKind AK) {
+    ResultKind = Ambiguous;
+    Ambiguity = AK;
+  }
+
+  void addDeclsFromBasePaths(const CXXBasePaths &P);
+  void configure();
+
+  // Sanity checks.
+  void sanity() const {
+    assert(ResultKind != NotFound || Decls.size() == 0);
+    assert(ResultKind != Found || Decls.size() == 1);
+    assert(ResultKind != FoundOverloaded || Decls.size() > 1 ||
+           (Decls.size() == 1 &&
+            isa<FunctionTemplateDecl>((*begin())->getUnderlyingDecl())));
+    assert(ResultKind != FoundUnresolvedValue || sanityCheckUnresolved());
+    assert(ResultKind != Ambiguous || Decls.size() > 1 ||
+           (Decls.size() == 1 && Ambiguity == AmbiguousBaseSubobjects));
+    assert((Paths != NULL) == (ResultKind == Ambiguous &&
+                               (Ambiguity == AmbiguousBaseSubobjectTypes ||
+                                Ambiguity == AmbiguousBaseSubobjects)));
+  }
+
+  bool sanityCheckUnresolved() const {
+    for (iterator I = begin(), E = end(); I != E; ++I)
+      if (isa<UnresolvedUsingValueDecl>(*I))
+        return true;
+    return false;
+  }
+
+  static void deletePaths(CXXBasePaths *);
+
+  // Results.
+  LookupResultKind ResultKind;
+  AmbiguityKind Ambiguity; // ill-defined unless ambiguous
+  UnresolvedSet<8> Decls;
+  CXXBasePaths *Paths;
+  CXXRecordDecl *NamingClass;
+
+  // Parameters.
+  Sema &SemaRef;
+  DeclarationName Name;
+  SourceLocation NameLoc;
+  SourceRange NameContextRange;
+  Sema::LookupNameKind LookupKind;
+  ResultFilter IsAcceptableFn; // set by configure()
+  unsigned IDNS; // set by configure()
+
+  bool Redecl;
+
+  /// \brief True if tag declarations should be hidden if non-tags
+  ///   are present
+  bool HideTags;
+
+  bool Diagnose;
+};
+
+  /// \brief Consumes visible declarations found when searching for
+  /// all visible names within a given scope or context.
+  ///
+  /// This abstract class is meant to be subclassed by clients of \c
+  /// Sema::LookupVisibleDecls(), each of which should override the \c
+  /// FoundDecl() function to process declarations as they are found.
+  class VisibleDeclConsumer {
+  public:
+    /// \brief Destroys the visible declaration consumer.
+    virtual ~VisibleDeclConsumer();
+
+    /// \brief Invoked each time \p Sema::LookupVisibleDecls() finds a
+    /// declaration visible from the current scope or context.
+    ///
+    /// \param ND the declaration found.
+    ///
+    /// \param Hiding a declaration that hides the declaration \p ND,
+    /// or NULL if no such declaration exists.
+    ///
+    /// \param InBaseClass whether this declaration was found in base
+    /// class of the context we searched.
+    virtual void FoundDecl(NamedDecl *ND, NamedDecl *Hiding, 
+                           bool InBaseClass) = 0;
+  };
+
+/// \brief A class for storing results from argument-dependent lookup.
+class ADLResult {
+private:
+  /// A map from canonical decls to the 'most recent' decl.
+  llvm::DenseMap<NamedDecl*, NamedDecl*> Decls;
+
+public:
+  /// Adds a new ADL candidate to this map.
+  void insert(NamedDecl *D);
+
+  /// Removes any data associated with a given decl.
+  void erase(NamedDecl *D) {
+    Decls.erase(cast<NamedDecl>(D->getCanonicalDecl()));
+  }
+
+  class iterator {
+    typedef llvm::DenseMap<NamedDecl*,NamedDecl*>::iterator inner_iterator;
+    inner_iterator iter;
+
+    friend class ADLResult;
+    iterator(const inner_iterator &iter) : iter(iter) {}
+  public:
+    iterator() {}
+
+    iterator &operator++() { ++iter; return *this; }
+    iterator operator++(int) { return iterator(iter++); }
+
+    NamedDecl *operator*() const { return iter->second; }
+
+    bool operator==(const iterator &other) const { return iter == other.iter; }
+    bool operator!=(const iterator &other) const { return iter != other.iter; }
+  };
+
+  iterator begin() { return iterator(Decls.begin()); }
+  iterator end() { return iterator(Decls.end()); }
+};
+
+}
+
+#endif
diff --git a/lib/Sema/Makefile b/lib/Sema/Makefile
new file mode 100644
index 0000000..158f1af
--- /dev/null
+++ b/lib/Sema/Makefile
@@ -0,0 +1,22 @@
+##===- clang/lib/Sema/Makefile -----------------------------*- Makefile -*-===##
+# 
+#                     The LLVM Compiler Infrastructure
+#
+# This file is distributed under the University of Illinois Open Source
+# License. See LICENSE.TXT for details.
+# 
+##===----------------------------------------------------------------------===##
+#
+#  This implements the semantic analyzer and AST builder library for the 
+#  C-Language front-end.
+#
+##===----------------------------------------------------------------------===##
+
+LEVEL = ../../../..
+LIBRARYNAME := clangSema
+BUILD_ARCHIVE = 1
+
+CPPFLAGS += -I$(PROJ_SRC_DIR)/../../include -I$(PROJ_OBJ_DIR)/../../include
+
+include $(LEVEL)/Makefile.common
+
diff --git a/lib/Sema/ParseAST.cpp b/lib/Sema/ParseAST.cpp
new file mode 100644
index 0000000..898b3c2
--- /dev/null
+++ b/lib/Sema/ParseAST.cpp
@@ -0,0 +1,101 @@
+//===--- ParseAST.cpp - Provide the clang::ParseAST method ----------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the clang::ParseAST method.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Sema/ParseAST.h"
+#include "Sema.h"
+#include "clang/Sema/CodeCompleteConsumer.h"
+#include "clang/Sema/SemaConsumer.h"
+#include "clang/Sema/ExternalSemaSource.h"
+#include "clang/AST/ASTConsumer.h"
+#include "clang/AST/ExternalASTSource.h"
+#include "clang/AST/Stmt.h"
+#include "clang/Parse/Parser.h"
+#include <cstdio>
+
+using namespace clang;
+
+//===----------------------------------------------------------------------===//
+// Public interface to the file
+//===----------------------------------------------------------------------===//
+
+/// ParseAST - Parse the entire file specified, notifying the ASTConsumer as
+/// the file is parsed.  This inserts the parsed decls into the translation unit
+/// held by Ctx.
+///
+void clang::ParseAST(Preprocessor &PP, ASTConsumer *Consumer,
+                     ASTContext &Ctx, bool PrintStats,
+                     bool CompleteTranslationUnit,
+                     CodeCompleteConsumer *CompletionConsumer) {
+  // Collect global stats on Decls/Stmts (until we have a module streamer).
+  if (PrintStats) {
+    Decl::CollectingStats(true);
+    Stmt::CollectingStats(true);
+  }
+
+  Sema S(PP, Ctx, *Consumer, CompleteTranslationUnit, CompletionConsumer);
+  Parser P(PP, S);
+  PP.EnterMainSourceFile();
+
+  // Initialize the parser.
+  P.Initialize();
+
+  Consumer->Initialize(Ctx);
+
+  if (SemaConsumer *SC = dyn_cast<SemaConsumer>(Consumer))
+    SC->InitializeSema(S);
+
+  if (ExternalASTSource *External = Ctx.getExternalSource()) {
+    if (ExternalSemaSource *ExternalSema =
+          dyn_cast<ExternalSemaSource>(External))
+      ExternalSema->InitializeSema(S);
+
+    External->StartTranslationUnit(Consumer);
+  }
+
+  Parser::DeclGroupPtrTy ADecl;
+
+  while (!P.ParseTopLevelDecl(ADecl)) {  // Not end of file.
+    // If we got a null return and something *was* parsed, ignore it.  This
+    // is due to a top-level semicolon, an action override, or a parse error
+    // skipping something.
+    if (ADecl)
+      Consumer->HandleTopLevelDecl(ADecl.getAsVal<DeclGroupRef>());
+  };
+  // Check for any pending objective-c implementation decl.
+  while ((ADecl = P.RetrievePendingObjCImpDecl()))
+    Consumer->HandleTopLevelDecl(ADecl.getAsVal<DeclGroupRef>());
+
+  // Process any TopLevelDecls generated by #pragma weak.
+  for (llvm::SmallVector<Decl*,2>::iterator
+        I = S.WeakTopLevelDecls().begin(),
+        E = S.WeakTopLevelDecls().end(); I != E; ++I)
+    Consumer->HandleTopLevelDecl(DeclGroupRef(*I));
+
+  Consumer->HandleTranslationUnit(Ctx);
+
+  if (ExternalSemaSource *ESS =
+        dyn_cast_or_null<ExternalSemaSource>(Ctx.getExternalSource()))
+    ESS->ForgetSema();
+
+  if (SemaConsumer *SC = dyn_cast<SemaConsumer>(Consumer))
+    SC->ForgetSema();
+
+  if (PrintStats) {
+    fprintf(stderr, "\nSTATISTICS:\n");
+    P.getActions().PrintStats();
+    Ctx.PrintStats();
+    Decl::PrintStats();
+    Stmt::PrintStats();
+    Consumer->PrintStats();
+  }
+}
diff --git a/lib/Sema/Sema.cpp b/lib/Sema/Sema.cpp
new file mode 100644
index 0000000..e9a1d9c
--- /dev/null
+++ b/lib/Sema/Sema.cpp
@@ -0,0 +1,333 @@
+//===--- Sema.cpp - AST Builder and Semantic Analysis Implementation ------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the actions class which performs semantic analysis and
+// builds an AST out of a parse stream.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Sema.h"
+#include "TargetAttributesSema.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/SmallSet.h"
+#include "llvm/ADT/APFloat.h"
+#include "clang/AST/ASTConsumer.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/ASTDiagnostic.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/AST/Expr.h"
+#include "clang/Lex/Preprocessor.h"
+#include "clang/Basic/PartialDiagnostic.h"
+#include "clang/Basic/TargetInfo.h"
+using namespace clang;
+                                       
+static inline RecordDecl *CreateStructDecl(ASTContext &C, const char *Name) {
+  if (C.getLangOptions().CPlusPlus)
+    return CXXRecordDecl::Create(C, TagDecl::TK_struct,
+                                 C.getTranslationUnitDecl(),
+                                 SourceLocation(), &C.Idents.get(Name));
+
+  return RecordDecl::Create(C, TagDecl::TK_struct,
+                            C.getTranslationUnitDecl(),
+                            SourceLocation(), &C.Idents.get(Name));
+}
+
+void Sema::ActOnTranslationUnitScope(SourceLocation Loc, Scope *S) {
+  TUScope = S;
+  PushDeclContext(S, Context.getTranslationUnitDecl());
+
+  if (PP.getTargetInfo().getPointerWidth(0) >= 64) {
+    TypeSourceInfo *TInfo;
+
+    // Install [u]int128_t for 64-bit targets.
+    TInfo = Context.getTrivialTypeSourceInfo(Context.Int128Ty);
+    PushOnScopeChains(TypedefDecl::Create(Context, CurContext,
+                                          SourceLocation(),
+                                          &Context.Idents.get("__int128_t"),
+                                          TInfo), TUScope);
+
+    TInfo = Context.getTrivialTypeSourceInfo(Context.UnsignedInt128Ty);
+    PushOnScopeChains(TypedefDecl::Create(Context, CurContext,
+                                          SourceLocation(),
+                                          &Context.Idents.get("__uint128_t"),
+                                          TInfo), TUScope);
+  }
+
+
+  if (!PP.getLangOptions().ObjC1) return;
+
+  // Built-in ObjC types may already be set by PCHReader (hence isNull checks).
+  if (Context.getObjCSelType().isNull()) {
+    // Create the built-in typedef for 'SEL'.
+    QualType SelT = Context.getPointerType(Context.ObjCBuiltinSelTy);
+    TypeSourceInfo *SelInfo = Context.getTrivialTypeSourceInfo(SelT);
+    TypedefDecl *SelTypedef
+      = TypedefDecl::Create(Context, CurContext, SourceLocation(),
+                            &Context.Idents.get("SEL"), SelInfo);
+    PushOnScopeChains(SelTypedef, TUScope);
+    Context.setObjCSelType(Context.getTypeDeclType(SelTypedef));
+    Context.ObjCSelRedefinitionType = Context.getObjCSelType();
+  }
+
+  // Synthesize "@class Protocol;
+  if (Context.getObjCProtoType().isNull()) {
+    ObjCInterfaceDecl *ProtocolDecl =
+      ObjCInterfaceDecl::Create(Context, CurContext, SourceLocation(),
+                                &Context.Idents.get("Protocol"),
+                                SourceLocation(), true);
+    Context.setObjCProtoType(Context.getObjCInterfaceType(ProtocolDecl));
+    PushOnScopeChains(ProtocolDecl, TUScope, false);
+  }
+  // Create the built-in typedef for 'id'.
+  if (Context.getObjCIdType().isNull()) {
+    QualType IdT = Context.getObjCObjectPointerType(Context.ObjCBuiltinIdTy);
+    TypeSourceInfo *IdInfo = Context.getTrivialTypeSourceInfo(IdT);
+    TypedefDecl *IdTypedef
+      = TypedefDecl::Create(Context, CurContext, SourceLocation(),
+                            &Context.Idents.get("id"), IdInfo);
+    PushOnScopeChains(IdTypedef, TUScope);
+    Context.setObjCIdType(Context.getTypeDeclType(IdTypedef));
+    Context.ObjCIdRedefinitionType = Context.getObjCIdType();
+  }
+  // Create the built-in typedef for 'Class'.
+  if (Context.getObjCClassType().isNull()) {
+    QualType ClassType
+      = Context.getObjCObjectPointerType(Context.ObjCBuiltinClassTy);
+    TypeSourceInfo *ClassInfo = Context.getTrivialTypeSourceInfo(ClassType);
+    TypedefDecl *ClassTypedef
+      = TypedefDecl::Create(Context, CurContext, SourceLocation(),
+                            &Context.Idents.get("Class"), ClassInfo);
+    PushOnScopeChains(ClassTypedef, TUScope);
+    Context.setObjCClassType(Context.getTypeDeclType(ClassTypedef));
+    Context.ObjCClassRedefinitionType = Context.getObjCClassType();
+  }
+}
+
+Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer,
+           bool CompleteTranslationUnit,
+           CodeCompleteConsumer *CodeCompleter)
+  : TheTargetAttributesSema(0),
+    LangOpts(pp.getLangOptions()), PP(pp), Context(ctxt), Consumer(consumer),
+    Diags(PP.getDiagnostics()), SourceMgr(PP.getSourceManager()),
+    ExternalSource(0), CodeCompleter(CodeCompleter), CurContext(0), 
+    CurBlock(0), PackContext(0), ParsingDeclDepth(0),
+    IdResolver(pp.getLangOptions()), StdNamespace(0), StdBadAlloc(0),
+    GlobalNewDeleteDeclared(false), 
+    CompleteTranslationUnit(CompleteTranslationUnit),
+    NumSFINAEErrors(0), NonInstantiationEntries(0), 
+    CurrentInstantiationScope(0), TyposCorrected(0)
+{
+  TUScope = 0;
+  if (getLangOptions().CPlusPlus)
+    FieldCollector.reset(new CXXFieldCollector());
+
+  // Tell diagnostics how to render things from the AST library.
+  PP.getDiagnostics().SetArgToStringFn(&FormatASTNodeDiagnosticArgument, 
+                                       &Context);
+
+  ExprEvalContexts.push_back(
+                  ExpressionEvaluationContextRecord(PotentiallyEvaluated, 0));
+}
+
+Sema::~Sema() {
+  if (PackContext) FreePackedContext();
+  delete TheTargetAttributesSema;
+}
+
+/// ImpCastExprToType - If Expr is not of type 'Type', insert an implicit cast.
+/// If there is already an implicit cast, merge into the existing one.
+/// If isLvalue, the result of the cast is an lvalue.
+void Sema::ImpCastExprToType(Expr *&Expr, QualType Ty,
+                             CastExpr::CastKind Kind, bool isLvalue) {
+  QualType ExprTy = Context.getCanonicalType(Expr->getType());
+  QualType TypeTy = Context.getCanonicalType(Ty);
+
+  if (ExprTy == TypeTy)
+    return;
+
+  if (Expr->getType()->isPointerType() && Ty->isPointerType()) {
+    QualType ExprBaseType = cast<PointerType>(ExprTy)->getPointeeType();
+    QualType BaseType = cast<PointerType>(TypeTy)->getPointeeType();
+    if (ExprBaseType.getAddressSpace() != BaseType.getAddressSpace()) {
+      Diag(Expr->getExprLoc(), diag::err_implicit_pointer_address_space_cast)
+        << Expr->getSourceRange();
+    }
+  }
+
+  CheckImplicitConversion(Expr, Ty);
+
+  if (ImplicitCastExpr *ImpCast = dyn_cast<ImplicitCastExpr>(Expr)) {
+    if (ImpCast->getCastKind() == Kind) {
+      ImpCast->setType(Ty);
+      ImpCast->setLvalueCast(isLvalue);
+      return;
+    }
+  }
+
+  Expr = new (Context) ImplicitCastExpr(Ty, Kind, Expr, isLvalue);
+}
+
+void Sema::DeleteExpr(ExprTy *E) {
+  if (E) static_cast<Expr*>(E)->Destroy(Context);
+}
+void Sema::DeleteStmt(StmtTy *S) {
+  if (S) static_cast<Stmt*>(S)->Destroy(Context);
+}
+
+/// ActOnEndOfTranslationUnit - This is called at the very end of the
+/// translation unit when EOF is reached and all but the top-level scope is
+/// popped.
+void Sema::ActOnEndOfTranslationUnit() {
+  
+  while (1) {
+    // C++: Perform implicit template instantiations.
+    //
+    // FIXME: When we perform these implicit instantiations, we do not carefully
+    // keep track of the point of instantiation (C++ [temp.point]). This means
+    // that name lookup that occurs within the template instantiation will
+    // always happen at the end of the translation unit, so it will find
+    // some names that should not be found. Although this is common behavior
+    // for C++ compilers, it is technically wrong. In the future, we either need
+    // to be able to filter the results of name lookup or we need to perform
+    // template instantiations earlier.
+    PerformPendingImplicitInstantiations();
+    
+    /// If ProcessPendingClassesWithUnmarkedVirtualMembers ends up marking 
+    /// any virtual member functions it might lead to more pending template
+    /// instantiations, which is why we need to loop here.
+    if (!ProcessPendingClassesWithUnmarkedVirtualMembers())
+      break;
+  }
+  
+  // Check for #pragma weak identifiers that were never declared
+  // FIXME: This will cause diagnostics to be emitted in a non-determinstic
+  // order!  Iterating over a densemap like this is bad.
+  for (llvm::DenseMap<IdentifierInfo*,WeakInfo>::iterator
+       I = WeakUndeclaredIdentifiers.begin(),
+       E = WeakUndeclaredIdentifiers.end(); I != E; ++I) {
+    if (I->second.getUsed()) continue;
+
+    Diag(I->second.getLocation(), diag::warn_weak_identifier_undeclared)
+      << I->first;
+  }
+
+  if (!CompleteTranslationUnit)
+    return;
+
+  // C99 6.9.2p2:
+  //   A declaration of an identifier for an 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. If a translation unit
+  //   contains one or more tentative definitions for an identifier,
+  //   and the translation unit contains no external definition for
+  //   that identifier, then the behavior is exactly as if the
+  //   translation unit contains a file scope declaration of that
+  //   identifier, with the composite type as of the end of the
+  //   translation unit, with an initializer equal to 0.
+  llvm::SmallSet<VarDecl *, 32> Seen;
+  for (unsigned i = 0, e = TentativeDefinitions.size(); i != e; ++i) {
+    VarDecl *VD = TentativeDefinitions[i]->getActingDefinition();
+
+    // If the tentative definition was completed, getActingDefinition() returns
+    // null. If we've already seen this variable before, insert()'s second
+    // return value is false.
+    if (VD == 0 || VD->isInvalidDecl() || !Seen.insert(VD))
+      continue;
+
+    if (const IncompleteArrayType *ArrayT
+        = Context.getAsIncompleteArrayType(VD->getType())) {
+      if (RequireCompleteType(VD->getLocation(),
+                              ArrayT->getElementType(),
+                              diag::err_tentative_def_incomplete_type_arr)) {
+        VD->setInvalidDecl();
+        continue;
+      }
+
+      // Set the length of the array to 1 (C99 6.9.2p5).
+      Diag(VD->getLocation(), diag::warn_tentative_incomplete_array);
+      llvm::APInt One(Context.getTypeSize(Context.getSizeType()), true);
+      QualType T = Context.getConstantArrayType(ArrayT->getElementType(),
+                                                One, ArrayType::Normal, 0);
+      VD->setType(T);
+    } else if (RequireCompleteType(VD->getLocation(), VD->getType(),
+                                   diag::err_tentative_def_incomplete_type))
+      VD->setInvalidDecl();
+
+    // Notify the consumer that we've completed a tentative definition.
+    if (!VD->isInvalidDecl())
+      Consumer.CompleteTentativeDefinition(VD);
+
+  }
+}
+
+
+//===----------------------------------------------------------------------===//
+// Helper functions.
+//===----------------------------------------------------------------------===//
+
+DeclContext *Sema::getFunctionLevelDeclContext() {
+  DeclContext *DC = CurContext;
+
+  while (isa<BlockDecl>(DC))
+    DC = DC->getParent();
+
+  return DC;
+}
+
+/// getCurFunctionDecl - If inside of a function body, this returns a pointer
+/// to the function decl for the function being parsed.  If we're currently
+/// in a 'block', this returns the containing context.
+FunctionDecl *Sema::getCurFunctionDecl() {
+  DeclContext *DC = getFunctionLevelDeclContext();
+  return dyn_cast<FunctionDecl>(DC);
+}
+
+ObjCMethodDecl *Sema::getCurMethodDecl() {
+  DeclContext *DC = getFunctionLevelDeclContext();
+  return dyn_cast<ObjCMethodDecl>(DC);
+}
+
+NamedDecl *Sema::getCurFunctionOrMethodDecl() {
+  DeclContext *DC = getFunctionLevelDeclContext();
+  if (isa<ObjCMethodDecl>(DC) || isa<FunctionDecl>(DC))
+    return cast<NamedDecl>(DC);
+  return 0;
+}
+
+Sema::SemaDiagnosticBuilder::~SemaDiagnosticBuilder() {
+  if (!this->Emit())
+    return;
+
+  // If this is not a note, and we're in a template instantiation
+  // that is different from the last template instantiation where
+  // we emitted an error, print a template instantiation
+  // backtrace.
+  if (!SemaRef.Diags.isBuiltinNote(DiagID) &&
+      !SemaRef.ActiveTemplateInstantiations.empty() &&
+      SemaRef.ActiveTemplateInstantiations.back()
+        != SemaRef.LastTemplateInstantiationErrorContext) {
+    SemaRef.PrintInstantiationStack();
+    SemaRef.LastTemplateInstantiationErrorContext
+      = SemaRef.ActiveTemplateInstantiations.back();
+  }
+}
+
+Sema::SemaDiagnosticBuilder
+Sema::Diag(SourceLocation Loc, const PartialDiagnostic& PD) {
+  SemaDiagnosticBuilder Builder(Diag(Loc, PD.getDiagID()));
+  PD.Emit(Builder);
+
+  return Builder;
+}
+
+void Sema::ActOnComment(SourceRange Comment) {
+  Context.Comments.push_back(Comment);
+}
+
diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h
new file mode 100644
index 0000000..a835c47
--- /dev/null
+++ b/lib/Sema/Sema.h
@@ -0,0 +1,4178 @@
+//===--- Sema.h - Semantic Analysis & AST Building --------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the Sema class, which performs semantic analysis and
+// builds ASTs.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_AST_SEMA_H
+#define LLVM_CLANG_AST_SEMA_H
+
+#include "IdentifierResolver.h"
+#include "CXXFieldCollector.h"
+#include "SemaOverload.h"
+#include "SemaTemplate.h"
+#include "clang/AST/Attr.h"
+#include "clang/AST/DeclBase.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/AST/DeclTemplate.h"
+#include "clang/AST/FullExpr.h"
+#include "clang/Parse/Action.h"
+#include "clang/Sema/SemaDiagnostic.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/DenseSet.h"
+#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/OwningPtr.h"
+#include <deque>
+#include <list>
+#include <map>
+#include <string>
+#include <vector>
+
+namespace llvm {
+  class APSInt;
+}
+
+namespace clang {
+  class AnalysisContext;
+  class ASTContext;
+  class ASTConsumer;
+  class CodeCompleteConsumer;
+  class Preprocessor;
+  class Decl;
+  class DeclContext;
+  class DeclSpec;
+  class ExternalSemaSource;
+  class NamedDecl;
+  class Stmt;
+  class Expr;
+  class InitListExpr;
+  class ParenListExpr;
+  class DesignatedInitExpr;
+  class CallExpr;
+  class DeclRefExpr;
+  class UnresolvedLookupExpr;
+  class UnresolvedMemberExpr;
+  class VarDecl;
+  class ParmVarDecl;
+  class TypedefDecl;
+  class FunctionDecl;
+  class QualType;
+  class LangOptions;
+  class Token;
+  class IntegerLiteral;
+  class StringLiteral;
+  class ArrayType;
+  class LabelStmt;
+  class SwitchStmt;
+  class CXXTryStmt;
+  class ExtVectorType;
+  class TypedefDecl;
+  class TemplateDecl;
+  class TemplateArgument;
+  class TemplateArgumentLoc;
+  class TemplateArgumentList;
+  class TemplateParameterList;
+  class TemplateTemplateParmDecl;
+  class ClassTemplatePartialSpecializationDecl;
+  class ClassTemplateDecl;
+  class ObjCInterfaceDecl;
+  class ObjCCompatibleAliasDecl;
+  class ObjCProtocolDecl;
+  class ObjCImplDecl;
+  class ObjCImplementationDecl;
+  class ObjCCategoryImplDecl;
+  class ObjCCategoryDecl;
+  class ObjCIvarDecl;
+  class ObjCMethodDecl;
+  class ObjCPropertyDecl;
+  class ObjCContainerDecl;
+  class FunctionProtoType;
+  class CXXBasePath;
+  class CXXBasePaths;
+  class CXXTemporary;
+  class LookupResult;
+  class InitializedEntity;
+  class InitializationKind;
+  class InitializationSequence;
+  class VisibleDeclConsumer;
+  class TargetAttributesSema;
+  class ADLResult;
+
+/// BlockSemaInfo - When a block is being parsed, this contains information
+/// about the block.  It is pointed to from Sema::CurBlock.
+struct BlockSemaInfo {
+  llvm::SmallVector<ParmVarDecl*, 8> Params;
+  bool hasPrototype;
+  bool isVariadic;
+  bool hasBlockDeclRefExprs;
+
+  BlockDecl *TheDecl;
+
+  /// TheScope - This is the scope for the block itself, which contains
+  /// arguments etc.
+  Scope *TheScope;
+
+  /// ReturnType - This will get set to block result type, by looking at
+  /// return types, if any, in the block body.
+  QualType ReturnType;
+
+  /// 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;
+
+  /// SwitchStack - This is the current set of active switch statements in the
+  /// block.
+  llvm::SmallVector<SwitchStmt*, 8> SwitchStack;
+
+  /// SavedFunctionNeedsScopeChecking - This is the value of
+  /// CurFunctionNeedsScopeChecking at the point when the block started.
+  bool SavedFunctionNeedsScopeChecking;
+
+  /// PrevBlockInfo - If this is nested inside another block, this points
+  /// to the outer block.
+  BlockSemaInfo *PrevBlockInfo;
+};
+
+/// \brief Holds a QualType and a TypeSourceInfo* that came out of a declarator
+/// parsing.
+///
+/// LocInfoType is a "transient" type, only needed for passing to/from Parser
+/// and Sema, when we want to preserve type source info for a parsed type.
+/// It will not participate in the type system semantics in any way.
+class LocInfoType : public Type {
+  enum {
+    // The last number that can fit in Type's TC.
+    // Avoids conflict with an existing Type class.
+    LocInfo = (1 << TypeClassBitSize) - 1
+  };
+
+  TypeSourceInfo *DeclInfo;
+
+  LocInfoType(QualType ty, TypeSourceInfo *TInfo)
+    : Type((TypeClass)LocInfo, ty, ty->isDependentType()), DeclInfo(TInfo) {
+    assert(getTypeClass() == (TypeClass)LocInfo && "LocInfo didn't fit in TC?");
+  }
+  friend class Sema;
+
+public:
+  QualType getType() const { return getCanonicalTypeInternal(); }
+  TypeSourceInfo *getTypeSourceInfo() const { return DeclInfo; }
+
+  virtual void getAsStringInternal(std::string &Str,
+                                   const PrintingPolicy &Policy) const;
+
+  static bool classof(const Type *T) {
+    return T->getTypeClass() == (TypeClass)LocInfo;
+  }
+  static bool classof(const LocInfoType *) { return true; }
+};
+
+/// Sema - This implements semantic analysis and AST building for C.
+class Sema : public Action {
+  Sema(const Sema&);           // DO NOT IMPLEMENT
+  void operator=(const Sema&); // DO NOT IMPLEMENT
+  mutable const TargetAttributesSema* TheTargetAttributesSema;
+public:
+  const LangOptions &LangOpts;
+  Preprocessor &PP;
+  ASTContext &Context;
+  ASTConsumer &Consumer;
+  Diagnostic &Diags;
+  SourceManager &SourceMgr;
+
+  /// \brief Source of additional semantic information.
+  ExternalSemaSource *ExternalSource;
+
+  /// \brief Code-completion consumer.
+  CodeCompleteConsumer *CodeCompleter;
+
+  /// CurContext - This is the current declaration context of parsing.
+  DeclContext *CurContext;
+
+  /// CurBlock - If inside of a block definition, this contains a pointer to
+  /// the active block object that represents it.
+  BlockSemaInfo *CurBlock;
+
+  /// PackContext - Manages the stack for #pragma pack. An alignment
+  /// of 0 indicates default alignment.
+  void *PackContext; // Really a "PragmaPackStack*"
+
+  /// FunctionLabelMap - 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.
+  ///
+  /// Note that this should always be accessed through getLabelMap() in order
+  /// to handle blocks properly.
+  llvm::DenseMap<IdentifierInfo*, LabelStmt*> FunctionLabelMap;
+
+  /// FunctionSwitchStack - This is the current set of active switch statements
+  /// in the top level function.  Clients should always use getSwitchStack() to
+  /// handle the case when they are in a block.
+  llvm::SmallVector<SwitchStmt*, 8> FunctionSwitchStack;
+
+  /// ExprTemporaries - This is the stack of temporaries that are created by
+  /// the current full expression.
+  llvm::SmallVector<CXXTemporary*, 8> ExprTemporaries;
+
+  /// CurFunctionNeedsScopeChecking - This is set to true when a function or
+  /// ObjC method body contains a VLA or an ObjC try block, which introduce
+  /// scopes that need to be checked for goto conditions.  If a function does
+  /// not contain this, then it need not have the jump checker run on it.
+  bool CurFunctionNeedsScopeChecking;
+
+  /// ExtVectorDecls - This is a list all the extended vector types. This allows
+  /// us to associate a raw vector type with one of the ext_vector type names.
+  /// This is only necessary for issuing pretty diagnostics.
+  llvm::SmallVector<TypedefDecl*, 24> ExtVectorDecls;
+
+  /// FieldCollector - Collects CXXFieldDecls during parsing of C++ classes.
+  llvm::OwningPtr<CXXFieldCollector> FieldCollector;
+
+  typedef llvm::SmallPtrSet<const CXXRecordDecl*, 8> RecordDeclSetTy;
+
+  /// PureVirtualClassDiagSet - a set of class declarations which we have
+  /// emitted a list of pure virtual functions. Used to prevent emitting the
+  /// same list more than once.
+  llvm::OwningPtr<RecordDeclSetTy> PureVirtualClassDiagSet;
+
+  /// \brief A mapping from external names to the most recent
+  /// locally-scoped external declaration with that name.
+  ///
+  /// This map contains external declarations introduced in local
+  /// scoped, e.g.,
+  ///
+  /// \code
+  /// void f() {
+  ///   void foo(int, int);
+  /// }
+  /// \endcode
+  ///
+  /// Here, the name "foo" will be associated with the declaration on
+  /// "foo" within f. This name is not visible outside of
+  /// "f". However, we still find it in two cases:
+  ///
+  ///   - If we are declaring another external with the name "foo", we
+  ///     can find "foo" as a previous declaration, so that the types
+  ///     of this external declaration can be checked for
+  ///     compatibility.
+  ///
+  ///   - If we would implicitly declare "foo" (e.g., due to a call to
+  ///     "foo" in C when no prototype or definition is visible), then
+  ///     we find this declaration of "foo" and complain that it is
+  ///     not visible.
+  llvm::DenseMap<DeclarationName, NamedDecl *> LocallyScopedExternalDecls;
+
+  /// \brief All the tentative definitions encountered in the TU.
+  std::vector<VarDecl *> TentativeDefinitions;
+
+  /// An enum describing the kind of diagnostics to use when checking
+  /// access.
+  enum AccessDiagnosticsKind {
+    /// Suppress diagnostics.
+    ADK_quiet,
+
+    /// Use the normal diagnostics.
+    ADK_normal,
+
+    /// Use the diagnostics appropriate for checking a covariant
+    /// return type.
+    ADK_covariance
+  };
+
+  class AccessedEntity {
+  public:
+    enum Kind {
+      /// A member declaration found through lookup.  The target is the
+      /// member.
+      Member,
+
+      /// A base-to-derived conversion.  The target is the base class.
+      BaseToDerivedConversion,
+
+      /// A derived-to-base conversion.  The target is the base class.
+      DerivedToBaseConversion
+    };
+
+    bool isMemberAccess() const { return K == Member; }
+
+    static AccessedEntity makeMember(CXXRecordDecl *NamingClass,
+                                     AccessSpecifier Access,
+                                     NamedDecl *Target) {
+      AccessedEntity E;
+      E.K = Member;
+      E.Access = Access;
+      E.Target = Target;
+      E.NamingClass = NamingClass;
+      return E;
+    }
+
+    static AccessedEntity makeBaseClass(bool BaseToDerived,
+                                        CXXRecordDecl *BaseClass,
+                                        CXXRecordDecl *DerivedClass,
+                                        AccessSpecifier Access) {
+      AccessedEntity E;
+      E.K = BaseToDerived ? BaseToDerivedConversion : DerivedToBaseConversion;
+      E.Access = Access;
+      E.Target = BaseClass;
+      E.NamingClass = DerivedClass;
+      return E;
+    }
+
+    Kind getKind() const { return Kind(K); }
+    AccessSpecifier getAccess() const { return AccessSpecifier(Access); }
+
+    // These apply to member decls...
+    NamedDecl *getTargetDecl() const { return Target; }
+    CXXRecordDecl *getNamingClass() const { return NamingClass; }
+
+    // ...and these apply to hierarchy conversions.
+    CXXRecordDecl *getBaseClass() const { return cast<CXXRecordDecl>(Target); }
+    CXXRecordDecl *getDerivedClass() const { return NamingClass; }
+
+  private:
+    unsigned K : 2;
+    unsigned Access : 2;
+    NamedDecl *Target;
+    CXXRecordDecl *NamingClass;    
+  };
+
+  struct DelayedDiagnostic {
+    enum DDKind { Deprecation, Access };
+
+    unsigned char Kind; // actually a DDKind
+    bool Triggered;
+
+    SourceLocation Loc;
+
+    union {
+      /// Deprecation.
+      struct { NamedDecl *Decl; } DeprecationData;
+
+      /// Access control.
+      AccessedEntity AccessData;
+    };
+
+    static DelayedDiagnostic makeDeprecation(SourceLocation Loc,
+                                             NamedDecl *D) {
+      DelayedDiagnostic DD;
+      DD.Kind = Deprecation;
+      DD.Triggered = false;
+      DD.Loc = Loc;
+      DD.DeprecationData.Decl = D;
+      return DD;
+    }
+
+    static DelayedDiagnostic makeAccess(SourceLocation Loc,
+                                        const AccessedEntity &Entity) {
+      DelayedDiagnostic DD;
+      DD.Kind = Access;
+      DD.Triggered = false;
+      DD.Loc = Loc;
+      DD.AccessData = Entity;
+      return DD;
+    }
+
+  };
+
+  /// \brief The stack of diagnostics that were delayed due to being
+  /// produced during the parsing of a declaration.
+  llvm::SmallVector<DelayedDiagnostic, 8> DelayedDiagnostics;
+
+  /// \brief The depth of the current ParsingDeclaration stack.
+  /// If nonzero, we are currently parsing a declaration (and
+  /// hence should delay deprecation warnings).
+  unsigned ParsingDeclDepth;
+
+  /// WeakUndeclaredIdentifiers - Identifiers contained in
+  /// #pragma weak before declared. rare. may alias another
+  /// identifier, declared or undeclared
+  class WeakInfo {
+    IdentifierInfo *alias;  // alias (optional)
+    SourceLocation loc;     // for diagnostics
+    bool used;              // identifier later declared?
+  public:
+    WeakInfo()
+      : alias(0), loc(SourceLocation()), used(false) {}
+    WeakInfo(IdentifierInfo *Alias, SourceLocation Loc)
+      : alias(Alias), loc(Loc), used(false) {}
+    inline IdentifierInfo * getAlias() const { return alias; }
+    inline SourceLocation getLocation() const { return loc; }
+    void setUsed(bool Used=true) { used = Used; }
+    inline bool getUsed() { return used; }
+    bool operator==(WeakInfo RHS) const {
+      return alias == RHS.getAlias() && loc == RHS.getLocation();
+    }
+    bool operator!=(WeakInfo RHS) const { return !(*this == RHS); }
+  };
+  llvm::DenseMap<IdentifierInfo*,WeakInfo> WeakUndeclaredIdentifiers;
+
+  /// WeakTopLevelDecl - Translation-unit scoped declarations generated by
+  /// #pragma weak during processing of other Decls.
+  /// I couldn't figure out a clean way to generate these in-line, so
+  /// we store them here and handle separately -- which is a hack.
+  /// It would be best to refactor this.
+  llvm::SmallVector<Decl*,2> WeakTopLevelDecl;
+
+  IdentifierResolver IdResolver;
+
+  /// Translation Unit Scope - useful to Objective-C actions that need
+  /// to lookup file scope declarations in the "ordinary" C decl namespace.
+  /// For example, user-defined classes, built-in "id" type, etc.
+  Scope *TUScope;
+
+  /// \brief The C++ "std" namespace, where the standard library resides.
+  NamespaceDecl *StdNamespace;
+
+  /// \brief The C++ "std::bad_alloc" class, which is defined by the C++
+  /// standard library.
+  CXXRecordDecl *StdBadAlloc;
+  
+  /// A flag to remember whether the implicit forms of operator new and delete
+  /// have been declared.
+  bool GlobalNewDeleteDeclared;
+
+  /// \brief The set of declarations that have been referenced within
+  /// a potentially evaluated expression.
+  typedef std::vector<std::pair<SourceLocation, Decl *> > 
+    PotentiallyReferencedDecls;
+
+  /// \brief A set of diagnostics that may be emitted.
+  typedef std::vector<std::pair<SourceLocation, PartialDiagnostic> >
+    PotentiallyEmittedDiagnostics;
+
+  /// \brief Data structure used to record current or nested
+  /// expression evaluation contexts.
+  struct ExpressionEvaluationContextRecord {
+    /// \brief The expression evaluation context.
+    ExpressionEvaluationContext Context;
+
+    /// \brief The number of temporaries that were active when we
+    /// entered this expression evaluation context.
+    unsigned NumTemporaries;
+
+    /// \brief The set of declarations referenced within a
+    /// potentially potentially-evaluated context.
+    ///
+    /// When leaving a potentially potentially-evaluated context, each
+    /// of these elements will be as referenced if the corresponding
+    /// potentially potentially evaluated expression is potentially
+    /// evaluated.
+    PotentiallyReferencedDecls *PotentiallyReferenced;
+
+    /// \brief The set of diagnostics to emit should this potentially
+    /// potentially-evaluated context become evaluated.
+    PotentiallyEmittedDiagnostics *PotentiallyDiagnosed;
+
+    ExpressionEvaluationContextRecord(ExpressionEvaluationContext Context,
+                                      unsigned NumTemporaries) 
+      : Context(Context), NumTemporaries(NumTemporaries), 
+        PotentiallyReferenced(0), PotentiallyDiagnosed(0) { }
+
+    void addReferencedDecl(SourceLocation Loc, Decl *Decl) {
+      if (!PotentiallyReferenced)
+        PotentiallyReferenced = new PotentiallyReferencedDecls;
+      PotentiallyReferenced->push_back(std::make_pair(Loc, Decl));
+    }
+
+    void addDiagnostic(SourceLocation Loc, const PartialDiagnostic &PD) {
+      if (!PotentiallyDiagnosed)
+        PotentiallyDiagnosed = new PotentiallyEmittedDiagnostics;
+      PotentiallyDiagnosed->push_back(std::make_pair(Loc, PD));
+    }
+
+    void Destroy() {
+      delete PotentiallyReferenced;
+      delete PotentiallyDiagnosed;
+      PotentiallyReferenced = 0;
+      PotentiallyDiagnosed = 0;
+    }
+  };
+
+  /// A stack of expression evaluation contexts.
+  llvm::SmallVector<ExpressionEvaluationContextRecord, 8> ExprEvalContexts;
+
+  /// \brief Whether the code handled by Sema should be considered a
+  /// complete translation unit or not.
+  ///
+  /// When true (which is generally the case), Sema will perform
+  /// end-of-translation-unit semantic tasks (such as creating
+  /// initializers for tentative definitions in C) once parsing has
+  /// completed. This flag will be false when building PCH files,
+  /// since a PCH file is by definition not a complete translation
+  /// unit.
+  bool CompleteTranslationUnit;
+
+  llvm::BumpPtrAllocator BumpAlloc;
+
+  /// \brief The number of SFINAE diagnostics that have been trapped.
+  unsigned NumSFINAEErrors;
+
+  typedef llvm::DenseMap<Selector, ObjCMethodList> MethodPool;
+
+  /// Instance/Factory Method Pools - allows efficient lookup when typechecking
+  /// messages to "id". We need to maintain a list, since selectors can have
+  /// differing signatures across classes. In Cocoa, this happens to be
+  /// extremely uncommon (only 1% of selectors are "overloaded").
+  MethodPool InstanceMethodPool;
+  MethodPool FactoryMethodPool;
+
+  MethodPool::iterator ReadMethodPool(Selector Sel, bool isInstance);
+
+  /// Private Helper predicate to check for 'self'.
+  bool isSelfExpr(Expr *RExpr);
+public:
+  Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer,
+       bool CompleteTranslationUnit = true,
+       CodeCompleteConsumer *CompletionConsumer = 0);
+  ~Sema();
+
+  const LangOptions &getLangOptions() const { return LangOpts; }
+  Diagnostic &getDiagnostics() const { return Diags; }
+  SourceManager &getSourceManager() const { return SourceMgr; }
+  const TargetAttributesSema &getTargetAttributesSema() const;
+
+  /// \brief Helper class that creates diagnostics with optional
+  /// template instantiation stacks.
+  ///
+  /// This class provides a wrapper around the basic DiagnosticBuilder
+  /// class that emits diagnostics. SemaDiagnosticBuilder is
+  /// responsible for emitting the diagnostic (as DiagnosticBuilder
+  /// does) and, if the diagnostic comes from inside a template
+  /// instantiation, printing the template instantiation stack as
+  /// well.
+  class SemaDiagnosticBuilder : public DiagnosticBuilder {
+    Sema &SemaRef;
+    unsigned DiagID;
+
+  public:
+    SemaDiagnosticBuilder(DiagnosticBuilder &DB, Sema &SemaRef, unsigned DiagID)
+      : DiagnosticBuilder(DB), SemaRef(SemaRef), DiagID(DiagID) { }
+
+    explicit SemaDiagnosticBuilder(Sema &SemaRef)
+      : DiagnosticBuilder(DiagnosticBuilder::Suppress), SemaRef(SemaRef) { }
+
+    ~SemaDiagnosticBuilder();
+  };
+
+  /// \brief Emit a diagnostic.
+  SemaDiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID) {
+    if (isSFINAEContext() && Diagnostic::isBuiltinSFINAEDiag(DiagID)) {
+      // If we encountered an error during template argument
+      // deduction, and that error is one of the SFINAE errors,
+      // suppress the diagnostic.
+      ++NumSFINAEErrors;
+      Diags.setLastDiagnosticIgnored();
+      return SemaDiagnosticBuilder(*this);
+    }
+
+    DiagnosticBuilder DB = Diags.Report(FullSourceLoc(Loc, SourceMgr), DiagID);
+    return SemaDiagnosticBuilder(DB, *this, DiagID);
+  }
+
+  /// \brief Emit a partial diagnostic.
+  SemaDiagnosticBuilder Diag(SourceLocation Loc, const PartialDiagnostic& PD);
+
+  virtual void DeleteExpr(ExprTy *E);
+  virtual void DeleteStmt(StmtTy *S);
+
+  OwningExprResult Owned(Expr* E) {
+    assert(!E || E->isRetained());
+    return OwningExprResult(*this, E);
+  }
+  OwningExprResult Owned(ExprResult R) {
+    if (R.isInvalid())
+      return ExprError();
+    assert(!R.get() || ((Expr*) R.get())->isRetained());
+    return OwningExprResult(*this, R.get());
+  }
+  OwningStmtResult Owned(Stmt* S) {
+    assert(!S || S->isRetained());
+    return OwningStmtResult(*this, S);
+  }
+
+  virtual void ActOnEndOfTranslationUnit();
+
+  /// getLabelMap() - Return the current label map.  If we're in a block, we
+  /// return it.
+  llvm::DenseMap<IdentifierInfo*, LabelStmt*> &getLabelMap() {
+    return CurBlock ? CurBlock->LabelMap : FunctionLabelMap;
+  }
+
+  /// getSwitchStack - This is returns the switch stack for the current block or
+  /// function.
+  llvm::SmallVector<SwitchStmt*,8> &getSwitchStack() {
+    return CurBlock ? CurBlock->SwitchStack : FunctionSwitchStack;
+  }
+
+  /// WeakTopLevelDeclDecls - access to #pragma weak-generated Decls
+  llvm::SmallVector<Decl*,2> &WeakTopLevelDecls() { return WeakTopLevelDecl; }
+
+  virtual void ActOnComment(SourceRange Comment);
+
+  //===--------------------------------------------------------------------===//
+  // Type Analysis / Processing: SemaType.cpp.
+  //
+
+  QualType adjustParameterType(QualType T);
+  QualType BuildPointerType(QualType T, unsigned Quals,
+                            SourceLocation Loc, DeclarationName Entity);
+  QualType BuildReferenceType(QualType T, bool LValueRef, unsigned Quals,
+                              SourceLocation Loc, DeclarationName Entity);
+  QualType BuildArrayType(QualType T, ArrayType::ArraySizeModifier ASM,
+                          Expr *ArraySize, unsigned Quals,
+                          SourceRange Brackets, DeclarationName Entity);
+  QualType BuildExtVectorType(QualType T, ExprArg ArraySize,
+                              SourceLocation AttrLoc);
+  QualType BuildFunctionType(QualType T,
+                             QualType *ParamTypes, unsigned NumParamTypes,
+                             bool Variadic, unsigned Quals,
+                             SourceLocation Loc, DeclarationName Entity);
+  QualType BuildMemberPointerType(QualType T, QualType Class,
+                                  unsigned Quals, SourceLocation Loc,
+                                  DeclarationName Entity);
+  QualType BuildBlockPointerType(QualType T, unsigned Quals,
+                                 SourceLocation Loc, DeclarationName Entity);
+  QualType GetTypeForDeclarator(Declarator &D, Scope *S,
+                                TypeSourceInfo **TInfo = 0,
+                                TagDecl **OwnedDecl = 0);
+  TypeSourceInfo *GetTypeSourceInfoForDeclarator(Declarator &D, QualType T);
+  /// \brief Create a LocInfoType to hold the given QualType and TypeSourceInfo.
+  QualType CreateLocInfoType(QualType T, TypeSourceInfo *TInfo);
+  DeclarationName GetNameForDeclarator(Declarator &D);
+  DeclarationName GetNameFromUnqualifiedId(const UnqualifiedId &Name);
+  static QualType GetTypeFromParser(TypeTy *Ty, TypeSourceInfo **TInfo = 0);
+  bool CheckSpecifiedExceptionType(QualType T, const SourceRange &Range);
+  bool CheckDistantExceptionSpec(QualType T);
+  bool CheckEquivalentExceptionSpec(
+      const FunctionProtoType *Old, SourceLocation OldLoc,
+      const FunctionProtoType *New, SourceLocation NewLoc);
+  bool CheckEquivalentExceptionSpec(
+      const PartialDiagnostic &DiagID, const PartialDiagnostic & NoteID,
+      const FunctionProtoType *Old, SourceLocation OldLoc,
+      const FunctionProtoType *New, SourceLocation NewLoc);
+  bool CheckExceptionSpecSubset(
+      const PartialDiagnostic &DiagID, const PartialDiagnostic & NoteID,
+      const FunctionProtoType *Superset, SourceLocation SuperLoc,
+      const FunctionProtoType *Subset, SourceLocation SubLoc);
+  bool CheckParamExceptionSpec(const PartialDiagnostic & NoteID,
+      const FunctionProtoType *Target, SourceLocation TargetLoc,
+      const FunctionProtoType *Source, SourceLocation SourceLoc);
+
+  bool UnwrapSimilarPointerTypes(QualType& T1, QualType& T2);
+
+  virtual TypeResult ActOnTypeName(Scope *S, Declarator &D);
+
+  bool RequireCompleteType(SourceLocation Loc, QualType T,
+                           const PartialDiagnostic &PD,
+                           std::pair<SourceLocation,
+                                     PartialDiagnostic> Note =
+                            std::make_pair(SourceLocation(), PDiag()));
+
+  QualType getQualifiedNameType(const CXXScopeSpec &SS, QualType T);
+
+  QualType BuildTypeofExprType(Expr *E);
+  QualType BuildDecltypeType(Expr *E);
+
+  //===--------------------------------------------------------------------===//
+  // Symbol table / Decl tracking callbacks: SemaDecl.cpp.
+  //
+
+  /// getDeclName - Return a pretty name for the specified decl if possible, or
+  /// an empty string if not.  This is used for pretty crash reporting.
+  virtual std::string getDeclName(DeclPtrTy D);
+
+  DeclGroupPtrTy ConvertDeclToDeclGroup(DeclPtrTy Ptr);
+
+  virtual TypeTy *getTypeName(IdentifierInfo &II, SourceLocation NameLoc,
+                              Scope *S, const CXXScopeSpec *SS,
+                              bool isClassName = false,
+                              TypeTy *ObjectType = 0);
+  virtual DeclSpec::TST isTagName(IdentifierInfo &II, Scope *S);
+  virtual bool DiagnoseUnknownTypeName(const IdentifierInfo &II, 
+                                       SourceLocation IILoc,
+                                       Scope *S,
+                                       const CXXScopeSpec *SS,
+                                       TypeTy *&SuggestedType);
+  
+  virtual DeclPtrTy ActOnDeclarator(Scope *S, Declarator &D) {
+    return HandleDeclarator(S, D, MultiTemplateParamsArg(*this), false);
+  }
+
+  DeclPtrTy HandleDeclarator(Scope *S, Declarator &D,
+                             MultiTemplateParamsArg TemplateParameterLists,
+                             bool IsFunctionDefinition);
+  void RegisterLocallyScopedExternCDecl(NamedDecl *ND,
+                                        const LookupResult &Previous,
+                                        Scope *S);
+  void DiagnoseFunctionSpecifiers(Declarator& D);
+  NamedDecl* ActOnTypedefDeclarator(Scope* S, Declarator& D, DeclContext* DC,
+                                    QualType R, TypeSourceInfo *TInfo,
+                                    LookupResult &Previous, bool &Redeclaration);
+  NamedDecl* ActOnVariableDeclarator(Scope* S, Declarator& D, DeclContext* DC,
+                                     QualType R, TypeSourceInfo *TInfo,
+                                     LookupResult &Previous,
+                                     MultiTemplateParamsArg TemplateParamLists,
+                                     bool &Redeclaration);
+  void CheckVariableDeclaration(VarDecl *NewVD, LookupResult &Previous,
+                                bool &Redeclaration);
+  NamedDecl* ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
+                                     QualType R, TypeSourceInfo *TInfo,
+                                     LookupResult &Previous,
+                                     MultiTemplateParamsArg TemplateParamLists,
+                                     bool IsFunctionDefinition,
+                                     bool &Redeclaration);
+  void AddOverriddenMethods(CXXRecordDecl *DC, CXXMethodDecl *MD);
+  void CheckFunctionDeclaration(Scope *S,
+                                FunctionDecl *NewFD, LookupResult &Previous,
+                                bool IsExplicitSpecialization,
+                                bool &Redeclaration,
+                                bool &OverloadableAttrRequired);
+  void CheckMain(FunctionDecl *FD);
+  virtual DeclPtrTy ActOnParamDeclarator(Scope *S, Declarator &D);
+  virtual void ActOnObjCCatchParam(DeclPtrTy D);
+  virtual void ActOnParamDefaultArgument(DeclPtrTy param,
+                                         SourceLocation EqualLoc,
+                                         ExprArg defarg);
+  virtual void ActOnParamUnparsedDefaultArgument(DeclPtrTy param,
+                                                 SourceLocation EqualLoc,
+                                                 SourceLocation ArgLoc);
+  virtual void ActOnParamDefaultArgumentError(DeclPtrTy param);
+  bool SetParamDefaultArgument(ParmVarDecl *Param, ExprArg DefaultArg,
+                               SourceLocation EqualLoc);
+
+
+  // Contains the locations of the beginning of unparsed default
+  // argument locations.
+  llvm::DenseMap<ParmVarDecl *,SourceLocation> UnparsedDefaultArgLocs;
+
+  virtual void AddInitializerToDecl(DeclPtrTy dcl, ExprArg init);
+  void AddInitializerToDecl(DeclPtrTy dcl, ExprArg init, bool DirectInit);
+  void ActOnUninitializedDecl(DeclPtrTy dcl, bool TypeContainsUndeducedAuto);
+  virtual void SetDeclDeleted(DeclPtrTy dcl, SourceLocation DelLoc);
+  virtual DeclGroupPtrTy FinalizeDeclaratorGroup(Scope *S, const DeclSpec &DS,
+                                                 DeclPtrTy *Group,
+                                                 unsigned NumDecls);
+  virtual void ActOnFinishKNRParamDeclarations(Scope *S, Declarator &D,
+                                               SourceLocation LocAfterDecls);
+  virtual DeclPtrTy ActOnStartOfFunctionDef(Scope *S, Declarator &D);
+  virtual DeclPtrTy ActOnStartOfFunctionDef(Scope *S, DeclPtrTy D);
+  virtual void ActOnStartOfObjCMethodDef(Scope *S, DeclPtrTy D);
+
+  virtual DeclPtrTy ActOnFinishFunctionBody(DeclPtrTy Decl, StmtArg Body);
+  DeclPtrTy ActOnFinishFunctionBody(DeclPtrTy Decl, StmtArg Body,
+                                    bool IsInstantiation);
+
+  /// \brief Diagnose any unused parameters in the given sequence of
+  /// ParmVarDecl pointers.
+  template<typename InputIterator>
+  void DiagnoseUnusedParameters(InputIterator Param, InputIterator ParamEnd) {
+    for (; Param != ParamEnd; ++Param) {
+      if (!(*Param)->isUsed() && (*Param)->getDeclName() &&
+          !(*Param)->template hasAttr<UnusedAttr>())
+        Diag((*Param)->getLocation(), diag::warn_unused_parameter)
+          << (*Param)->getDeclName();
+    }
+  }
+
+  void DiagnoseInvalidJumps(Stmt *Body);
+  virtual DeclPtrTy ActOnFileScopeAsmDecl(SourceLocation Loc, ExprArg expr);
+
+  /// Scope actions.
+  virtual void ActOnPopScope(SourceLocation Loc, Scope *S);
+  virtual void ActOnTranslationUnitScope(SourceLocation Loc, Scope *S);
+
+  /// ParsedFreeStandingDeclSpec - This method is invoked when a declspec with
+  /// no declarator (e.g. "struct foo;") is parsed.
+  virtual DeclPtrTy ParsedFreeStandingDeclSpec(Scope *S, DeclSpec &DS);
+
+  bool InjectAnonymousStructOrUnionMembers(Scope *S, DeclContext *Owner,
+                                           RecordDecl *AnonRecord);
+  virtual DeclPtrTy BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS,
+                                                RecordDecl *Record);
+
+  bool isAcceptableTagRedeclaration(const TagDecl *Previous,
+                                    TagDecl::TagKind NewTag,
+                                    SourceLocation NewTagLoc,
+                                    const IdentifierInfo &Name);
+
+  virtual DeclPtrTy ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
+                             SourceLocation KWLoc, const CXXScopeSpec &SS,
+                             IdentifierInfo *Name, SourceLocation NameLoc,
+                             AttributeList *Attr, AccessSpecifier AS,
+                             MultiTemplateParamsArg TemplateParameterLists,
+                             bool &OwnedDecl, bool &IsDependent);
+
+  virtual TypeResult ActOnDependentTag(Scope *S,
+                                       unsigned TagSpec,
+                                       TagUseKind TUK,
+                                       const CXXScopeSpec &SS,
+                                       IdentifierInfo *Name,
+                                       SourceLocation TagLoc,
+                                       SourceLocation NameLoc);
+
+  virtual void ActOnDefs(Scope *S, DeclPtrTy TagD, SourceLocation DeclStart,
+                         IdentifierInfo *ClassName,
+                         llvm::SmallVectorImpl<DeclPtrTy> &Decls);
+  virtual DeclPtrTy ActOnField(Scope *S, DeclPtrTy TagD,
+                               SourceLocation DeclStart,
+                               Declarator &D, ExprTy *BitfieldWidth);
+
+  FieldDecl *HandleField(Scope *S, RecordDecl *TagD, SourceLocation DeclStart,
+                         Declarator &D, Expr *BitfieldWidth,
+                         AccessSpecifier AS);
+
+  FieldDecl *CheckFieldDecl(DeclarationName Name, QualType T,
+                            TypeSourceInfo *TInfo,
+                            RecordDecl *Record, SourceLocation Loc,
+                            bool Mutable, Expr *BitfieldWidth,
+                            SourceLocation TSSL,
+                            AccessSpecifier AS, NamedDecl *PrevDecl,
+                            Declarator *D = 0);
+
+  enum CXXSpecialMember {
+    CXXDefaultConstructor = 0,
+    CXXCopyConstructor = 1,
+    CXXCopyAssignment = 2,
+    CXXDestructor = 3
+  };
+  void DiagnoseNontrivial(const RecordType* Record, CXXSpecialMember mem);
+
+  virtual DeclPtrTy ActOnIvar(Scope *S, SourceLocation DeclStart,
+                              DeclPtrTy IntfDecl,
+                              Declarator &D, ExprTy *BitfieldWidth,
+                              tok::ObjCKeywordKind visibility);
+
+  // This is used for both record definitions and ObjC interface declarations.
+  virtual void ActOnFields(Scope* S,
+                           SourceLocation RecLoc, DeclPtrTy TagDecl,
+                           DeclPtrTy *Fields, unsigned NumFields,
+                           SourceLocation LBrac, SourceLocation RBrac,
+                           AttributeList *AttrList);
+
+  /// ActOnTagStartDefinition - Invoked when we have entered the
+  /// scope of a tag's definition (e.g., for an enumeration, class,
+  /// struct, or union).
+  virtual void ActOnTagStartDefinition(Scope *S, DeclPtrTy TagDecl);
+
+  /// ActOnStartCXXMemberDeclarations - Invoked when we have parsed a
+  /// C++ record definition's base-specifiers clause and are starting its
+  /// member declarations.
+  virtual void ActOnStartCXXMemberDeclarations(Scope *S, DeclPtrTy TagDecl,
+                                               SourceLocation LBraceLoc);
+
+  /// ActOnTagFinishDefinition - Invoked once we have finished parsing
+  /// the definition of a tag (enumeration, class, struct, or union).
+  virtual void ActOnTagFinishDefinition(Scope *S, DeclPtrTy TagDecl,
+                                        SourceLocation RBraceLoc);
+
+  EnumConstantDecl *CheckEnumConstant(EnumDecl *Enum,
+                                      EnumConstantDecl *LastEnumConst,
+                                      SourceLocation IdLoc,
+                                      IdentifierInfo *Id,
+                                      ExprArg val);
+
+  virtual DeclPtrTy ActOnEnumConstant(Scope *S, DeclPtrTy EnumDecl,
+                                      DeclPtrTy LastEnumConstant,
+                                      SourceLocation IdLoc, IdentifierInfo *Id,
+                                      SourceLocation EqualLoc, ExprTy *Val);
+  virtual void ActOnEnumBody(SourceLocation EnumLoc, SourceLocation LBraceLoc,
+                             SourceLocation RBraceLoc, DeclPtrTy EnumDecl,
+                             DeclPtrTy *Elements, unsigned NumElements,
+                             Scope *S, AttributeList *Attr);
+
+  DeclContext *getContainingDC(DeclContext *DC);
+
+  /// Set the current declaration context until it gets popped.
+  void PushDeclContext(Scope *S, DeclContext *DC);
+  void PopDeclContext();
+
+  /// EnterDeclaratorContext - Used when we must lookup names in the context
+  /// of a declarator's nested name specifier.
+  void EnterDeclaratorContext(Scope *S, DeclContext *DC);
+  void ExitDeclaratorContext(Scope *S);
+
+  DeclContext *getFunctionLevelDeclContext();
+
+  /// getCurFunctionDecl - If inside of a function body, this returns a pointer
+  /// to the function decl for the function being parsed.  If we're currently
+  /// in a 'block', this returns the containing context.
+  FunctionDecl *getCurFunctionDecl();
+
+  /// getCurMethodDecl - If inside of a method body, this returns a pointer to
+  /// the method decl for the method being parsed.  If we're currently
+  /// in a 'block', this returns the containing context.
+  ObjCMethodDecl *getCurMethodDecl();
+
+  /// getCurFunctionOrMethodDecl - Return the Decl for the current ObjC method
+  /// or C function we're in, otherwise return null.  If we're currently
+  /// in a 'block', this returns the containing context.
+  NamedDecl *getCurFunctionOrMethodDecl();
+
+  /// Add this decl to the scope shadowed decl chains.
+  void PushOnScopeChains(NamedDecl *D, Scope *S, bool AddToContext = true);
+
+  /// isDeclInScope - If 'Ctx' is a function/method, isDeclInScope returns true
+  /// if 'D' is in Scope 'S', otherwise 'S' is ignored and isDeclInScope returns
+  /// true if 'D' belongs to the given declaration context.
+  bool isDeclInScope(NamedDecl *&D, DeclContext *Ctx, Scope *S = 0);
+
+  /// Finds the scope corresponding to the given decl context, if it
+  /// happens to be an enclosing scope.  Otherwise return NULL.
+  Scope *getScopeForDeclContext(Scope *S, DeclContext *DC) {
+    DeclContext *TargetDC = DC->getPrimaryContext();
+    do {
+      if (DeclContext *ScopeDC = (DeclContext*) S->getEntity())
+        if (ScopeDC->getPrimaryContext() == TargetDC)
+          return S;
+    } while ((S = S->getParent()));
+
+    return NULL;
+  }
+
+  /// Subroutines of ActOnDeclarator().
+  TypedefDecl *ParseTypedefDecl(Scope *S, Declarator &D, QualType T,
+                                TypeSourceInfo *TInfo);
+  void MergeTypeDefDecl(TypedefDecl *New, LookupResult &OldDecls);
+  bool MergeFunctionDecl(FunctionDecl *New, Decl *Old);
+  bool MergeCompatibleFunctionDecls(FunctionDecl *New, FunctionDecl *Old);
+  void MergeVarDecl(VarDecl *New, LookupResult &OldDecls);
+  bool MergeCXXFunctionDecl(FunctionDecl *New, FunctionDecl *Old);
+
+  // AssignmentAction - This is used by all the assignment diagnostic functions
+  // to represent what is actually causing the operation
+  enum AssignmentAction {
+    AA_Assigning,
+    AA_Passing,
+    AA_Returning,
+    AA_Converting,
+    AA_Initializing,
+    AA_Sending,
+    AA_Casting
+  };
+  
+  /// C++ Overloading.
+  enum OverloadKind {
+    /// This is a legitimate overload: the existing declarations are
+    /// functions or function templates with different signatures.
+    Ovl_Overload,
+
+    /// This is not an overload because the signature exactly matches
+    /// an existing declaration.
+    Ovl_Match,
+
+    /// This is not an overload because the lookup results contain a
+    /// non-function.
+    Ovl_NonFunction
+  };
+  OverloadKind CheckOverload(FunctionDecl *New,
+                             const LookupResult &OldDecls,
+                             NamedDecl *&OldDecl);
+  bool IsOverload(FunctionDecl *New, FunctionDecl *Old);
+
+  ImplicitConversionSequence
+  TryImplicitConversion(Expr* From, QualType ToType,
+                        bool SuppressUserConversions,
+                        bool AllowExplicit,
+                        bool ForceRValue,
+                        bool InOverloadResolution,
+                        bool UserCast = false);
+  bool IsStandardConversion(Expr *From, QualType ToType,
+                            bool InOverloadResolution,
+                            StandardConversionSequence& SCS);
+  bool IsIntegralPromotion(Expr *From, QualType FromType, QualType ToType);
+  bool IsFloatingPointPromotion(QualType FromType, QualType ToType);
+  bool IsComplexPromotion(QualType FromType, QualType ToType);
+  bool IsPointerConversion(Expr *From, QualType FromType, QualType ToType,
+                           bool InOverloadResolution,
+                           QualType& ConvertedType, bool &IncompatibleObjC);
+  bool isObjCPointerConversion(QualType FromType, QualType ToType,
+                               QualType& ConvertedType, bool &IncompatibleObjC);
+  bool CheckPointerConversion(Expr *From, QualType ToType,
+                              CastExpr::CastKind &Kind,
+                              bool IgnoreBaseAccess);
+  bool IsMemberPointerConversion(Expr *From, QualType FromType, QualType ToType,
+                                 bool InOverloadResolution,
+                                 QualType &ConvertedType);
+  bool CheckMemberPointerConversion(Expr *From, QualType ToType,
+                                    CastExpr::CastKind &Kind,
+                                    bool IgnoreBaseAccess);
+  bool IsQualificationConversion(QualType FromType, QualType ToType);
+  OverloadingResult IsUserDefinedConversion(Expr *From, QualType ToType,
+                               UserDefinedConversionSequence& User,
+                               OverloadCandidateSet& Conversions,
+                               bool AllowConversionFunctions,
+                               bool AllowExplicit, bool ForceRValue,
+                               bool UserCast = false);
+  bool DiagnoseMultipleUserDefinedConversion(Expr *From, QualType ToType);
+                                              
+
+  ImplicitConversionSequence::CompareKind
+  CompareImplicitConversionSequences(const ImplicitConversionSequence& ICS1,
+                                     const ImplicitConversionSequence& ICS2);
+
+  ImplicitConversionSequence::CompareKind
+  CompareStandardConversionSequences(const StandardConversionSequence& SCS1,
+                                     const StandardConversionSequence& SCS2);
+
+  ImplicitConversionSequence::CompareKind
+  CompareQualificationConversions(const StandardConversionSequence& SCS1,
+                                  const StandardConversionSequence& SCS2);
+
+  ImplicitConversionSequence::CompareKind
+  CompareDerivedToBaseConversions(const StandardConversionSequence& SCS1,
+                                  const StandardConversionSequence& SCS2);
+
+  ImplicitConversionSequence
+  TryCopyInitialization(Expr* From, QualType ToType,
+                        bool SuppressUserConversions, bool ForceRValue,
+                        bool InOverloadResolution);
+  
+  bool PerformCopyInitialization(Expr *&From, QualType ToType,
+                                 AssignmentAction Action, bool Elidable = false);
+
+  OwningExprResult PerformCopyInitialization(const InitializedEntity &Entity,
+                                             SourceLocation EqualLoc,
+                                             OwningExprResult Init);
+  ImplicitConversionSequence
+  TryObjectArgumentInitialization(QualType FromType, CXXMethodDecl *Method,
+                                  CXXRecordDecl *ActingContext);
+  bool PerformObjectArgumentInitialization(Expr *&From, CXXMethodDecl *Method);
+
+  ImplicitConversionSequence TryContextuallyConvertToBool(Expr *From);
+  bool PerformContextuallyConvertToBool(Expr *&From);
+
+  bool PerformObjectMemberConversion(Expr *&From, NamedDecl *Member);
+
+  // Members have to be NamespaceDecl* or TranslationUnitDecl*.
+  // TODO: make this is a typesafe union.
+  typedef llvm::SmallPtrSet<DeclContext   *, 16> AssociatedNamespaceSet;
+  typedef llvm::SmallPtrSet<CXXRecordDecl *, 16> AssociatedClassSet;
+
+  void AddOverloadCandidate(NamedDecl *Function,
+                            AccessSpecifier Access,
+                            Expr **Args, unsigned NumArgs,
+                            OverloadCandidateSet &CandidateSet);
+
+  void AddOverloadCandidate(FunctionDecl *Function,
+                            AccessSpecifier Access,
+                            Expr **Args, unsigned NumArgs,
+                            OverloadCandidateSet& CandidateSet,
+                            bool SuppressUserConversions = false,
+                            bool ForceRValue = false,
+                            bool PartialOverloading = false);
+  void AddFunctionCandidates(const UnresolvedSetImpl &Functions,
+                             Expr **Args, unsigned NumArgs,
+                             OverloadCandidateSet& CandidateSet,
+                             bool SuppressUserConversions = false);
+  void AddMethodCandidate(NamedDecl *Decl, AccessSpecifier Access,
+                          QualType ObjectType,
+                          Expr **Args, unsigned NumArgs,
+                          OverloadCandidateSet& CandidateSet,
+                          bool SuppressUserConversion = false,
+                          bool ForceRValue = false);
+  void AddMethodCandidate(CXXMethodDecl *Method, AccessSpecifier Access,
+                          CXXRecordDecl *ActingContext, QualType ObjectType,
+                          Expr **Args, unsigned NumArgs,
+                          OverloadCandidateSet& CandidateSet,
+                          bool SuppressUserConversions = false,
+                          bool ForceRValue = false);
+  void AddMethodTemplateCandidate(FunctionTemplateDecl *MethodTmpl,
+                                  AccessSpecifier Access,
+                                  CXXRecordDecl *ActingContext,
+                         const TemplateArgumentListInfo *ExplicitTemplateArgs,
+                                  QualType ObjectType,
+                                  Expr **Args, unsigned NumArgs,
+                                  OverloadCandidateSet& CandidateSet,
+                                  bool SuppressUserConversions = false,
+                                  bool ForceRValue = false);
+  void AddTemplateOverloadCandidate(FunctionTemplateDecl *FunctionTemplate,
+                                    AccessSpecifier Access,
+                      const TemplateArgumentListInfo *ExplicitTemplateArgs,
+                                    Expr **Args, unsigned NumArgs,
+                                    OverloadCandidateSet& CandidateSet,
+                                    bool SuppressUserConversions = false,
+                                    bool ForceRValue = false);
+  void AddConversionCandidate(CXXConversionDecl *Conversion,
+                              AccessSpecifier Access,
+                              CXXRecordDecl *ActingContext,
+                              Expr *From, QualType ToType,
+                              OverloadCandidateSet& CandidateSet);
+  void AddTemplateConversionCandidate(FunctionTemplateDecl *FunctionTemplate,
+                                      AccessSpecifier Access,
+                                      CXXRecordDecl *ActingContext,
+                                      Expr *From, QualType ToType,
+                                      OverloadCandidateSet &CandidateSet);
+  void AddSurrogateCandidate(CXXConversionDecl *Conversion,
+                             AccessSpecifier Access,
+                             CXXRecordDecl *ActingContext,
+                             const FunctionProtoType *Proto,
+                             QualType ObjectTy, Expr **Args, unsigned NumArgs,
+                             OverloadCandidateSet& CandidateSet);
+  void AddOperatorCandidates(OverloadedOperatorKind Op, Scope *S,
+                             SourceLocation OpLoc,
+                             Expr **Args, unsigned NumArgs,
+                             OverloadCandidateSet& CandidateSet,
+                             SourceRange OpRange = SourceRange());
+  void AddMemberOperatorCandidates(OverloadedOperatorKind Op,
+                                   SourceLocation OpLoc,
+                                   Expr **Args, unsigned NumArgs,
+                                   OverloadCandidateSet& CandidateSet,
+                                   SourceRange OpRange = SourceRange());
+  void AddBuiltinCandidate(QualType ResultTy, QualType *ParamTys,
+                           Expr **Args, unsigned NumArgs,
+                           OverloadCandidateSet& CandidateSet,
+                           bool IsAssignmentOperator = false,
+                           unsigned NumContextualBoolArguments = 0);
+  void AddBuiltinOperatorCandidates(OverloadedOperatorKind Op,
+                                    SourceLocation OpLoc,
+                                    Expr **Args, unsigned NumArgs,
+                                    OverloadCandidateSet& CandidateSet);
+  void AddArgumentDependentLookupCandidates(DeclarationName Name,
+                                            bool Operator,
+                                            Expr **Args, unsigned NumArgs,
+                        const TemplateArgumentListInfo *ExplicitTemplateArgs,
+                                            OverloadCandidateSet& CandidateSet,
+                                            bool PartialOverloading = false);
+  bool isBetterOverloadCandidate(const OverloadCandidate& Cand1,
+                                 const OverloadCandidate& Cand2,
+                                 SourceLocation Loc);
+  OverloadingResult BestViableFunction(OverloadCandidateSet& CandidateSet,
+                                       SourceLocation Loc,
+                                       OverloadCandidateSet::iterator& Best);
+
+  enum OverloadCandidateDisplayKind {
+    /// Requests that all candidates be shown.  Viable candidates will
+    /// be printed first.
+    OCD_AllCandidates,
+
+    /// Requests that only viable candidates be shown.
+    OCD_ViableCandidates
+  };
+  void PrintOverloadCandidates(OverloadCandidateSet& CandidateSet,
+                               OverloadCandidateDisplayKind OCD,
+                               Expr **Args, unsigned NumArgs,
+                               const char *Opc = 0,
+                               SourceLocation Loc = SourceLocation());
+
+  void NoteOverloadCandidate(FunctionDecl *Fn);
+  void DiagnoseAmbiguousConversion(const ImplicitConversionSequence &ICS,
+                                   SourceLocation CaretLoc,
+                                   const PartialDiagnostic &PDiag);
+
+  FunctionDecl *ResolveAddressOfOverloadedFunction(Expr *From, QualType ToType,
+                                                   bool Complain);
+  FunctionDecl *ResolveSingleFunctionTemplateSpecialization(Expr *From);
+
+  Expr *FixOverloadedFunctionReference(Expr *E, FunctionDecl *Fn);
+  OwningExprResult FixOverloadedFunctionReference(OwningExprResult, 
+                                                  FunctionDecl *Fn);
+
+  void AddOverloadedCallCandidates(UnresolvedLookupExpr *ULE,
+                                   Expr **Args, unsigned NumArgs,
+                                   OverloadCandidateSet &CandidateSet,
+                                   bool PartialOverloading = false);
+    
+  OwningExprResult BuildOverloadedCallExpr(Expr *Fn,
+                                           UnresolvedLookupExpr *ULE,
+                                           SourceLocation LParenLoc,
+                                           Expr **Args, unsigned NumArgs,
+                                           SourceLocation *CommaLocs,
+                                           SourceLocation RParenLoc);
+
+  OwningExprResult CreateOverloadedUnaryOp(SourceLocation OpLoc,
+                                           unsigned Opc,
+                                           const UnresolvedSetImpl &Fns,
+                                           ExprArg input);
+
+  OwningExprResult CreateOverloadedBinOp(SourceLocation OpLoc,
+                                         unsigned Opc,
+                                         const UnresolvedSetImpl &Fns,
+                                         Expr *LHS, Expr *RHS);
+
+  OwningExprResult CreateOverloadedArraySubscriptExpr(SourceLocation LLoc,
+                                                      SourceLocation RLoc,
+                                                      ExprArg Base,ExprArg Idx);
+
+  OwningExprResult
+  BuildCallToMemberFunction(Scope *S, Expr *MemExpr,
+                            SourceLocation LParenLoc, Expr **Args,
+                            unsigned NumArgs, SourceLocation *CommaLocs,
+                            SourceLocation RParenLoc);
+  ExprResult
+  BuildCallToObjectOfClassType(Scope *S, Expr *Object, SourceLocation LParenLoc,
+                               Expr **Args, unsigned NumArgs,
+                               SourceLocation *CommaLocs,
+                               SourceLocation RParenLoc);
+
+  OwningExprResult BuildOverloadedArrowExpr(Scope *S, ExprArg Base,
+                                            SourceLocation OpLoc);
+
+  /// CheckUnreachable - Check for unreachable code.
+  void CheckUnreachable(AnalysisContext &);
+
+  /// CheckCallReturnType - Checks that a call expression's return type is
+  /// complete. Returns true on failure. The location passed in is the location
+  /// that best represents the call.
+  bool CheckCallReturnType(QualType ReturnType, SourceLocation Loc,
+                           CallExpr *CE, FunctionDecl *FD);
+                           
+  /// Helpers for dealing with blocks and functions.
+  void CheckFallThroughForFunctionDef(Decl *D, Stmt *Body, AnalysisContext &);
+  void CheckFallThroughForBlock(QualType BlockTy, Stmt *, AnalysisContext &);
+  bool CheckParmsForFunctionDef(FunctionDecl *FD);
+  void CheckCXXDefaultArguments(FunctionDecl *FD);
+  void CheckExtraCXXDefaultArguments(Declarator &D);
+  enum ControlFlowKind { NeverFallThrough = 0, MaybeFallThrough = 1,
+                         AlwaysFallThrough = 2, NeverFallThroughOrReturn = 3 };
+  ControlFlowKind CheckFallThrough(AnalysisContext &);
+
+  Scope *getNonFieldDeclScope(Scope *S);
+
+  /// \name Name lookup
+  ///
+  /// These routines provide name lookup that is used during semantic
+  /// analysis to resolve the various kinds of names (identifiers,
+  /// overloaded operator names, constructor names, etc.) into zero or
+  /// more declarations within a particular scope. The major entry
+  /// points are LookupName, which performs unqualified name lookup,
+  /// and LookupQualifiedName, which performs qualified name lookup.
+  ///
+  /// All name lookup is performed based on some specific criteria,
+  /// which specify what names will be visible to name lookup and how
+  /// far name lookup should work. These criteria are important both
+  /// for capturing language semantics (certain lookups will ignore
+  /// certain names, for example) and for performance, since name
+  /// lookup is often a bottleneck in the compilation of C++. Name
+  /// lookup criteria is specified via the LookupCriteria enumeration.
+  ///
+  /// The results of name lookup can vary based on the kind of name
+  /// lookup performed, the current language, and the translation
+  /// unit. In C, for example, name lookup will either return nothing
+  /// (no entity found) or a single declaration. In C++, name lookup
+  /// can additionally refer to a set of overloaded functions or
+  /// result in an ambiguity. All of the possible results of name
+  /// lookup are captured by the LookupResult class, which provides
+  /// the ability to distinguish among them.
+  //@{
+
+  /// @brief Describes the kind of name lookup to perform.
+  enum LookupNameKind {
+    /// Ordinary name lookup, which finds ordinary names (functions,
+    /// variables, typedefs, etc.) in C and most kinds of names
+    /// (functions, variables, members, types, etc.) in C++.
+    LookupOrdinaryName = 0,
+    /// Tag name lookup, which finds the names of enums, classes,
+    /// structs, and unions.
+    LookupTagName,
+    /// Member name lookup, which finds the names of
+    /// class/struct/union members.
+    LookupMemberName,
+    // Look up of an operator name (e.g., operator+) for use with
+    // operator overloading. This lookup is similar to ordinary name
+    // lookup, but will ignore any declarations that are class
+    // members.
+    LookupOperatorName,
+    /// Look up of a name that precedes the '::' scope resolution
+    /// operator in C++. This lookup completely ignores operator, object,
+    /// function, and enumerator names (C++ [basic.lookup.qual]p1).
+    LookupNestedNameSpecifierName,
+    /// Look up a namespace name within a C++ using directive or
+    /// namespace alias definition, ignoring non-namespace names (C++
+    /// [basic.lookup.udir]p1).
+    LookupNamespaceName,
+    /// Look up all declarations in a scope with the given name,
+    /// including resolved using declarations.  This is appropriate
+    /// for checking redeclarations for a using declaration.
+    LookupUsingDeclName,
+    /// Look up an ordinary name that is going to be redeclared as a
+    /// name with linkage. This lookup ignores any declarations that
+    /// are outside of the current scope unless they have linkage. See
+    /// C99 6.2.2p4-5 and C++ [basic.link]p6.
+    LookupRedeclarationWithLinkage,
+    /// Look up the name of an Objective-C protocol.
+    LookupObjCProtocolName,
+    /// Look up the name of an Objective-C implementation
+    LookupObjCImplementationName
+  };
+
+  /// \brief Specifies whether (or how) name lookup is being performed for a
+  /// redeclaration (vs. a reference).
+  enum RedeclarationKind {
+    /// \brief The lookup is a reference to this name that is not for the
+    /// purpose of redeclaring the name.
+    NotForRedeclaration = 0,
+    /// \brief The lookup results will be used for redeclaration of a name,
+    /// if an entity by that name already exists.
+    ForRedeclaration
+  };
+
+private:
+  bool CppLookupName(LookupResult &R, Scope *S);
+
+public:
+  /// \brief Look up a name, looking for a single declaration.  Return
+  /// null if the results were absent, ambiguous, or overloaded.
+  ///
+  /// It is preferable to use the elaborated form and explicitly handle
+  /// ambiguity and overloaded.
+  NamedDecl *LookupSingleName(Scope *S, DeclarationName Name,
+                              LookupNameKind NameKind,
+                              RedeclarationKind Redecl
+                                = NotForRedeclaration);
+  bool LookupName(LookupResult &R, Scope *S,
+                  bool AllowBuiltinCreation = false);
+  bool LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx,
+                           bool InUnqualifiedLookup = false);
+  bool LookupParsedName(LookupResult &R, Scope *S, const CXXScopeSpec *SS,
+                        bool AllowBuiltinCreation = false,
+                        bool EnteringContext = false);
+
+  ObjCProtocolDecl *LookupProtocol(IdentifierInfo *II);
+
+  void LookupOverloadedOperatorName(OverloadedOperatorKind Op, Scope *S,
+                                    QualType T1, QualType T2,
+                                    UnresolvedSetImpl &Functions);
+  
+  void ArgumentDependentLookup(DeclarationName Name, bool Operator,
+                               Expr **Args, unsigned NumArgs,
+                               ADLResult &Functions);
+
+  void LookupVisibleDecls(Scope *S, LookupNameKind Kind,
+                          VisibleDeclConsumer &Consumer);
+  void LookupVisibleDecls(DeclContext *Ctx, LookupNameKind Kind,
+                          VisibleDeclConsumer &Consumer);
+
+  bool CorrectTypo(LookupResult &R, Scope *S, const CXXScopeSpec *SS,
+                   DeclContext *MemberContext = 0,
+                   bool EnteringContext = false,
+                   const ObjCObjectPointerType *OPT = 0);
+
+  void FindAssociatedClassesAndNamespaces(Expr **Args, unsigned NumArgs,
+                                   AssociatedNamespaceSet &AssociatedNamespaces,
+                                   AssociatedClassSet &AssociatedClasses);
+
+  bool DiagnoseAmbiguousLookup(LookupResult &Result);
+  //@}
+
+  ObjCInterfaceDecl *getObjCInterfaceDecl(IdentifierInfo *&Id,
+                                 SourceLocation RecoverLoc = SourceLocation());
+  NamedDecl *LazilyCreateBuiltin(IdentifierInfo *II, unsigned ID,
+                                 Scope *S, bool ForRedeclaration,
+                                 SourceLocation Loc);
+  NamedDecl *ImplicitlyDefineFunction(SourceLocation Loc, IdentifierInfo &II,
+                                      Scope *S);
+  void AddKnownFunctionAttributes(FunctionDecl *FD);
+
+  // More parsing and symbol table subroutines.
+
+  // Decl attributes - this routine is the top level dispatcher.
+  void ProcessDeclAttributes(Scope *S, Decl *D, const Declarator &PD);
+  void ProcessDeclAttributeList(Scope *S, Decl *D, const AttributeList *AttrList);
+
+  void WarnUndefinedMethod(SourceLocation ImpLoc, ObjCMethodDecl *method,
+                           bool &IncompleteImpl);
+  void WarnConflictingTypedMethods(ObjCMethodDecl *ImpMethod,
+                                   ObjCMethodDecl *IntfMethod);
+
+  bool isPropertyReadonly(ObjCPropertyDecl *PropertyDecl,
+                          ObjCInterfaceDecl *IDecl);
+
+  /// CheckProtocolMethodDefs - This routine checks unimplemented
+  /// methods declared in protocol, and those referenced by it.
+  /// \param IDecl - Used for checking for methods which may have been
+  /// inherited.
+  void CheckProtocolMethodDefs(SourceLocation ImpLoc,
+                               ObjCProtocolDecl *PDecl,
+                               bool& IncompleteImpl,
+                               const llvm::DenseSet<Selector> &InsMap,
+                               const llvm::DenseSet<Selector> &ClsMap,
+                               ObjCInterfaceDecl *IDecl);
+
+  /// CheckImplementationIvars - This routine checks if the instance variables
+  /// listed in the implelementation match those listed in the interface.
+  void CheckImplementationIvars(ObjCImplementationDecl *ImpDecl,
+                                ObjCIvarDecl **Fields, unsigned nIvars,
+                                SourceLocation Loc);
+
+  /// ImplMethodsVsClassMethods - This is main routine to warn if any method
+  /// remains unimplemented in the class or category @implementation.
+  void ImplMethodsVsClassMethods(ObjCImplDecl* IMPDecl,
+                                 ObjCContainerDecl* IDecl,
+                                 bool IncompleteImpl = false);
+  
+  /// DiagnoseUnimplementedProperties - This routine warns on those properties
+  /// which must be implemented by this implementation.
+  void DiagnoseUnimplementedProperties(ObjCImplDecl* IMPDecl,
+                                       ObjCContainerDecl *CDecl,
+                                       const llvm::DenseSet<Selector>& InsMap);
+  
+  /// CollectImmediateProperties - This routine collects all properties in
+  /// the class and its conforming protocols; but not those it its super class.
+  void CollectImmediateProperties(ObjCContainerDecl *CDecl,
+                  llvm::DenseMap<IdentifierInfo *, ObjCPropertyDecl*>& PropMap);
+  
+  /// LookupPropertyDecl - Looks up a property in the current class and all
+  /// its protocols.
+  ObjCPropertyDecl *LookupPropertyDecl(const ObjCContainerDecl *CDecl, 
+                                       IdentifierInfo *II);
+  
+  ObjCIvarDecl *SynthesizeNewPropertyIvar(ObjCInterfaceDecl *IDecl,
+                                          IdentifierInfo *NameII);
+  
+  /// AtomicPropertySetterGetterRules - This routine enforces the rule (via
+  /// warning) when atomic property has one but not the other user-declared
+  /// setter or getter.
+  void AtomicPropertySetterGetterRules(ObjCImplDecl* IMPDecl,
+                                       ObjCContainerDecl* IDecl);
+
+  /// MatchTwoMethodDeclarations - Checks if two methods' type match and returns
+  /// true, or false, accordingly.
+  bool MatchTwoMethodDeclarations(const ObjCMethodDecl *Method,
+                                  const ObjCMethodDecl *PrevMethod,
+                                  bool matchBasedOnSizeAndAlignment = false);
+
+  /// MatchAllMethodDeclarations - Check methods declaraed in interface or
+  /// or protocol against those declared in their implementations.
+  void MatchAllMethodDeclarations(const llvm::DenseSet<Selector> &InsMap,
+                                  const llvm::DenseSet<Selector> &ClsMap,
+                                  llvm::DenseSet<Selector> &InsMapSeen,
+                                  llvm::DenseSet<Selector> &ClsMapSeen,
+                                  ObjCImplDecl* IMPDecl,
+                                  ObjCContainerDecl* IDecl,
+                                  bool &IncompleteImpl,
+                                  bool ImmediateClass);
+
+  /// AddInstanceMethodToGlobalPool - All instance methods in a translation
+  /// unit are added to a global pool. This allows us to efficiently associate
+  /// a selector with a method declaraation for purposes of typechecking
+  /// messages sent to "id" (where the class of the object is unknown).
+  void AddInstanceMethodToGlobalPool(ObjCMethodDecl *Method);
+
+  /// LookupInstanceMethodInGlobalPool - Returns the method and warns if
+  /// there are multiple signatures.
+  ObjCMethodDecl *LookupInstanceMethodInGlobalPool(Selector Sel, SourceRange R,
+                                                   bool warn=true);
+
+  /// LookupFactoryMethodInGlobalPool - Returns the method and warns if
+  /// there are multiple signatures.
+  ObjCMethodDecl *LookupFactoryMethodInGlobalPool(Selector Sel, SourceRange R);
+
+  /// AddFactoryMethodToGlobalPool - Same as above, but for factory methods.
+  void AddFactoryMethodToGlobalPool(ObjCMethodDecl *Method);
+  //===--------------------------------------------------------------------===//
+  // Statement Parsing Callbacks: SemaStmt.cpp.
+public:
+  virtual OwningStmtResult ActOnExprStmt(FullExprArg Expr);
+
+  virtual OwningStmtResult ActOnNullStmt(SourceLocation SemiLoc);
+  virtual OwningStmtResult ActOnCompoundStmt(SourceLocation L, SourceLocation R,
+                                             MultiStmtArg Elts,
+                                             bool isStmtExpr);
+  virtual OwningStmtResult ActOnDeclStmt(DeclGroupPtrTy Decl,
+                                         SourceLocation StartLoc,
+                                         SourceLocation EndLoc);
+  virtual void ActOnForEachDeclStmt(DeclGroupPtrTy Decl);
+  virtual OwningStmtResult ActOnCaseStmt(SourceLocation CaseLoc, ExprArg LHSVal,
+                                    SourceLocation DotDotDotLoc, ExprArg RHSVal,
+                                    SourceLocation ColonLoc);
+  virtual void ActOnCaseStmtBody(StmtTy *CaseStmt, StmtArg SubStmt);
+
+  virtual OwningStmtResult ActOnDefaultStmt(SourceLocation DefaultLoc,
+                                            SourceLocation ColonLoc,
+                                            StmtArg SubStmt, Scope *CurScope);
+  virtual OwningStmtResult ActOnLabelStmt(SourceLocation IdentLoc,
+                                          IdentifierInfo *II,
+                                          SourceLocation ColonLoc,
+                                          StmtArg SubStmt);
+  virtual OwningStmtResult ActOnIfStmt(SourceLocation IfLoc,
+                                       FullExprArg CondVal, DeclPtrTy CondVar,
+                                       StmtArg ThenVal,
+                                       SourceLocation ElseLoc, StmtArg ElseVal);
+  virtual OwningStmtResult ActOnStartOfSwitchStmt(FullExprArg Cond, 
+                                                  DeclPtrTy CondVar);
+  virtual void ActOnSwitchBodyError(SourceLocation SwitchLoc, StmtArg Switch,
+                                    StmtArg Body);
+  virtual OwningStmtResult ActOnFinishSwitchStmt(SourceLocation SwitchLoc,
+                                                 StmtArg Switch, StmtArg Body);
+  virtual OwningStmtResult ActOnWhileStmt(SourceLocation WhileLoc,
+                                          FullExprArg Cond,
+                                          DeclPtrTy CondVar, StmtArg Body);
+  virtual OwningStmtResult ActOnDoStmt(SourceLocation DoLoc, StmtArg Body,
+                                       SourceLocation WhileLoc,
+                                       SourceLocation CondLParen, ExprArg Cond,
+                                       SourceLocation CondRParen);
+
+  virtual OwningStmtResult ActOnForStmt(SourceLocation ForLoc,
+                                        SourceLocation LParenLoc,
+                                        StmtArg First, FullExprArg Second,
+                                        DeclPtrTy SecondVar,
+                                        FullExprArg Third, 
+                                        SourceLocation RParenLoc,
+                                        StmtArg Body);
+  virtual OwningStmtResult ActOnObjCForCollectionStmt(SourceLocation ForColLoc,
+                                       SourceLocation LParenLoc,
+                                       StmtArg First, ExprArg Second,
+                                       SourceLocation RParenLoc, StmtArg Body);
+
+  virtual OwningStmtResult ActOnGotoStmt(SourceLocation GotoLoc,
+                                         SourceLocation LabelLoc,
+                                         IdentifierInfo *LabelII);
+  virtual OwningStmtResult ActOnIndirectGotoStmt(SourceLocation GotoLoc,
+                                                 SourceLocation StarLoc,
+                                                 ExprArg DestExp);
+  virtual OwningStmtResult ActOnContinueStmt(SourceLocation ContinueLoc,
+                                             Scope *CurScope);
+  virtual OwningStmtResult ActOnBreakStmt(SourceLocation GotoLoc,
+                                          Scope *CurScope);
+
+  virtual OwningStmtResult ActOnReturnStmt(SourceLocation ReturnLoc,
+                                           ExprArg RetValExp);
+  OwningStmtResult ActOnBlockReturnStmt(SourceLocation ReturnLoc,
+                                        Expr *RetValExp);
+
+  virtual OwningStmtResult ActOnAsmStmt(SourceLocation AsmLoc,
+                                        bool IsSimple,
+                                        bool IsVolatile,
+                                        unsigned NumOutputs,
+                                        unsigned NumInputs,
+                                        IdentifierInfo **Names,
+                                        MultiExprArg Constraints,
+                                        MultiExprArg Exprs,
+                                        ExprArg AsmString,
+                                        MultiExprArg Clobbers,
+                                        SourceLocation RParenLoc,
+                                        bool MSAsm = false);
+
+  virtual OwningStmtResult ActOnObjCAtCatchStmt(SourceLocation AtLoc,
+                                                SourceLocation RParen,
+                                                DeclPtrTy Parm, StmtArg Body,
+                                                StmtArg CatchList);
+
+  virtual OwningStmtResult ActOnObjCAtFinallyStmt(SourceLocation AtLoc,
+                                                  StmtArg Body);
+
+  virtual OwningStmtResult ActOnObjCAtTryStmt(SourceLocation AtLoc,
+                                              StmtArg Try,
+                                              StmtArg Catch, StmtArg Finally);
+
+  virtual OwningStmtResult ActOnObjCAtThrowStmt(SourceLocation AtLoc,
+                                                ExprArg Throw,
+                                                Scope *CurScope);
+  virtual OwningStmtResult ActOnObjCAtSynchronizedStmt(SourceLocation AtLoc,
+                                                       ExprArg SynchExpr,
+                                                       StmtArg SynchBody);
+
+  VarDecl *BuildExceptionDeclaration(Scope *S, QualType ExDeclType,
+                                     TypeSourceInfo *TInfo,
+                                     IdentifierInfo *Name,
+                                     SourceLocation Loc,
+                                     SourceRange Range);
+  virtual DeclPtrTy ActOnExceptionDeclarator(Scope *S, Declarator &D);
+
+  virtual OwningStmtResult ActOnCXXCatchBlock(SourceLocation CatchLoc,
+                                              DeclPtrTy ExDecl,
+                                              StmtArg HandlerBlock);
+  virtual OwningStmtResult ActOnCXXTryBlock(SourceLocation TryLoc,
+                                            StmtArg TryBlock,
+                                            MultiStmtArg Handlers);
+  void DiagnoseReturnInConstructorExceptionHandler(CXXTryStmt *TryBlock);
+
+  /// DiagnoseUnusedExprResult - If the statement passed in is an expression
+  /// whose result is unused, warn.
+  void DiagnoseUnusedExprResult(const Stmt *S);
+
+  ParsingDeclStackState PushParsingDeclaration();
+  void PopParsingDeclaration(ParsingDeclStackState S, DeclPtrTy D);
+  void EmitDeprecationWarning(NamedDecl *D, SourceLocation Loc);
+
+  void HandleDelayedDeprecationCheck(DelayedDiagnostic &DD, Decl *Ctx);
+
+  //===--------------------------------------------------------------------===//
+  // Expression Parsing Callbacks: SemaExpr.cpp.
+
+  bool DiagnoseUseOfDecl(NamedDecl *D, SourceLocation Loc);
+  bool DiagnosePropertyAccessorMismatch(ObjCPropertyDecl *PD,
+                                        ObjCMethodDecl *Getter,
+                                        SourceLocation Loc);
+  void DiagnoseSentinelCalls(NamedDecl *D, SourceLocation Loc,
+                             Expr **Args, unsigned NumArgs);
+
+  virtual void
+  PushExpressionEvaluationContext(ExpressionEvaluationContext NewContext);
+
+  virtual void PopExpressionEvaluationContext();
+
+  void MarkDeclarationReferenced(SourceLocation Loc, Decl *D);
+  bool DiagRuntimeBehavior(SourceLocation Loc, const PartialDiagnostic &PD);
+  
+  // Primary Expressions.
+  virtual SourceRange getExprRange(ExprTy *E) const;
+
+  virtual OwningExprResult ActOnIdExpression(Scope *S,
+                                             const CXXScopeSpec &SS,
+                                             UnqualifiedId &Name,
+                                             bool HasTrailingLParen,
+                                             bool IsAddressOfOperand);
+
+  bool DiagnoseEmptyLookup(Scope *S, const CXXScopeSpec &SS, LookupResult &R);
+
+  OwningExprResult LookupInObjCMethod(LookupResult &R,
+                                      Scope *S,
+                                      IdentifierInfo *II,
+                                      bool AllowBuiltinCreation=false);
+
+  OwningExprResult ActOnDependentIdExpression(const CXXScopeSpec &SS,
+                                              DeclarationName Name,
+                                              SourceLocation NameLoc,
+                                              bool isAddressOfOperand,
+                                const TemplateArgumentListInfo *TemplateArgs);
+  
+  OwningExprResult BuildDeclRefExpr(ValueDecl *D, QualType Ty,
+                                    SourceLocation Loc,
+                                    const CXXScopeSpec *SS = 0);
+  VarDecl *BuildAnonymousStructUnionMemberPath(FieldDecl *Field,
+                                    llvm::SmallVectorImpl<FieldDecl *> &Path);
+  OwningExprResult
+  BuildAnonymousStructUnionMemberReference(SourceLocation Loc,
+                                           FieldDecl *Field,
+                                           Expr *BaseObjectExpr = 0,
+                                      SourceLocation OpLoc = SourceLocation());
+  OwningExprResult BuildPossibleImplicitMemberExpr(const CXXScopeSpec &SS,
+                                                   LookupResult &R,
+                                const TemplateArgumentListInfo *TemplateArgs);
+  OwningExprResult BuildImplicitMemberExpr(const CXXScopeSpec &SS,
+                                           LookupResult &R,
+                                const TemplateArgumentListInfo *TemplateArgs,
+                                           bool IsDefiniteInstance);
+  bool UseArgumentDependentLookup(const CXXScopeSpec &SS,
+                                  const LookupResult &R,
+                                  bool HasTrailingLParen);
+
+  OwningExprResult BuildQualifiedDeclarationNameExpr(const CXXScopeSpec &SS,
+                                                     DeclarationName Name,
+                                                     SourceLocation NameLoc);
+  OwningExprResult BuildDependentDeclRefExpr(const CXXScopeSpec &SS,
+                                             DeclarationName Name,
+                                             SourceLocation NameLoc,
+                                const TemplateArgumentListInfo *TemplateArgs);
+
+  OwningExprResult BuildDeclarationNameExpr(const CXXScopeSpec &SS,
+                                            LookupResult &R,
+                                            bool ADL);
+  OwningExprResult BuildDeclarationNameExpr(const CXXScopeSpec &SS,
+                                            SourceLocation Loc,
+                                            NamedDecl *D);
+
+  virtual OwningExprResult ActOnPredefinedExpr(SourceLocation Loc,
+                                               tok::TokenKind Kind);
+  virtual OwningExprResult ActOnNumericConstant(const Token &);
+  virtual OwningExprResult ActOnCharacterConstant(const Token &);
+  virtual OwningExprResult ActOnParenExpr(SourceLocation L, SourceLocation R,
+                                          ExprArg Val);
+  virtual OwningExprResult ActOnParenOrParenListExpr(SourceLocation L,
+                                              SourceLocation R,
+                                              MultiExprArg Val,
+                                              TypeTy *TypeOfCast=0);
+
+  /// ActOnStringLiteral - The specified tokens were lexed as pasted string
+  /// fragments (e.g. "foo" "bar" L"baz").
+  virtual OwningExprResult ActOnStringLiteral(const Token *Toks,
+                                              unsigned NumToks);
+
+  // Binary/Unary Operators.  'Tok' is the token for the operator.
+  OwningExprResult CreateBuiltinUnaryOp(SourceLocation OpLoc,
+                                        unsigned OpcIn,
+                                        ExprArg InputArg);
+  OwningExprResult BuildUnaryOp(Scope *S, SourceLocation OpLoc,
+                                UnaryOperator::Opcode Opc, ExprArg input);
+  virtual OwningExprResult ActOnUnaryOp(Scope *S, SourceLocation OpLoc,
+                                        tok::TokenKind Op, ExprArg Input);
+
+  OwningExprResult CreateSizeOfAlignOfExpr(TypeSourceInfo *T,
+                                           SourceLocation OpLoc,
+                                           bool isSizeOf, SourceRange R);
+  OwningExprResult CreateSizeOfAlignOfExpr(Expr *E, SourceLocation OpLoc,
+                                           bool isSizeOf, SourceRange R);
+  virtual OwningExprResult
+    ActOnSizeOfAlignOfExpr(SourceLocation OpLoc, bool isSizeof, bool isType,
+                           void *TyOrEx, const SourceRange &ArgRange);
+
+  bool CheckAlignOfExpr(Expr *E, SourceLocation OpLoc, const SourceRange &R);
+  bool CheckSizeOfAlignOfOperand(QualType type, SourceLocation OpLoc,
+                                 const SourceRange &R, bool isSizeof);
+
+  virtual OwningExprResult ActOnPostfixUnaryOp(Scope *S, SourceLocation OpLoc,
+                                               tok::TokenKind Kind,
+                                               ExprArg Input);
+
+  virtual OwningExprResult ActOnArraySubscriptExpr(Scope *S, ExprArg Base,
+                                                   SourceLocation LLoc,
+                                                   ExprArg Idx,
+                                                   SourceLocation RLoc);
+  OwningExprResult CreateBuiltinArraySubscriptExpr(ExprArg Base,
+                                                   SourceLocation LLoc,
+                                                   ExprArg Idx,
+                                                   SourceLocation RLoc);
+
+  OwningExprResult BuildMemberReferenceExpr(ExprArg Base,
+                                            QualType BaseType,
+                                            SourceLocation OpLoc,
+                                            bool IsArrow,
+                                            const CXXScopeSpec &SS,
+                                            NamedDecl *FirstQualifierInScope,
+                                            DeclarationName Name,
+                                            SourceLocation NameLoc,
+                                const TemplateArgumentListInfo *TemplateArgs);
+
+  OwningExprResult BuildMemberReferenceExpr(ExprArg Base,
+                                            QualType BaseType,
+                                            SourceLocation OpLoc, bool IsArrow,
+                                            const CXXScopeSpec &SS,
+                                            NamedDecl *FirstQualifierInScope,
+                                            LookupResult &R,
+                                 const TemplateArgumentListInfo *TemplateArgs);
+
+  OwningExprResult LookupMemberExpr(LookupResult &R, Expr *&Base,
+                                    bool &IsArrow, SourceLocation OpLoc,
+                                    const CXXScopeSpec &SS,
+                                    DeclPtrTy ObjCImpDecl);
+
+  bool CheckQualifiedMemberReference(Expr *BaseExpr, QualType BaseType,
+                                     const CXXScopeSpec &SS,
+                                     const LookupResult &R);
+
+  OwningExprResult ActOnDependentMemberExpr(ExprArg Base,
+                                            QualType BaseType,
+                                            bool IsArrow,
+                                            SourceLocation OpLoc,
+                                            const CXXScopeSpec &SS,
+                                            NamedDecl *FirstQualifierInScope,
+                                            DeclarationName Name,
+                                            SourceLocation NameLoc,
+                               const TemplateArgumentListInfo *TemplateArgs);
+
+  virtual OwningExprResult ActOnMemberAccessExpr(Scope *S, ExprArg Base,
+                                                 SourceLocation OpLoc,
+                                                 tok::TokenKind OpKind,
+                                                 const CXXScopeSpec &SS,
+                                                 UnqualifiedId &Member,
+                                                 DeclPtrTy ObjCImpDecl,
+                                                 bool HasTrailingLParen);
+    
+  virtual void ActOnDefaultCtorInitializers(DeclPtrTy CDtorDecl);
+  bool ConvertArgumentsForCall(CallExpr *Call, Expr *Fn,
+                               FunctionDecl *FDecl,
+                               const FunctionProtoType *Proto,
+                               Expr **Args, unsigned NumArgs,
+                               SourceLocation RParenLoc);
+
+  /// ActOnCallExpr - 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 OwningExprResult ActOnCallExpr(Scope *S, ExprArg Fn,
+                                         SourceLocation LParenLoc,
+                                         MultiExprArg Args,
+                                         SourceLocation *CommaLocs,
+                                         SourceLocation RParenLoc);
+  OwningExprResult BuildResolvedCallExpr(Expr *Fn,
+                                         NamedDecl *NDecl,
+                                         SourceLocation LParenLoc,
+                                         Expr **Args, unsigned NumArgs,
+                                         SourceLocation RParenLoc);
+
+  virtual OwningExprResult ActOnCastExpr(Scope *S, SourceLocation LParenLoc,
+                                         TypeTy *Ty, SourceLocation RParenLoc,
+                                         ExprArg Op);
+  OwningExprResult BuildCStyleCastExpr(SourceLocation LParenLoc,
+                                       TypeSourceInfo *Ty,
+                                       SourceLocation RParenLoc,
+                                       ExprArg Op);
+
+  virtual bool TypeIsVectorType(TypeTy *Ty) {
+    return GetTypeFromParser(Ty)->isVectorType();
+  }
+
+  OwningExprResult MaybeConvertParenListExprToParenExpr(Scope *S, ExprArg ME);
+  OwningExprResult ActOnCastOfParenListExpr(Scope *S, SourceLocation LParenLoc,
+                                            SourceLocation RParenLoc, ExprArg E,
+                                            TypeSourceInfo *TInfo);
+
+  virtual OwningExprResult ActOnCompoundLiteral(SourceLocation LParenLoc,
+                                                TypeTy *Ty,
+                                                SourceLocation RParenLoc,
+                                                ExprArg Op);
+
+  OwningExprResult BuildCompoundLiteralExpr(SourceLocation LParenLoc,
+                                            TypeSourceInfo *TInfo,
+                                            SourceLocation RParenLoc,
+                                            ExprArg InitExpr);
+
+  virtual OwningExprResult ActOnInitList(SourceLocation LParenLoc,
+                                         MultiExprArg InitList,
+                                         SourceLocation RParenLoc);
+
+  virtual OwningExprResult ActOnDesignatedInitializer(Designation &Desig,
+                                                      SourceLocation Loc,
+                                                      bool GNUSyntax,
+                                                      OwningExprResult Init);
+
+  virtual OwningExprResult ActOnBinOp(Scope *S, SourceLocation TokLoc,
+                                      tok::TokenKind Kind,
+                                      ExprArg LHS, ExprArg RHS);
+  OwningExprResult BuildBinOp(Scope *S, SourceLocation OpLoc,
+                              BinaryOperator::Opcode Opc,
+                              Expr *lhs, Expr *rhs);
+  OwningExprResult CreateBuiltinBinOp(SourceLocation TokLoc,
+                                      unsigned Opc, Expr *lhs, Expr *rhs);
+
+  /// ActOnConditionalOp - Parse a ?: operation.  Note that 'LHS' may be null
+  /// in the case of a the GNU conditional expr extension.
+  virtual OwningExprResult ActOnConditionalOp(SourceLocation QuestionLoc,
+                                              SourceLocation ColonLoc,
+                                              ExprArg Cond, ExprArg LHS,
+                                              ExprArg RHS);
+
+  /// ActOnAddrLabel - Parse the GNU address of label extension: "&&foo".
+  virtual OwningExprResult ActOnAddrLabel(SourceLocation OpLoc,
+                                          SourceLocation LabLoc,
+                                          IdentifierInfo *LabelII);
+
+  virtual OwningExprResult ActOnStmtExpr(SourceLocation LPLoc, StmtArg SubStmt,
+                                         SourceLocation RPLoc); // "({..})"
+
+  /// __builtin_offsetof(type, a.b[123][456].c)
+  virtual OwningExprResult ActOnBuiltinOffsetOf(Scope *S,
+                                                SourceLocation BuiltinLoc,
+                                                SourceLocation TypeLoc,
+                                                TypeTy *Arg1,
+                                                OffsetOfComponent *CompPtr,
+                                                unsigned NumComponents,
+                                                SourceLocation RParenLoc);
+
+  // __builtin_types_compatible_p(type1, type2)
+  virtual OwningExprResult ActOnTypesCompatibleExpr(SourceLocation BuiltinLoc,
+                                                    TypeTy *arg1, TypeTy *arg2,
+                                                    SourceLocation RPLoc);
+
+  // __builtin_choose_expr(constExpr, expr1, expr2)
+  virtual OwningExprResult ActOnChooseExpr(SourceLocation BuiltinLoc,
+                                           ExprArg cond, ExprArg expr1,
+                                           ExprArg expr2, SourceLocation RPLoc);
+
+  // __builtin_va_arg(expr, type)
+  virtual OwningExprResult ActOnVAArg(SourceLocation BuiltinLoc,
+                                      ExprArg expr, TypeTy *type,
+                                      SourceLocation RPLoc);
+
+  // __null
+  virtual OwningExprResult ActOnGNUNullExpr(SourceLocation TokenLoc);
+
+  //===------------------------- "Block" Extension ------------------------===//
+
+  /// ActOnBlockStart - This callback is invoked when a block literal is
+  /// started.
+  virtual void ActOnBlockStart(SourceLocation CaretLoc, Scope *CurScope);
+
+  /// ActOnBlockArguments - This callback allows processing of block arguments.
+  /// If there are no arguments, this is still invoked.
+  virtual void ActOnBlockArguments(Declarator &ParamInfo, Scope *CurScope);
+
+  /// ActOnBlockError - If there is an error parsing a block, this callback
+  /// is invoked to pop the information about the block from the action impl.
+  virtual void ActOnBlockError(SourceLocation CaretLoc, Scope *CurScope);
+
+  /// ActOnBlockStmtExpr - This is called when the body of a block statement
+  /// literal was successfully completed.  ^(int x){...}
+  virtual OwningExprResult ActOnBlockStmtExpr(SourceLocation CaretLoc,
+                                              StmtArg Body, Scope *CurScope);
+
+  //===---------------------------- C++ Features --------------------------===//
+
+  // Act on C++ namespaces
+  virtual DeclPtrTy ActOnStartNamespaceDef(Scope *S, SourceLocation IdentLoc,
+                                           IdentifierInfo *Ident,
+                                           SourceLocation LBrace,
+                                           AttributeList *AttrList);
+  virtual void ActOnFinishNamespaceDef(DeclPtrTy Dcl, SourceLocation RBrace);
+
+  virtual DeclPtrTy ActOnUsingDirective(Scope *CurScope,
+                                        SourceLocation UsingLoc,
+                                        SourceLocation NamespcLoc,
+                                        const CXXScopeSpec &SS,
+                                        SourceLocation IdentLoc,
+                                        IdentifierInfo *NamespcName,
+                                        AttributeList *AttrList);
+
+  void PushUsingDirective(Scope *S, UsingDirectiveDecl *UDir);
+
+  virtual DeclPtrTy ActOnNamespaceAliasDef(Scope *CurScope,
+                                           SourceLocation NamespaceLoc,
+                                           SourceLocation AliasLoc,
+                                           IdentifierInfo *Alias,
+                                           const CXXScopeSpec &SS,
+                                           SourceLocation IdentLoc,
+                                           IdentifierInfo *Ident);
+
+  void HideUsingShadowDecl(Scope *S, UsingShadowDecl *Shadow);
+  bool CheckUsingShadowDecl(UsingDecl *UD, NamedDecl *Target,
+                            const LookupResult &PreviousDecls);
+  UsingShadowDecl *BuildUsingShadowDecl(Scope *S, UsingDecl *UD,
+                                        NamedDecl *Target);
+
+  bool CheckUsingDeclRedeclaration(SourceLocation UsingLoc,
+                                   bool isTypeName,
+                                   const CXXScopeSpec &SS,
+                                   SourceLocation NameLoc,
+                                   const LookupResult &Previous);
+  bool CheckUsingDeclQualifier(SourceLocation UsingLoc,
+                               const CXXScopeSpec &SS,
+                               SourceLocation NameLoc);
+
+  NamedDecl *BuildUsingDeclaration(Scope *S, AccessSpecifier AS,
+                                   SourceLocation UsingLoc,
+                                   const CXXScopeSpec &SS,
+                                   SourceLocation IdentLoc,
+                                   DeclarationName Name,
+                                   AttributeList *AttrList,
+                                   bool IsInstantiation,
+                                   bool IsTypeName,
+                                   SourceLocation TypenameLoc);
+
+  virtual DeclPtrTy ActOnUsingDeclaration(Scope *CurScope,
+                                          AccessSpecifier AS,
+                                          bool HasUsingKeyword,
+                                          SourceLocation UsingLoc,
+                                          const CXXScopeSpec &SS,
+                                          UnqualifiedId &Name,
+                                          AttributeList *AttrList,
+                                          bool IsTypeName,
+                                          SourceLocation TypenameLoc);
+
+  /// AddCXXDirectInitializerToDecl - This action is called immediately after
+  /// ActOnDeclarator, when a C++ direct initializer is present.
+  /// e.g: "int x(1);"
+  virtual void AddCXXDirectInitializerToDecl(DeclPtrTy Dcl,
+                                             SourceLocation LParenLoc,
+                                             MultiExprArg Exprs,
+                                             SourceLocation *CommaLocs,
+                                             SourceLocation RParenLoc);
+
+  /// InitializeVarWithConstructor - Creates an CXXConstructExpr
+  /// and sets it as the initializer for the the passed in VarDecl.
+  bool InitializeVarWithConstructor(VarDecl *VD,
+                                    CXXConstructorDecl *Constructor,
+                                    MultiExprArg Exprs);
+
+  /// BuildCXXConstructExpr - Creates a complete call to a constructor,
+  /// including handling of its default argument expressions.
+  OwningExprResult BuildCXXConstructExpr(SourceLocation ConstructLoc,
+                                         QualType DeclInitType,
+                                         CXXConstructorDecl *Constructor,
+                                         MultiExprArg Exprs,
+                                         bool RequiresZeroInit = false,
+                                         bool BaseInitialization = false);
+
+  // FIXME: Can re remove this and have the above BuildCXXConstructExpr check if
+  // the constructor can be elidable?
+  OwningExprResult BuildCXXConstructExpr(SourceLocation ConstructLoc,
+                                         QualType DeclInitType,
+                                         CXXConstructorDecl *Constructor,
+                                         bool Elidable,
+                                         MultiExprArg Exprs,
+                                         bool RequiresZeroInit = false,
+                                         bool BaseInitialization = false);
+
+  OwningExprResult BuildCXXCastArgument(SourceLocation CastLoc,
+                                        QualType Ty,
+                                        CastExpr::CastKind Kind,
+                                        CXXMethodDecl *Method,
+                                        ExprArg Arg);
+
+  /// BuildCXXDefaultArgExpr - Creates a CXXDefaultArgExpr, instantiating
+  /// the default expr if needed.
+  OwningExprResult BuildCXXDefaultArgExpr(SourceLocation CallLoc,
+                                          FunctionDecl *FD,
+                                          ParmVarDecl *Param);
+
+  /// FinalizeVarWithDestructor - Prepare for calling destructor on the
+  /// constructed variable.
+  void FinalizeVarWithDestructor(VarDecl *VD, const RecordType *DeclInitType);
+
+  /// DefineImplicitDefaultConstructor - Checks for feasibility of
+  /// defining this constructor as the default constructor.
+  void DefineImplicitDefaultConstructor(SourceLocation CurrentLocation,
+                                        CXXConstructorDecl *Constructor);
+
+  /// DefineImplicitDestructor - Checks for feasibility of
+  /// defining this destructor as the default destructor.
+  void DefineImplicitDestructor(SourceLocation CurrentLocation,
+                                        CXXDestructorDecl *Destructor);
+
+  /// DefineImplicitCopyConstructor - Checks for feasibility of
+  /// defining this constructor as the copy constructor.
+  void DefineImplicitCopyConstructor(SourceLocation CurrentLocation,
+                                     CXXConstructorDecl *Constructor,
+                                     unsigned TypeQuals);
+
+  /// DefineImplicitOverloadedAssign - Checks for feasibility of
+  /// defining implicit this overloaded assignment operator.
+  void DefineImplicitOverloadedAssign(SourceLocation CurrentLocation,
+                                      CXXMethodDecl *MethodDecl);
+
+  /// getAssignOperatorMethod - Returns the default copy assignmment operator
+  /// for the class.
+  CXXMethodDecl *getAssignOperatorMethod(SourceLocation CurrentLocation,
+                                         ParmVarDecl *Decl,
+                                         CXXRecordDecl *ClassDecl);
+
+  /// MaybeBindToTemporary - If the passed in expression has a record type with
+  /// a non-trivial destructor, this will return CXXBindTemporaryExpr. Otherwise
+  /// it simply returns the passed in expression.
+  OwningExprResult MaybeBindToTemporary(Expr *E);
+
+  CXXConstructorDecl *
+  TryInitializationByConstructor(QualType ClassType,
+                                 Expr **Args, unsigned NumArgs,
+                                 SourceLocation Loc,
+                                 InitializationKind Kind);
+
+  bool CompleteConstructorCall(CXXConstructorDecl *Constructor,
+                               MultiExprArg ArgsPtr,
+                               SourceLocation Loc,                                    
+                      ASTOwningVector<&ActionBase::DeleteExpr> &ConvertedArgs);
+    
+  /// ActOnCXXNamedCast - Parse {dynamic,static,reinterpret,const}_cast's.
+  virtual OwningExprResult ActOnCXXNamedCast(SourceLocation OpLoc,
+                                             tok::TokenKind Kind,
+                                             SourceLocation LAngleBracketLoc,
+                                             TypeTy *Ty,
+                                             SourceLocation RAngleBracketLoc,
+                                             SourceLocation LParenLoc,
+                                             ExprArg E,
+                                             SourceLocation RParenLoc);
+
+  OwningExprResult BuildCXXNamedCast(SourceLocation OpLoc,
+                                     tok::TokenKind Kind,
+                                     TypeSourceInfo *Ty,
+                                     ExprArg E,
+                                     SourceRange AngleBrackets,
+                                     SourceRange Parens);
+
+  /// ActOnCXXTypeid - Parse typeid( something ).
+  virtual OwningExprResult ActOnCXXTypeid(SourceLocation OpLoc,
+                                          SourceLocation LParenLoc, bool isType,
+                                          void *TyOrExpr,
+                                          SourceLocation RParenLoc);
+
+  //// ActOnCXXThis -  Parse 'this' pointer.
+  virtual OwningExprResult ActOnCXXThis(SourceLocation ThisLoc);
+
+  /// ActOnCXXBoolLiteral - Parse {true,false} literals.
+  virtual OwningExprResult ActOnCXXBoolLiteral(SourceLocation OpLoc,
+                                               tok::TokenKind Kind);
+
+  /// ActOnCXXNullPtrLiteral - Parse 'nullptr'.
+  virtual OwningExprResult ActOnCXXNullPtrLiteral(SourceLocation Loc);
+
+  //// ActOnCXXThrow -  Parse throw expressions.
+  virtual OwningExprResult ActOnCXXThrow(SourceLocation OpLoc,
+                                         ExprArg expr);
+  bool CheckCXXThrowOperand(SourceLocation ThrowLoc, Expr *&E);
+
+  /// ActOnCXXTypeConstructExpr - Parse construction of a specified type.
+  /// Can be interpreted either as function-style casting ("int(x)")
+  /// or class type construction ("ClassType(x,y,z)")
+  /// or creation of a value-initialized type ("int()").
+  virtual OwningExprResult ActOnCXXTypeConstructExpr(SourceRange TypeRange,
+                                                     TypeTy *TypeRep,
+                                                     SourceLocation LParenLoc,
+                                                     MultiExprArg Exprs,
+                                                     SourceLocation *CommaLocs,
+                                                     SourceLocation RParenLoc);
+
+  /// ActOnCXXNew - Parsed a C++ 'new' expression.
+  virtual OwningExprResult ActOnCXXNew(SourceLocation StartLoc, bool UseGlobal,
+                                       SourceLocation PlacementLParen,
+                                       MultiExprArg PlacementArgs,
+                                       SourceLocation PlacementRParen,
+                                       bool ParenTypeId, Declarator &D,
+                                       SourceLocation ConstructorLParen,
+                                       MultiExprArg ConstructorArgs,
+                                       SourceLocation ConstructorRParen);
+  OwningExprResult BuildCXXNew(SourceLocation StartLoc, bool UseGlobal,
+                               SourceLocation PlacementLParen,
+                               MultiExprArg PlacementArgs,
+                               SourceLocation PlacementRParen,
+                               bool ParenTypeId,
+                               QualType AllocType,
+                               SourceLocation TypeLoc,
+                               SourceRange TypeRange,
+                               ExprArg ArraySize,
+                               SourceLocation ConstructorLParen,
+                               MultiExprArg ConstructorArgs,
+                               SourceLocation ConstructorRParen);
+
+  bool CheckAllocatedType(QualType AllocType, SourceLocation Loc,
+                          SourceRange R);
+  bool FindAllocationFunctions(SourceLocation StartLoc, SourceRange Range,
+                               bool UseGlobal, QualType AllocType, bool IsArray,
+                               Expr **PlaceArgs, unsigned NumPlaceArgs,
+                               FunctionDecl *&OperatorNew,
+                               FunctionDecl *&OperatorDelete);
+  bool FindAllocationOverload(SourceLocation StartLoc, SourceRange Range,
+                              DeclarationName Name, Expr** Args,
+                              unsigned NumArgs, DeclContext *Ctx,
+                              bool AllowMissing, FunctionDecl *&Operator);
+  void DeclareGlobalNewDelete();
+  void DeclareGlobalAllocationFunction(DeclarationName Name, QualType Return,
+                                       QualType Argument,
+                                       bool addMallocAttr = false);
+
+  bool FindDeallocationFunction(SourceLocation StartLoc, CXXRecordDecl *RD, 
+                                DeclarationName Name, FunctionDecl* &Operator);
+
+  /// ActOnCXXDelete - Parsed a C++ 'delete' expression
+  virtual OwningExprResult ActOnCXXDelete(SourceLocation StartLoc,
+                                          bool UseGlobal, bool ArrayForm,
+                                          ExprArg Operand);
+
+  virtual DeclResult ActOnCXXConditionDeclaration(Scope *S,
+                                                  Declarator &D);
+  OwningExprResult CheckConditionVariable(VarDecl *ConditionVar);
+                                          
+  /// ActOnUnaryTypeTrait - Parsed one of the unary type trait support
+  /// pseudo-functions.
+  virtual OwningExprResult ActOnUnaryTypeTrait(UnaryTypeTrait OTT,
+                                               SourceLocation KWLoc,
+                                               SourceLocation LParen,
+                                               TypeTy *Ty,
+                                               SourceLocation RParen);
+
+  virtual OwningExprResult ActOnStartCXXMemberReference(Scope *S,
+                                                        ExprArg Base,
+                                                        SourceLocation OpLoc,
+                                                        tok::TokenKind OpKind,
+                                                        TypeTy *&ObjectType);
+
+  /// MaybeCreateCXXExprWithTemporaries - If the list of temporaries is
+  /// non-empty, will create a new CXXExprWithTemporaries expression.
+  /// Otherwise, just returs the passed in expression.
+  Expr *MaybeCreateCXXExprWithTemporaries(Expr *SubExpr);
+  OwningExprResult MaybeCreateCXXExprWithTemporaries(OwningExprResult SubExpr);
+  FullExpr CreateFullExpr(Expr *SubExpr);
+  
+  virtual OwningExprResult ActOnFinishFullExpr(ExprArg Expr);
+
+  bool RequireCompleteDeclContext(const CXXScopeSpec &SS);
+
+  DeclContext *computeDeclContext(QualType T);
+  DeclContext *computeDeclContext(const CXXScopeSpec &SS,
+                                  bool EnteringContext = false);
+  bool isDependentScopeSpecifier(const CXXScopeSpec &SS);
+  CXXRecordDecl *getCurrentInstantiationOf(NestedNameSpecifier *NNS);
+  bool isUnknownSpecialization(const CXXScopeSpec &SS);
+
+  /// ActOnCXXGlobalScopeSpecifier - Return the object that represents the
+  /// global scope ('::').
+  virtual CXXScopeTy *ActOnCXXGlobalScopeSpecifier(Scope *S,
+                                                   SourceLocation CCLoc);
+
+  bool isAcceptableNestedNameSpecifier(NamedDecl *SD);
+  NamedDecl *FindFirstQualifierInScope(Scope *S, NestedNameSpecifier *NNS);
+
+
+  CXXScopeTy *BuildCXXNestedNameSpecifier(Scope *S,
+                                          const CXXScopeSpec &SS,
+                                          SourceLocation IdLoc,
+                                          SourceLocation CCLoc,
+                                          IdentifierInfo &II,
+                                          QualType ObjectType,
+                                          NamedDecl *ScopeLookupResult,
+                                          bool EnteringContext,
+                                          bool ErrorRecoveryLookup);
+
+  virtual CXXScopeTy *ActOnCXXNestedNameSpecifier(Scope *S,
+                                                  const CXXScopeSpec &SS,
+                                                  SourceLocation IdLoc,
+                                                  SourceLocation CCLoc,
+                                                  IdentifierInfo &II,
+                                                  TypeTy *ObjectType,
+                                                  bool EnteringContext);
+
+  virtual bool IsInvalidUnlessNestedName(Scope *S,
+                                         const CXXScopeSpec &SS,
+                                         IdentifierInfo &II,
+                                         TypeTy *ObjectType,
+                                         bool EnteringContext);
+  
+  /// ActOnCXXNestedNameSpecifier - Called during parsing of a
+  /// nested-name-specifier that involves a template-id, e.g.,
+  /// "foo::bar<int, float>::", and now we need to build a scope
+  /// specifier. \p SS is empty or the previously parsed nested-name
+  /// part ("foo::"), \p Type is the already-parsed class template
+  /// specialization (or other template-id that names a type), \p
+  /// TypeRange is the source range where the type is located, and \p
+  /// CCLoc is the location of the trailing '::'.
+  virtual CXXScopeTy *ActOnCXXNestedNameSpecifier(Scope *S,
+                                                  const CXXScopeSpec &SS,
+                                                  TypeTy *Type,
+                                                  SourceRange TypeRange,
+                                                  SourceLocation CCLoc);
+
+  virtual bool ShouldEnterDeclaratorScope(Scope *S, const CXXScopeSpec &SS);
+
+  /// ActOnCXXEnterDeclaratorScope - Called when a C++ scope specifier (global
+  /// scope or nested-name-specifier) is parsed, part of a declarator-id.
+  /// After this method is called, according to [C++ 3.4.3p3], names should be
+  /// looked up in the declarator-id's scope, until the declarator is parsed and
+  /// ActOnCXXExitDeclaratorScope is called.
+  /// The 'SS' should be a non-empty valid CXXScopeSpec.
+  virtual bool ActOnCXXEnterDeclaratorScope(Scope *S, const CXXScopeSpec &SS);
+
+  /// ActOnCXXExitDeclaratorScope - Called when a declarator that previously
+  /// invoked ActOnCXXEnterDeclaratorScope(), is finished. 'SS' is the same
+  /// CXXScopeSpec that was passed to ActOnCXXEnterDeclaratorScope as well.
+  /// Used to indicate that names should revert to being looked up in the
+  /// defining scope.
+  virtual void ActOnCXXExitDeclaratorScope(Scope *S, const CXXScopeSpec &SS);
+
+  /// ActOnCXXEnterDeclInitializer - Invoked when we are about to parse an
+  /// initializer for the declaration 'Dcl'.
+  /// After this method is called, according to [C++ 3.4.1p13], if 'Dcl' is a
+  /// static data member of class X, names should be looked up in the scope of
+  /// class X.
+  virtual void ActOnCXXEnterDeclInitializer(Scope *S, DeclPtrTy Dcl);
+
+  /// ActOnCXXExitDeclInitializer - Invoked after we are finished parsing an
+  /// initializer for the declaration 'Dcl'.
+  virtual void ActOnCXXExitDeclInitializer(Scope *S, DeclPtrTy Dcl);
+
+  // ParseObjCStringLiteral - Parse Objective-C string literals.
+  virtual ExprResult ParseObjCStringLiteral(SourceLocation *AtLocs,
+                                            ExprTy **Strings,
+                                            unsigned NumStrings);
+
+  Expr *BuildObjCEncodeExpression(SourceLocation AtLoc,
+                                  QualType EncodedType,
+                                  SourceLocation RParenLoc);
+  CXXMemberCallExpr *BuildCXXMemberCallExpr(Expr *Exp, CXXMethodDecl *Method);
+
+  virtual ExprResult ParseObjCEncodeExpression(SourceLocation AtLoc,
+                                               SourceLocation EncodeLoc,
+                                               SourceLocation LParenLoc,
+                                               TypeTy *Ty,
+                                               SourceLocation RParenLoc);
+
+  // ParseObjCSelectorExpression - Build selector expression for @selector
+  virtual ExprResult ParseObjCSelectorExpression(Selector Sel,
+                                                 SourceLocation AtLoc,
+                                                 SourceLocation SelLoc,
+                                                 SourceLocation LParenLoc,
+                                                 SourceLocation RParenLoc);
+
+  // ParseObjCProtocolExpression - Build protocol expression for @protocol
+  virtual ExprResult ParseObjCProtocolExpression(IdentifierInfo * ProtocolName,
+                                                 SourceLocation AtLoc,
+                                                 SourceLocation ProtoLoc,
+                                                 SourceLocation LParenLoc,
+                                                 SourceLocation RParenLoc);
+
+  //===--------------------------------------------------------------------===//
+  // C++ Declarations
+  //
+  virtual DeclPtrTy ActOnStartLinkageSpecification(Scope *S,
+                                                   SourceLocation ExternLoc,
+                                                   SourceLocation LangLoc,
+                                                   const char *Lang,
+                                                   unsigned StrSize,
+                                                   SourceLocation LBraceLoc);
+  virtual DeclPtrTy ActOnFinishLinkageSpecification(Scope *S,
+                                                    DeclPtrTy LinkageSpec,
+                                                    SourceLocation RBraceLoc);
+
+
+  //===--------------------------------------------------------------------===//
+  // C++ Classes
+  //
+  virtual bool isCurrentClassName(const IdentifierInfo &II, Scope *S,
+                                  const CXXScopeSpec *SS);
+
+  virtual DeclPtrTy ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS,
+                                             Declarator &D,
+                                 MultiTemplateParamsArg TemplateParameterLists,
+                                             ExprTy *BitfieldWidth,
+                                             ExprTy *Init, bool IsDefinition,
+                                             bool Deleted = false);
+
+  virtual MemInitResult ActOnMemInitializer(DeclPtrTy ConstructorD,
+                                            Scope *S,
+                                            const CXXScopeSpec &SS,
+                                            IdentifierInfo *MemberOrBase,
+                                            TypeTy *TemplateTypeTy,
+                                            SourceLocation IdLoc,
+                                            SourceLocation LParenLoc,
+                                            ExprTy **Args, unsigned NumArgs,
+                                            SourceLocation *CommaLocs,
+                                            SourceLocation RParenLoc);
+
+  MemInitResult BuildMemberInitializer(FieldDecl *Member, Expr **Args,
+                                       unsigned NumArgs, SourceLocation IdLoc,
+                                       SourceLocation LParenLoc,
+                                       SourceLocation RParenLoc);
+
+  MemInitResult BuildBaseInitializer(QualType BaseType,
+                                     TypeSourceInfo *BaseTInfo,
+                                     Expr **Args, unsigned NumArgs,
+                                     SourceLocation LParenLoc,
+                                     SourceLocation RParenLoc,
+                                     CXXRecordDecl *ClassDecl);
+
+  bool SetBaseOrMemberInitializers(CXXConstructorDecl *Constructor,
+                                   CXXBaseOrMemberInitializer **Initializers,
+                                   unsigned NumInitializers,
+                                   bool IsImplicitConstructor,
+                                   bool AnyErrors);
+
+  /// MarkBaseAndMemberDestructorsReferenced - Given a destructor decl,
+  /// mark all its non-trivial member and base destructor declarations
+  /// as referenced.
+  void MarkBaseAndMemberDestructorsReferenced(CXXDestructorDecl *Destructor);
+
+  /// ClassesWithUnmarkedVirtualMembers - Contains record decls whose virtual
+  /// members need to be marked as referenced at the end of the translation
+  /// unit. It will contain polymorphic classes that do not have a key
+  /// function or have a key function that has been defined.
+  llvm::SmallVector<std::pair<CXXRecordDecl *, SourceLocation>, 4>
+    ClassesWithUnmarkedVirtualMembers;
+
+  /// MaybeMarkVirtualMembersReferenced - If the passed in method is the
+  /// key function of the record decl, will mark virtual member functions as 
+  /// referenced.
+  void MaybeMarkVirtualMembersReferenced(SourceLocation Loc, CXXMethodDecl *MD);
+  
+  /// MarkVirtualMembersReferenced - Will mark all virtual members of the given
+  /// CXXRecordDecl referenced.
+  void MarkVirtualMembersReferenced(SourceLocation Loc, CXXRecordDecl *RD);
+
+  /// ProcessPendingClassesWithUnmarkedVirtualMembers - Will process classes 
+  /// that might need to have their virtual members marked as referenced.
+  /// Returns false if no work was done.
+  bool ProcessPendingClassesWithUnmarkedVirtualMembers();
+  
+  void AddImplicitlyDeclaredMembersToClass(CXXRecordDecl *ClassDecl);
+
+  virtual void ActOnMemInitializers(DeclPtrTy ConstructorDecl,
+                                    SourceLocation ColonLoc,
+                                    MemInitTy **MemInits, unsigned NumMemInits,
+                                    bool AnyErrors);
+
+  void CheckCompletedCXXClass(CXXRecordDecl *Record);
+  virtual void ActOnFinishCXXMemberSpecification(Scope* S, SourceLocation RLoc,
+                                                 DeclPtrTy TagDecl,
+                                                 SourceLocation LBrac,
+                                                 SourceLocation RBrac);
+
+  virtual void ActOnReenterTemplateScope(Scope *S, DeclPtrTy Template);
+  virtual void ActOnStartDelayedMemberDeclarations(Scope *S,
+                                                   DeclPtrTy Record);
+  virtual void ActOnStartDelayedCXXMethodDeclaration(Scope *S,
+                                                     DeclPtrTy Method);
+  virtual void ActOnDelayedCXXMethodParameter(Scope *S, DeclPtrTy Param);
+  virtual void ActOnFinishDelayedCXXMethodDeclaration(Scope *S,
+                                                      DeclPtrTy Method);
+  virtual void ActOnFinishDelayedMemberDeclarations(Scope *S,
+                                                    DeclPtrTy Record);
+
+  virtual DeclPtrTy ActOnStaticAssertDeclaration(SourceLocation AssertLoc,
+                                                 ExprArg AssertExpr,
+                                                 ExprArg AssertMessageExpr);
+
+  DeclPtrTy ActOnFriendTypeDecl(Scope *S, const DeclSpec &DS,
+                                MultiTemplateParamsArg TemplateParams);
+  DeclPtrTy ActOnFriendFunctionDecl(Scope *S, Declarator &D, bool IsDefinition,
+                                    MultiTemplateParamsArg TemplateParams);
+
+  QualType CheckConstructorDeclarator(Declarator &D, QualType R,
+                                      FunctionDecl::StorageClass& SC);
+  void CheckConstructor(CXXConstructorDecl *Constructor);
+  QualType CheckDestructorDeclarator(Declarator &D,
+                                     FunctionDecl::StorageClass& SC);
+  bool CheckDestructor(CXXDestructorDecl *Destructor);
+  void CheckConversionDeclarator(Declarator &D, QualType &R,
+                                 FunctionDecl::StorageClass& SC);
+  DeclPtrTy ActOnConversionDeclarator(CXXConversionDecl *Conversion);
+  
+  //===--------------------------------------------------------------------===//
+  // C++ Derived Classes
+  //
+
+  /// ActOnBaseSpecifier - Parsed a base specifier
+  CXXBaseSpecifier *CheckBaseSpecifier(CXXRecordDecl *Class,
+                                       SourceRange SpecifierRange,
+                                       bool Virtual, AccessSpecifier Access,
+                                       QualType BaseType,
+                                       SourceLocation BaseLoc);
+  
+  /// SetClassDeclAttributesFromBase - Copies class decl traits 
+  /// (such as whether the class has a trivial constructor, 
+  /// trivial destructor etc) from the given base class.
+  void SetClassDeclAttributesFromBase(CXXRecordDecl *Class,
+                                      const CXXRecordDecl *BaseClass,
+                                      bool BaseIsVirtual);
+  
+  virtual BaseResult ActOnBaseSpecifier(DeclPtrTy classdecl,
+                                        SourceRange SpecifierRange,
+                                        bool Virtual, AccessSpecifier Access,
+                                        TypeTy *basetype, SourceLocation
+                                        BaseLoc);
+
+  bool AttachBaseSpecifiers(CXXRecordDecl *Class, CXXBaseSpecifier **Bases,
+                            unsigned NumBases);
+  virtual void ActOnBaseSpecifiers(DeclPtrTy ClassDecl, BaseTy **Bases,
+                                   unsigned NumBases);
+
+  bool IsDerivedFrom(QualType Derived, QualType Base);
+  bool IsDerivedFrom(QualType Derived, QualType Base, CXXBasePaths &Paths);
+  
+  bool CheckDerivedToBaseConversion(QualType Derived, QualType Base,
+                                    SourceLocation Loc, SourceRange Range,
+                                    bool IgnoreAccess = false);
+  bool CheckDerivedToBaseConversion(QualType Derived, QualType Base,
+                                    AccessDiagnosticsKind ADK,
+                                    unsigned AmbigiousBaseConvID,
+                                    SourceLocation Loc, SourceRange Range,
+                                    DeclarationName Name);
+
+  std::string getAmbiguousPathsDisplayString(CXXBasePaths &Paths);
+
+  /// CheckOverridingFunctionReturnType - Checks whether the return types are
+  /// covariant, according to C++ [class.virtual]p5.
+  bool CheckOverridingFunctionReturnType(const CXXMethodDecl *New,
+                                         const CXXMethodDecl *Old);
+
+  /// CheckOverridingFunctionExceptionSpec - Checks whether the exception
+  /// spec is a subset of base spec.
+  bool CheckOverridingFunctionExceptionSpec(const CXXMethodDecl *New,
+                                            const CXXMethodDecl *Old);
+
+  /// CheckOverridingFunctionAttributes - Checks whether attributes are
+  /// incompatible or prevent overriding.
+  bool CheckOverridingFunctionAttributes(const CXXMethodDecl *New,
+                                         const CXXMethodDecl *Old);
+
+  bool CheckPureMethod(CXXMethodDecl *Method, SourceRange InitRange);
+  //===--------------------------------------------------------------------===//
+  // C++ Access Control
+  //
+
+  enum AccessResult {
+    AR_accessible,
+    AR_inaccessible,
+    AR_dependent,
+    AR_delayed
+  };
+
+  bool SetMemberAccessSpecifier(NamedDecl *MemberDecl,
+                                NamedDecl *PrevMemberDecl,
+                                AccessSpecifier LexicalAS);
+
+  AccessResult CheckUnresolvedMemberAccess(UnresolvedMemberExpr *E,
+                                           NamedDecl *D,
+                                           AccessSpecifier Access);
+  AccessResult CheckUnresolvedLookupAccess(UnresolvedLookupExpr *E,
+                                           NamedDecl *D,
+                                           AccessSpecifier Access);
+  AccessResult CheckConstructorAccess(SourceLocation Loc,
+                                      CXXConstructorDecl *D,
+                                      AccessSpecifier Access);
+  AccessResult CheckDestructorAccess(SourceLocation Loc,
+                                     const RecordType *Record);
+  AccessResult CheckMemberOperatorAccess(SourceLocation Loc,
+                                         Expr *ObjectExpr,
+                                         NamedDecl *D,
+                                         AccessSpecifier Access);
+  AccessResult CheckBaseClassAccess(SourceLocation AccessLoc,
+                                    bool IsBaseToDerived,
+                                    QualType Base, QualType Derived,
+                                    const CXXBasePath &Path,
+                                    bool ForceCheck = false,
+                                    bool ForceUnprivileged = false,
+                                    AccessDiagnosticsKind ADK = ADK_normal);
+                            
+  void CheckLookupAccess(const LookupResult &R);
+
+  void HandleDelayedAccessCheck(DelayedDiagnostic &DD, Decl *Ctx);
+
+  enum AbstractDiagSelID {
+    AbstractNone = -1,
+    AbstractReturnType,
+    AbstractParamType,
+    AbstractVariableType,
+    AbstractFieldType
+  };
+
+  bool RequireNonAbstractType(SourceLocation Loc, QualType T,
+                              const PartialDiagnostic &PD,
+                              const CXXRecordDecl *CurrentRD = 0);
+
+  bool RequireNonAbstractType(SourceLocation Loc, QualType T, unsigned DiagID,
+                              AbstractDiagSelID SelID = AbstractNone,
+                              const CXXRecordDecl *CurrentRD = 0);
+
+  //===--------------------------------------------------------------------===//
+  // C++ Overloaded Operators [C++ 13.5]
+  //
+
+  bool CheckOverloadedOperatorDeclaration(FunctionDecl *FnDecl);
+
+  bool CheckLiteralOperatorDeclaration(FunctionDecl *FnDecl);
+
+  //===--------------------------------------------------------------------===//
+  // C++ Templates [C++ 14]
+  //
+  void LookupTemplateName(LookupResult &R, Scope *S, const CXXScopeSpec &SS,
+                          QualType ObjectType, bool EnteringContext);
+
+  virtual TemplateNameKind isTemplateName(Scope *S,
+                                          const CXXScopeSpec &SS,
+                                          UnqualifiedId &Name,
+                                          TypeTy *ObjectType,
+                                          bool EnteringContext,
+                                          TemplateTy &Template);
+  
+  virtual bool DiagnoseUnknownTemplateName(const IdentifierInfo &II, 
+                                           SourceLocation IILoc,
+                                           Scope *S,
+                                           const CXXScopeSpec *SS,
+                                           TemplateTy &SuggestedTemplate,
+                                           TemplateNameKind &SuggestedKind);
+    
+  bool DiagnoseTemplateParameterShadow(SourceLocation Loc, Decl *PrevDecl);
+  TemplateDecl *AdjustDeclIfTemplate(DeclPtrTy &Decl);
+
+  virtual DeclPtrTy ActOnTypeParameter(Scope *S, bool Typename, bool Ellipsis,
+                                       SourceLocation EllipsisLoc,
+                                       SourceLocation KeyLoc,
+                                       IdentifierInfo *ParamName,
+                                       SourceLocation ParamNameLoc,
+                                       unsigned Depth, unsigned Position);
+  virtual void ActOnTypeParameterDefault(DeclPtrTy TypeParam,
+                                         SourceLocation EqualLoc,
+                                         SourceLocation DefaultLoc,
+                                         TypeTy *Default);
+
+  QualType CheckNonTypeTemplateParameterType(QualType T, SourceLocation Loc);
+  virtual DeclPtrTy ActOnNonTypeTemplateParameter(Scope *S, Declarator &D,
+                                                  unsigned Depth,
+                                                  unsigned Position);
+  virtual void ActOnNonTypeTemplateParameterDefault(DeclPtrTy TemplateParam,
+                                                    SourceLocation EqualLoc,
+                                                    ExprArg Default);
+  virtual DeclPtrTy ActOnTemplateTemplateParameter(Scope *S,
+                                                   SourceLocation TmpLoc,
+                                                   TemplateParamsTy *Params,
+                                                   IdentifierInfo *ParamName,
+                                                   SourceLocation ParamNameLoc,
+                                                   unsigned Depth,
+                                                   unsigned Position);
+  virtual void ActOnTemplateTemplateParameterDefault(DeclPtrTy TemplateParam,
+                                                     SourceLocation EqualLoc,
+                                        const ParsedTemplateArgument &Default);
+
+  virtual TemplateParamsTy *
+  ActOnTemplateParameterList(unsigned Depth,
+                             SourceLocation ExportLoc,
+                             SourceLocation TemplateLoc,
+                             SourceLocation LAngleLoc,
+                             DeclPtrTy *Params, unsigned NumParams,
+                             SourceLocation RAngleLoc);
+
+  /// \brief The context in which we are checking a template parameter
+  /// list.
+  enum TemplateParamListContext {
+    TPC_ClassTemplate,
+    TPC_FunctionTemplate,
+    TPC_ClassTemplateMember,
+    TPC_FriendFunctionTemplate
+  };
+
+  bool CheckTemplateParameterList(TemplateParameterList *NewParams,
+                                  TemplateParameterList *OldParams,
+                                  TemplateParamListContext TPC);
+  TemplateParameterList *
+  MatchTemplateParametersToScopeSpecifier(SourceLocation DeclStartLoc,
+                                          const CXXScopeSpec &SS,
+                                          TemplateParameterList **ParamLists,
+                                          unsigned NumParamLists,
+                                          bool &IsExplicitSpecialization);
+
+  DeclResult CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK,
+                                SourceLocation KWLoc, const CXXScopeSpec &SS,
+                                IdentifierInfo *Name, SourceLocation NameLoc,
+                                AttributeList *Attr,
+                                TemplateParameterList *TemplateParams,
+                                AccessSpecifier AS);
+
+  void translateTemplateArguments(const ASTTemplateArgsPtr &In,
+                                  TemplateArgumentListInfo &Out);
+    
+  QualType CheckTemplateIdType(TemplateName Template,
+                               SourceLocation TemplateLoc,
+                               const TemplateArgumentListInfo &TemplateArgs);
+
+  virtual TypeResult
+  ActOnTemplateIdType(TemplateTy Template, SourceLocation TemplateLoc,
+                      SourceLocation LAngleLoc,
+                      ASTTemplateArgsPtr TemplateArgs,
+                      SourceLocation RAngleLoc);
+
+  virtual TypeResult ActOnTagTemplateIdType(TypeResult Type,
+                                            TagUseKind TUK,
+                                            DeclSpec::TST TagSpec,
+                                            SourceLocation TagLoc);
+
+  OwningExprResult BuildTemplateIdExpr(const CXXScopeSpec &SS,
+                                       LookupResult &R,
+                                       bool RequiresADL,
+                               const TemplateArgumentListInfo &TemplateArgs);
+  OwningExprResult BuildQualifiedTemplateIdExpr(const CXXScopeSpec &SS,
+                                                DeclarationName Name,
+                                                SourceLocation NameLoc,
+                               const TemplateArgumentListInfo &TemplateArgs);
+
+  virtual TemplateTy ActOnDependentTemplateName(SourceLocation TemplateKWLoc,
+                                                const CXXScopeSpec &SS,
+                                                UnqualifiedId &Name,
+                                                TypeTy *ObjectType,
+                                                bool EnteringContext);
+
+  bool CheckClassTemplatePartialSpecializationArgs(
+                                        TemplateParameterList *TemplateParams,
+                              const TemplateArgumentListBuilder &TemplateArgs,
+                                        bool &MirrorsPrimaryTemplate);
+
+  virtual DeclResult
+  ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, TagUseKind TUK,
+                                   SourceLocation KWLoc,
+                                   const CXXScopeSpec &SS,
+                                   TemplateTy Template,
+                                   SourceLocation TemplateNameLoc,
+                                   SourceLocation LAngleLoc,
+                                   ASTTemplateArgsPtr TemplateArgs,
+                                   SourceLocation RAngleLoc,
+                                   AttributeList *Attr,
+                                 MultiTemplateParamsArg TemplateParameterLists);
+
+  virtual DeclPtrTy ActOnTemplateDeclarator(Scope *S,
+                                  MultiTemplateParamsArg TemplateParameterLists,
+                                            Declarator &D);
+
+  virtual DeclPtrTy ActOnStartOfFunctionTemplateDef(Scope *FnBodyScope,
+                                                    MultiTemplateParamsArg TemplateParameterLists,
+                                                    Declarator &D);
+
+  bool
+  CheckSpecializationInstantiationRedecl(SourceLocation NewLoc,
+                                         TemplateSpecializationKind NewTSK,
+                                         NamedDecl *PrevDecl,
+                                         TemplateSpecializationKind PrevTSK,
+                                         SourceLocation PrevPointOfInstantiation,
+                                         bool &SuppressNew);
+    
+  bool CheckFunctionTemplateSpecialization(FunctionDecl *FD,
+                        const TemplateArgumentListInfo *ExplicitTemplateArgs,
+                                           LookupResult &Previous);
+  bool CheckMemberSpecialization(NamedDecl *Member, LookupResult &Previous);
+    
+  virtual DeclResult
+  ActOnExplicitInstantiation(Scope *S,
+                             SourceLocation ExternLoc,
+                             SourceLocation TemplateLoc,
+                             unsigned TagSpec,
+                             SourceLocation KWLoc,
+                             const CXXScopeSpec &SS,
+                             TemplateTy Template,
+                             SourceLocation TemplateNameLoc,
+                             SourceLocation LAngleLoc,
+                             ASTTemplateArgsPtr TemplateArgs,
+                             SourceLocation RAngleLoc,
+                             AttributeList *Attr);
+
+  virtual DeclResult
+  ActOnExplicitInstantiation(Scope *S,
+                             SourceLocation ExternLoc,
+                             SourceLocation TemplateLoc,
+                             unsigned TagSpec,
+                             SourceLocation KWLoc,
+                             const CXXScopeSpec &SS,
+                             IdentifierInfo *Name,
+                             SourceLocation NameLoc,
+                             AttributeList *Attr);
+
+  virtual DeclResult ActOnExplicitInstantiation(Scope *S,
+                                                SourceLocation ExternLoc,
+                                                SourceLocation TemplateLoc,
+                                                Declarator &D);
+    
+  TemplateArgumentLoc 
+  SubstDefaultTemplateArgumentIfAvailable(TemplateDecl *Template,
+                                          SourceLocation TemplateLoc,
+                                          SourceLocation RAngleLoc,
+                                          Decl *Param,
+                                      TemplateArgumentListBuilder &Converted);
+
+  bool CheckTemplateArgument(NamedDecl *Param,
+                             const TemplateArgumentLoc &Arg,
+                             TemplateDecl *Template,
+                             SourceLocation TemplateLoc,
+                             SourceLocation RAngleLoc,
+                             TemplateArgumentListBuilder &Converted);
+  
+  bool CheckTemplateArgumentList(TemplateDecl *Template,
+                                 SourceLocation TemplateLoc,
+                                 const TemplateArgumentListInfo &TemplateArgs,
+                                 bool PartialTemplateArgs,
+                                 TemplateArgumentListBuilder &Converted);
+
+  bool CheckTemplateTypeArgument(TemplateTypeParmDecl *Param,
+                                 const TemplateArgumentLoc &Arg,
+                                 TemplateArgumentListBuilder &Converted);
+
+  bool CheckTemplateArgument(TemplateTypeParmDecl *Param,
+                             TypeSourceInfo *Arg);
+  bool CheckTemplateArgumentAddressOfObjectOrFunction(Expr *Arg,
+                                                      NamedDecl *&Entity);
+  bool CheckTemplateArgumentPointerToMember(Expr *Arg, 
+                                            TemplateArgument &Converted);
+  bool CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
+                             QualType InstantiatedParamType, Expr *&Arg,
+                             TemplateArgument &Converted);
+  bool CheckTemplateArgument(TemplateTemplateParmDecl *Param, 
+                             const TemplateArgumentLoc &Arg);
+  
+  /// \brief Enumeration describing how template parameter lists are compared
+  /// for equality.
+  enum TemplateParameterListEqualKind {
+    /// \brief We are matching the template parameter lists of two templates
+    /// that might be redeclarations.
+    ///
+    /// \code
+    /// template<typename T> struct X;
+    /// template<typename T> struct X;
+    /// \endcode
+    TPL_TemplateMatch,
+    
+    /// \brief We are matching the template parameter lists of two template
+    /// template parameters as part of matching the template parameter lists
+    /// of two templates that might be redeclarations.
+    ///
+    /// \code
+    /// template<template<int I> class TT> struct X;
+    /// template<template<int Value> class Other> struct X;
+    /// \endcode
+    TPL_TemplateTemplateParmMatch,
+    
+    /// \brief We are matching the template parameter lists of a template
+    /// template argument against the template parameter lists of a template
+    /// template parameter.
+    ///
+    /// \code
+    /// template<template<int Value> class Metafun> struct X;
+    /// template<int Value> struct integer_c;
+    /// X<integer_c> xic;
+    /// \endcode
+    TPL_TemplateTemplateArgumentMatch
+  };
+  
+  bool TemplateParameterListsAreEqual(TemplateParameterList *New,
+                                      TemplateParameterList *Old,
+                                      bool Complain,
+                                      TemplateParameterListEqualKind Kind,
+                                      SourceLocation TemplateArgLoc
+                                        = SourceLocation());
+
+  bool CheckTemplateDeclScope(Scope *S, TemplateParameterList *TemplateParams);
+
+  /// \brief Called when the parser has parsed a C++ typename
+  /// specifier, e.g., "typename T::type".
+  ///
+  /// \param TypenameLoc the location of the 'typename' keyword
+  /// \param SS the nested-name-specifier following the typename (e.g., 'T::').
+  /// \param II the identifier we're retrieving (e.g., 'type' in the example).
+  /// \param IdLoc the location of the identifier.
+  virtual TypeResult
+  ActOnTypenameType(SourceLocation TypenameLoc, const CXXScopeSpec &SS,
+                    const IdentifierInfo &II, SourceLocation IdLoc);
+
+  /// \brief Called when the parser has parsed a C++ typename
+  /// specifier that ends in a template-id, e.g.,
+  /// "typename MetaFun::template apply<T1, T2>".
+  ///
+  /// \param TypenameLoc the location of the 'typename' keyword
+  /// \param SS the nested-name-specifier following the typename (e.g., 'T::').
+  /// \param TemplateLoc the location of the 'template' keyword, if any.
+  /// \param Ty the type that the typename specifier refers to.
+  virtual TypeResult
+  ActOnTypenameType(SourceLocation TypenameLoc, const CXXScopeSpec &SS,
+                    SourceLocation TemplateLoc, TypeTy *Ty);
+
+  QualType CheckTypenameType(NestedNameSpecifier *NNS,
+                             const IdentifierInfo &II,
+                             SourceRange Range);
+
+  QualType RebuildTypeInCurrentInstantiation(QualType T, SourceLocation Loc,
+                                             DeclarationName Name);
+
+  std::string
+  getTemplateArgumentBindingsText(const TemplateParameterList *Params,
+                                  const TemplateArgumentList &Args);
+
+  std::string
+  getTemplateArgumentBindingsText(const TemplateParameterList *Params,
+                                  const TemplateArgument *Args,
+                                  unsigned NumArgs);
+  
+  /// \brief Describes the result of template argument deduction.
+  ///
+  /// The TemplateDeductionResult enumeration describes the result of
+  /// template argument deduction, as returned from
+  /// DeduceTemplateArguments(). The separate TemplateDeductionInfo
+  /// structure provides additional information about the results of
+  /// template argument deduction, e.g., the deduced template argument
+  /// list (if successful) or the specific template parameters or
+  /// deduced arguments that were involved in the failure.
+  enum TemplateDeductionResult {
+    /// \brief Template argument deduction was successful.
+    TDK_Success = 0,
+    /// \brief Template argument deduction exceeded the maximum template
+    /// instantiation depth (which has already been diagnosed).
+    TDK_InstantiationDepth,
+    /// \brief Template argument deduction did not deduce a value
+    /// for every template parameter.
+    TDK_Incomplete,
+    /// \brief Template argument deduction produced inconsistent
+    /// deduced values for the given template parameter.
+    TDK_Inconsistent,
+    /// \brief Template argument deduction failed due to inconsistent
+    /// cv-qualifiers on a template parameter type that would
+    /// otherwise be deduced, e.g., we tried to deduce T in "const T"
+    /// but were given a non-const "X".
+    TDK_InconsistentQuals,
+    /// \brief Substitution of the deduced template argument values
+    /// resulted in an error.
+    TDK_SubstitutionFailure,
+    /// \brief Substitution of the deduced template argument values
+    /// into a non-deduced context produced a type or value that
+    /// produces a type that does not match the original template
+    /// arguments provided.
+    TDK_NonDeducedMismatch,
+    /// \brief When performing template argument deduction for a function
+    /// template, there were too many call arguments.
+    TDK_TooManyArguments,
+    /// \brief When performing template argument deduction for a function
+    /// template, there were too few call arguments.
+    TDK_TooFewArguments,
+    /// \brief The explicitly-specified template arguments were not valid
+    /// template arguments for the given template.
+    TDK_InvalidExplicitArguments,
+    /// \brief The arguments included an overloaded function name that could
+    /// not be resolved to a suitable function.
+    TDK_FailedOverloadResolution
+  };
+
+  /// \brief Provides information about an attempted template argument
+  /// deduction, whose success or failure was described by a
+  /// TemplateDeductionResult value.
+  class TemplateDeductionInfo {
+    /// \brief The context in which the template arguments are stored.
+    ASTContext &Context;
+
+    /// \brief The deduced template argument list.
+    ///
+    TemplateArgumentList *Deduced;
+
+    /// \brief The source location at which template argument
+    /// deduction is occurring.
+    SourceLocation Loc;
+
+    // do not implement these
+    TemplateDeductionInfo(const TemplateDeductionInfo&);
+    TemplateDeductionInfo &operator=(const TemplateDeductionInfo&);
+
+  public:
+    TemplateDeductionInfo(ASTContext &Context, SourceLocation Loc)
+      : Context(Context), Deduced(0), Loc(Loc) { }
+
+    ~TemplateDeductionInfo() {
+      // FIXME: if (Deduced) Deduced->Destroy(Context);
+    }
+
+    /// \brief Returns the location at which template argument is
+    /// occuring.
+    SourceLocation getLocation() const {
+      return Loc;
+    }
+
+    /// \brief Take ownership of the deduced template argument list.
+    TemplateArgumentList *take() {
+      TemplateArgumentList *Result = Deduced;
+      Deduced = 0;
+      return Result;
+    }
+
+    /// \brief Provide a new template argument list that contains the
+    /// results of template argument deduction.
+    void reset(TemplateArgumentList *NewDeduced) {
+      // FIXME: if (Deduced) Deduced->Destroy(Context);
+      Deduced = NewDeduced;
+    }
+
+    /// \brief The template parameter to which a template argument
+    /// deduction failure refers.
+    ///
+    /// Depending on the result of template argument deduction, this
+    /// template parameter may have different meanings:
+    ///
+    ///   TDK_Incomplete: this is the first template parameter whose
+    ///   corresponding template argument was not deduced.
+    ///
+    ///   TDK_Inconsistent: this is the template parameter for which
+    ///   two different template argument values were deduced.
+    TemplateParameter Param;
+
+    /// \brief The first template argument to which the template
+    /// argument deduction failure refers.
+    ///
+    /// Depending on the result of the template argument deduction,
+    /// this template argument may have different meanings:
+    ///
+    ///   TDK_Inconsistent: this argument is the first value deduced
+    ///   for the corresponding template parameter.
+    ///
+    ///   TDK_SubstitutionFailure: this argument is the template
+    ///   argument we were instantiating when we encountered an error.
+    ///
+    ///   TDK_NonDeducedMismatch: this is the template argument
+    ///   provided in the source code.
+    TemplateArgument FirstArg;
+
+    /// \brief The second template argument to which the template
+    /// argument deduction failure refers.
+    ///
+    /// FIXME: Finish documenting this.
+    TemplateArgument SecondArg;
+  };
+
+  TemplateDeductionResult
+  DeduceTemplateArguments(ClassTemplatePartialSpecializationDecl *Partial,
+                          const TemplateArgumentList &TemplateArgs,
+                          TemplateDeductionInfo &Info);
+
+  TemplateDeductionResult
+  SubstituteExplicitTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
+                        const TemplateArgumentListInfo &ExplicitTemplateArgs,
+                            llvm::SmallVectorImpl<TemplateArgument> &Deduced,
+                                 llvm::SmallVectorImpl<QualType> &ParamTypes,
+                                      QualType *FunctionType,
+                                      TemplateDeductionInfo &Info);
+
+  TemplateDeductionResult
+  FinishTemplateArgumentDeduction(FunctionTemplateDecl *FunctionTemplate,
+                             llvm::SmallVectorImpl<TemplateArgument> &Deduced,
+                                  FunctionDecl *&Specialization,
+                                  TemplateDeductionInfo &Info);
+
+  TemplateDeductionResult
+  DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
+                          const TemplateArgumentListInfo *ExplicitTemplateArgs,
+                          Expr **Args, unsigned NumArgs,
+                          FunctionDecl *&Specialization,
+                          TemplateDeductionInfo &Info);
+
+  TemplateDeductionResult
+  DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
+                          const TemplateArgumentListInfo *ExplicitTemplateArgs,
+                          QualType ArgFunctionType,
+                          FunctionDecl *&Specialization,
+                          TemplateDeductionInfo &Info);
+
+  TemplateDeductionResult
+  DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
+                          QualType ToType,
+                          CXXConversionDecl *&Specialization,
+                          TemplateDeductionInfo &Info);
+
+  TemplateDeductionResult
+  DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
+                          const TemplateArgumentListInfo *ExplicitTemplateArgs,
+                          FunctionDecl *&Specialization,
+                          TemplateDeductionInfo &Info);
+
+  FunctionTemplateDecl *getMoreSpecializedTemplate(FunctionTemplateDecl *FT1,
+                                                   FunctionTemplateDecl *FT2,
+                                                   SourceLocation Loc,
+                                           TemplatePartialOrderingContext TPOC);
+  UnresolvedSetIterator getMostSpecialized(UnresolvedSetIterator SBegin,
+                                           UnresolvedSetIterator SEnd,
+                                           TemplatePartialOrderingContext TPOC,
+                                           SourceLocation Loc,
+                                           const PartialDiagnostic &NoneDiag,
+                                           const PartialDiagnostic &AmbigDiag,
+                                        const PartialDiagnostic &CandidateDiag);
+                                   
+  ClassTemplatePartialSpecializationDecl *
+  getMoreSpecializedPartialSpecialization(
+                                  ClassTemplatePartialSpecializationDecl *PS1,
+                                  ClassTemplatePartialSpecializationDecl *PS2,
+                                  SourceLocation Loc);
+  
+  void MarkUsedTemplateParameters(const TemplateArgumentList &TemplateArgs,
+                                  bool OnlyDeduced,
+                                  unsigned Depth,
+                                  llvm::SmallVectorImpl<bool> &Used);
+  void MarkDeducedTemplateParameters(FunctionTemplateDecl *FunctionTemplate,
+                                     llvm::SmallVectorImpl<bool> &Deduced);
+  
+  //===--------------------------------------------------------------------===//
+  // C++ Template Instantiation
+  //
+
+  MultiLevelTemplateArgumentList getTemplateInstantiationArgs(NamedDecl *D,
+                                     const TemplateArgumentList *Innermost = 0,
+                                     bool RelativeToPrimary = false);
+
+  /// \brief A template instantiation that is currently in progress.
+  struct ActiveTemplateInstantiation {
+    /// \brief The kind of template instantiation we are performing
+    enum InstantiationKind {
+      /// We are instantiating a template declaration. The entity is
+      /// the declaration we're instantiating (e.g., a CXXRecordDecl).
+      TemplateInstantiation,
+
+      /// We are instantiating a default argument for a template
+      /// parameter. The Entity is the template, and
+      /// TemplateArgs/NumTemplateArguments provides the template
+      /// arguments as specified.
+      /// FIXME: Use a TemplateArgumentList
+      DefaultTemplateArgumentInstantiation,
+
+      /// We are instantiating a default argument for a function.
+      /// The Entity is the ParmVarDecl, and TemplateArgs/NumTemplateArgs
+      /// provides the template arguments as specified.
+      DefaultFunctionArgumentInstantiation,
+
+      /// We are substituting explicit template arguments provided for
+      /// a function template. The entity is a FunctionTemplateDecl.
+      ExplicitTemplateArgumentSubstitution,
+
+      /// We are substituting template argument determined as part of
+      /// template argument deduction for either a class template
+      /// partial specialization or a function template. The
+      /// Entity is either a ClassTemplatePartialSpecializationDecl or
+      /// a FunctionTemplateDecl.
+      DeducedTemplateArgumentSubstitution,
+      
+      /// We are substituting prior template arguments into a new
+      /// template parameter. The template parameter itself is either a
+      /// NonTypeTemplateParmDecl or a TemplateTemplateParmDecl.
+      PriorTemplateArgumentSubstitution,
+      
+      /// We are checking the validity of a default template argument that
+      /// has been used when naming a template-id.
+      DefaultTemplateArgumentChecking
+    } Kind;
+
+    /// \brief The point of instantiation within the source code.
+    SourceLocation PointOfInstantiation;
+
+    /// \brief The template in which we are performing the instantiation,
+    /// for substitutions of prior template arguments.
+    TemplateDecl *Template;
+    
+    /// \brief The entity that is being instantiated.
+    uintptr_t Entity;
+
+    /// \brief The list of template arguments we are substituting, if they
+    /// are not part of the entity.
+    const TemplateArgument *TemplateArgs;
+
+    /// \brief The number of template arguments in TemplateArgs.
+    unsigned NumTemplateArgs;
+
+    /// \brief The source range that covers the construct that cause
+    /// the instantiation, e.g., the template-id that causes a class
+    /// template instantiation.
+    SourceRange InstantiationRange;
+
+    ActiveTemplateInstantiation()
+      : Kind(TemplateInstantiation), Template(0), Entity(0), TemplateArgs(0), 
+        NumTemplateArgs(0) {}
+
+    /// \brief Determines whether this template is an actual instantiation
+    /// that should be counted toward the maximum instantiation depth.
+    bool isInstantiationRecord() const;
+    
+    friend bool operator==(const ActiveTemplateInstantiation &X,
+                           const ActiveTemplateInstantiation &Y) {
+      if (X.Kind != Y.Kind)
+        return false;
+
+      if (X.Entity != Y.Entity)
+        return false;
+
+      switch (X.Kind) {
+      case TemplateInstantiation:
+        return true;
+
+      case PriorTemplateArgumentSubstitution:
+      case DefaultTemplateArgumentChecking:
+        if (X.Template != Y.Template)
+          return false;
+          
+        // Fall through
+          
+      case DefaultTemplateArgumentInstantiation:
+      case ExplicitTemplateArgumentSubstitution:
+      case DeducedTemplateArgumentSubstitution:
+      case DefaultFunctionArgumentInstantiation:
+        return X.TemplateArgs == Y.TemplateArgs;
+
+      }
+
+      return true;
+    }
+
+    friend bool operator!=(const ActiveTemplateInstantiation &X,
+                           const ActiveTemplateInstantiation &Y) {
+      return !(X == Y);
+    }
+  };
+
+  /// \brief List of active template instantiations.
+  ///
+  /// This vector is treated as a stack. As one template instantiation
+  /// requires another template instantiation, additional
+  /// instantiations are pushed onto the stack up to a
+  /// user-configurable limit LangOptions::InstantiationDepth.
+  llvm::SmallVector<ActiveTemplateInstantiation, 16>
+    ActiveTemplateInstantiations;
+
+  /// \brief The number of ActiveTemplateInstantiation entries in
+  /// \c ActiveTemplateInstantiations that are not actual instantiations and,
+  /// therefore, should not be counted as part of the instantiation depth.
+  unsigned NonInstantiationEntries;
+  
+  /// \brief The last template from which a template instantiation
+  /// error or warning was produced.
+  ///
+  /// This value is used to suppress printing of redundant template
+  /// instantiation backtraces when there are multiple errors in the
+  /// same instantiation. FIXME: Does this belong in Sema? It's tough
+  /// to implement it anywhere else.
+  ActiveTemplateInstantiation LastTemplateInstantiationErrorContext;
+
+  /// \brief A stack object to be created when performing template
+  /// instantiation.
+  ///
+  /// Construction of an object of type \c InstantiatingTemplate
+  /// pushes the current instantiation onto the stack of active
+  /// instantiations. If the size of this stack exceeds the maximum
+  /// number of recursive template instantiations, construction
+  /// produces an error and evaluates true.
+  ///
+  /// Destruction of this object will pop the named instantiation off
+  /// the stack.
+  struct InstantiatingTemplate {
+    /// \brief Note that we are instantiating a class template,
+    /// function template, or a member thereof.
+    InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
+                          Decl *Entity,
+                          SourceRange InstantiationRange = SourceRange());
+
+    /// \brief Note that we are instantiating a default argument in a
+    /// template-id.
+    InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
+                          TemplateDecl *Template,
+                          const TemplateArgument *TemplateArgs,
+                          unsigned NumTemplateArgs,
+                          SourceRange InstantiationRange = SourceRange());
+
+    /// \brief Note that we are instantiating a default argument in a
+    /// template-id.
+    InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
+                          FunctionTemplateDecl *FunctionTemplate,
+                          const TemplateArgument *TemplateArgs,
+                          unsigned NumTemplateArgs,
+                          ActiveTemplateInstantiation::InstantiationKind Kind,
+                          SourceRange InstantiationRange = SourceRange());
+
+    /// \brief Note that we are instantiating as part of template
+    /// argument deduction for a class template partial
+    /// specialization.
+    InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
+                          ClassTemplatePartialSpecializationDecl *PartialSpec,
+                          const TemplateArgument *TemplateArgs,
+                          unsigned NumTemplateArgs,
+                          SourceRange InstantiationRange = SourceRange());
+
+    InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
+                          ParmVarDecl *Param,
+                          const TemplateArgument *TemplateArgs,
+                          unsigned NumTemplateArgs,
+                          SourceRange InstantiationRange = SourceRange());
+
+    /// \brief Note that we are substituting prior template arguments into a
+    /// non-type or template template parameter.
+    InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
+                          TemplateDecl *Template,
+                          NonTypeTemplateParmDecl *Param,
+                          const TemplateArgument *TemplateArgs,
+                          unsigned NumTemplateArgs,
+                          SourceRange InstantiationRange);
+
+    InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
+                          TemplateDecl *Template,
+                          TemplateTemplateParmDecl *Param,
+                          const TemplateArgument *TemplateArgs,
+                          unsigned NumTemplateArgs,
+                          SourceRange InstantiationRange);
+    
+    /// \brief Note that we are checking the default template argument
+    /// against the template parameter for a given template-id.
+    InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
+                          TemplateDecl *Template,
+                          NamedDecl *Param,
+                          const TemplateArgument *TemplateArgs,
+                          unsigned NumTemplateArgs,
+                          SourceRange InstantiationRange);
+    
+    
+    /// \brief Note that we have finished instantiating this template.
+    void Clear();
+
+    ~InstantiatingTemplate() { Clear(); }
+
+    /// \brief Determines whether we have exceeded the maximum
+    /// recursive template instantiations.
+    operator bool() const { return Invalid; }
+
+  private:
+    Sema &SemaRef;
+    bool Invalid;
+
+    bool CheckInstantiationDepth(SourceLocation PointOfInstantiation,
+                                 SourceRange InstantiationRange);
+
+    InstantiatingTemplate(const InstantiatingTemplate&); // not implemented
+
+    InstantiatingTemplate&
+    operator=(const InstantiatingTemplate&); // not implemented
+  };
+
+  void PrintInstantiationStack();
+
+  /// \brief Determines whether we are currently in a context where
+  /// template argument substitution failures are not considered
+  /// errors.
+  ///
+  /// When this routine returns true, the emission of most diagnostics
+  /// will be suppressed and there will be no local error recovery.
+  bool isSFINAEContext() const;
+
+  /// \brief RAII class used to determine whether SFINAE has
+  /// trapped any errors that occur during template argument
+  /// deduction.
+  class SFINAETrap {
+    Sema &SemaRef;
+    unsigned PrevSFINAEErrors;
+  public:
+    explicit SFINAETrap(Sema &SemaRef)
+      : SemaRef(SemaRef), PrevSFINAEErrors(SemaRef.NumSFINAEErrors) { }
+
+    ~SFINAETrap() { SemaRef.NumSFINAEErrors = PrevSFINAEErrors; }
+
+    /// \brief Determine whether any SFINAE errors have been trapped.
+    bool hasErrorOccurred() const {
+      return SemaRef.NumSFINAEErrors > PrevSFINAEErrors;
+    }
+  };
+
+  /// \brief A stack-allocated class that identifies which local
+  /// variable declaration instantiations are present in this scope.
+  ///
+  /// A new instance of this class type will be created whenever we
+  /// instantiate a new function declaration, which will have its own
+  /// set of parameter declarations.
+  class LocalInstantiationScope {
+    /// \brief Reference to the semantic analysis that is performing
+    /// this template instantiation.
+    Sema &SemaRef;
+
+    /// \brief A mapping from local declarations that occur
+    /// within a template to their instantiations.
+    ///
+    /// This mapping is used during instantiation to keep track of,
+    /// e.g., function parameter and variable declarations. For example,
+    /// given:
+    ///
+    /// \code
+    ///   template<typename T> T add(T x, T y) { return x + y; }
+    /// \endcode
+    ///
+    /// when we instantiate add<int>, we will introduce a mapping from
+    /// the ParmVarDecl for 'x' that occurs in the template to the
+    /// instantiated ParmVarDecl for 'x'.
+    llvm::DenseMap<const Decl *, Decl *> LocalDecls;
+
+    /// \brief The outer scope, in which contains local variable
+    /// definitions from some other instantiation (that may not be
+    /// relevant to this particular scope).
+    LocalInstantiationScope *Outer;
+
+    /// \brief Whether we have already exited this scope.
+    bool Exited;
+
+    // This class is non-copyable
+    LocalInstantiationScope(const LocalInstantiationScope &);
+    LocalInstantiationScope &operator=(const LocalInstantiationScope &);
+
+  public:
+    LocalInstantiationScope(Sema &SemaRef, bool CombineWithOuterScope = false)
+      : SemaRef(SemaRef), Outer(SemaRef.CurrentInstantiationScope), 
+        Exited(false) {
+      if (!CombineWithOuterScope)
+        SemaRef.CurrentInstantiationScope = this;
+      else
+        assert(SemaRef.CurrentInstantiationScope && 
+               "No outer instantiation scope?");
+    }
+
+    ~LocalInstantiationScope() {
+      if (!Exited)
+        SemaRef.CurrentInstantiationScope = Outer;
+    }
+
+    /// \brief Exit this local instantiation scope early.
+    void Exit() {
+      SemaRef.CurrentInstantiationScope = Outer;
+      LocalDecls.clear();
+      Exited = true;
+    }
+
+    Decl *getInstantiationOf(const Decl *D) {
+      Decl *Result = LocalDecls[D];
+      assert(Result && "declaration was not instantiated in this scope!");
+      return Result;
+    }
+
+    VarDecl *getInstantiationOf(const VarDecl *Var) {
+      return cast<VarDecl>(getInstantiationOf(cast<Decl>(Var)));
+    }
+
+    ParmVarDecl *getInstantiationOf(const ParmVarDecl *Var) {
+      return cast<ParmVarDecl>(getInstantiationOf(cast<Decl>(Var)));
+    }
+
+    NonTypeTemplateParmDecl *getInstantiationOf(
+                                          const NonTypeTemplateParmDecl *Var) {
+      return cast<NonTypeTemplateParmDecl>(getInstantiationOf(cast<Decl>(Var)));
+    }
+    
+    void InstantiatedLocal(const Decl *D, Decl *Inst) {
+      Decl *&Stored = LocalDecls[D];
+      assert(!Stored && "Already instantiated this local");
+      Stored = Inst;
+    }
+  };
+
+  /// \brief The current instantiation scope used to store local
+  /// variables.
+  LocalInstantiationScope *CurrentInstantiationScope;
+
+  /// \brief The number of typos corrected by CorrectTypo.
+  unsigned TyposCorrected;
+
+  /// \brief An entity for which implicit template instantiation is required.
+  ///
+  /// The source location associated with the declaration is the first place in
+  /// the source code where the declaration was "used". It is not necessarily
+  /// the point of instantiation (which will be either before or after the
+  /// namespace-scope declaration that triggered this implicit instantiation),
+  /// However, it is the location that diagnostics should generally refer to,
+  /// because users will need to know what code triggered the instantiation.
+  typedef std::pair<ValueDecl *, SourceLocation> PendingImplicitInstantiation;
+
+  /// \brief The queue of implicit template instantiations that are required
+  /// but have not yet been performed.
+  std::deque<PendingImplicitInstantiation> PendingImplicitInstantiations;
+
+  /// \brief The queue of implicit template instantiations that are required
+  /// and must be performed within the current local scope.
+  ///
+  /// This queue is only used for member functions of local classes in
+  /// templates, which must be instantiated in the same scope as their
+  /// enclosing function, so that they can reference function-local
+  /// types, static variables, enumerators, etc.
+  std::deque<PendingImplicitInstantiation> PendingLocalImplicitInstantiations;
+
+  void PerformPendingImplicitInstantiations(bool LocalOnly = false);
+
+  TypeSourceInfo *SubstType(TypeSourceInfo *T,
+                            const MultiLevelTemplateArgumentList &TemplateArgs,
+                            SourceLocation Loc, DeclarationName Entity);
+
+  QualType SubstType(QualType T,
+                     const MultiLevelTemplateArgumentList &TemplateArgs,
+                     SourceLocation Loc, DeclarationName Entity);
+
+  OwningExprResult SubstExpr(Expr *E,
+                            const MultiLevelTemplateArgumentList &TemplateArgs);
+
+  OwningStmtResult SubstStmt(Stmt *S,
+                            const MultiLevelTemplateArgumentList &TemplateArgs);
+
+  Decl *SubstDecl(Decl *D, DeclContext *Owner,
+                  const MultiLevelTemplateArgumentList &TemplateArgs);
+
+  bool
+  SubstBaseSpecifiers(CXXRecordDecl *Instantiation,
+                      CXXRecordDecl *Pattern,
+                      const MultiLevelTemplateArgumentList &TemplateArgs);
+
+  bool
+  InstantiateClass(SourceLocation PointOfInstantiation,
+                   CXXRecordDecl *Instantiation, CXXRecordDecl *Pattern,
+                   const MultiLevelTemplateArgumentList &TemplateArgs,
+                   TemplateSpecializationKind TSK,
+                   bool Complain = true);
+
+  bool
+  InstantiateClassTemplateSpecialization(SourceLocation PointOfInstantiation,
+                           ClassTemplateSpecializationDecl *ClassTemplateSpec,
+                           TemplateSpecializationKind TSK,
+                           bool Complain = true);
+
+  void InstantiateClassMembers(SourceLocation PointOfInstantiation,
+                               CXXRecordDecl *Instantiation,
+                            const MultiLevelTemplateArgumentList &TemplateArgs,
+                               TemplateSpecializationKind TSK);
+
+  void InstantiateClassTemplateSpecializationMembers(
+                                          SourceLocation PointOfInstantiation,
+                           ClassTemplateSpecializationDecl *ClassTemplateSpec,
+                                                TemplateSpecializationKind TSK);
+
+  NestedNameSpecifier *
+  SubstNestedNameSpecifier(NestedNameSpecifier *NNS,
+                           SourceRange Range,
+                           const MultiLevelTemplateArgumentList &TemplateArgs);
+
+  TemplateName
+  SubstTemplateName(TemplateName Name, SourceLocation Loc,
+                    const MultiLevelTemplateArgumentList &TemplateArgs);
+  bool Subst(const TemplateArgumentLoc &Arg, TemplateArgumentLoc &Result,
+             const MultiLevelTemplateArgumentList &TemplateArgs);
+
+  void InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,
+                                     FunctionDecl *Function,
+                                     bool Recursive = false,
+                                     bool DefinitionRequired = false);
+  void InstantiateStaticDataMemberDefinition(
+                                     SourceLocation PointOfInstantiation,
+                                     VarDecl *Var,
+                                     bool Recursive = false,
+                                     bool DefinitionRequired = false);
+
+  void InstantiateMemInitializers(CXXConstructorDecl *New,
+                                  const CXXConstructorDecl *Tmpl,
+                            const MultiLevelTemplateArgumentList &TemplateArgs);
+
+  NamedDecl *FindInstantiatedDecl(NamedDecl *D,
+                          const MultiLevelTemplateArgumentList &TemplateArgs);
+  DeclContext *FindInstantiatedContext(DeclContext *DC,
+                          const MultiLevelTemplateArgumentList &TemplateArgs);
+
+  // Objective-C declarations.
+  virtual DeclPtrTy ActOnStartClassInterface(SourceLocation AtInterfaceLoc,
+                                             IdentifierInfo *ClassName,
+                                             SourceLocation ClassLoc,
+                                             IdentifierInfo *SuperName,
+                                             SourceLocation SuperLoc,
+                                             const DeclPtrTy *ProtoRefs,
+                                             unsigned NumProtoRefs,
+                                             const SourceLocation *ProtoLocs,
+                                             SourceLocation EndProtoLoc,
+                                             AttributeList *AttrList);
+
+  virtual DeclPtrTy ActOnCompatiblityAlias(
+                    SourceLocation AtCompatibilityAliasLoc,
+                    IdentifierInfo *AliasName,  SourceLocation AliasLocation,
+                    IdentifierInfo *ClassName, SourceLocation ClassLocation);
+
+  void CheckForwardProtocolDeclarationForCircularDependency(
+    IdentifierInfo *PName,
+    SourceLocation &PLoc, SourceLocation PrevLoc,
+    const ObjCList<ObjCProtocolDecl> &PList);
+
+  virtual DeclPtrTy ActOnStartProtocolInterface(
+                    SourceLocation AtProtoInterfaceLoc,
+                    IdentifierInfo *ProtocolName, SourceLocation ProtocolLoc,
+                    const DeclPtrTy *ProtoRefNames, unsigned NumProtoRefs,
+                    const SourceLocation *ProtoLocs,
+                    SourceLocation EndProtoLoc,
+                    AttributeList *AttrList);
+
+  virtual DeclPtrTy ActOnStartCategoryInterface(SourceLocation AtInterfaceLoc,
+                                                IdentifierInfo *ClassName,
+                                                SourceLocation ClassLoc,
+                                                IdentifierInfo *CategoryName,
+                                                SourceLocation CategoryLoc,
+                                                const DeclPtrTy *ProtoRefs,
+                                                unsigned NumProtoRefs,
+                                                const SourceLocation *ProtoLocs,
+                                                SourceLocation EndProtoLoc);
+
+  virtual DeclPtrTy ActOnStartClassImplementation(
+                    SourceLocation AtClassImplLoc,
+                    IdentifierInfo *ClassName, SourceLocation ClassLoc,
+                    IdentifierInfo *SuperClassname,
+                    SourceLocation SuperClassLoc);
+
+  virtual DeclPtrTy ActOnStartCategoryImplementation(
+                                                  SourceLocation AtCatImplLoc,
+                                                  IdentifierInfo *ClassName,
+                                                  SourceLocation ClassLoc,
+                                                  IdentifierInfo *CatName,
+                                                  SourceLocation CatLoc);
+
+  virtual DeclPtrTy ActOnForwardClassDeclaration(SourceLocation Loc,
+                                                 IdentifierInfo **IdentList,
+                                                 SourceLocation *IdentLocs,
+                                                 unsigned NumElts);
+
+  virtual DeclPtrTy ActOnForwardProtocolDeclaration(SourceLocation AtProtocolLoc,
+                                            const IdentifierLocPair *IdentList,
+                                                  unsigned NumElts,
+                                                  AttributeList *attrList);
+
+  virtual void FindProtocolDeclaration(bool WarnOnDeclarations,
+                                       const IdentifierLocPair *ProtocolId,
+                                       unsigned NumProtocols,
+                                   llvm::SmallVectorImpl<DeclPtrTy> &Protocols);
+
+  /// Ensure attributes are consistent with type.
+  /// \param [in, out] Attributes The attributes to check; they will
+  /// be modified to be consistent with \arg PropertyTy.
+  void CheckObjCPropertyAttributes(QualType PropertyTy,
+                                   SourceLocation Loc,
+                                   unsigned &Attributes);
+  void ProcessPropertyDecl(ObjCPropertyDecl *property, ObjCContainerDecl *DC);
+  void DiagnosePropertyMismatch(ObjCPropertyDecl *Property,
+                                ObjCPropertyDecl *SuperProperty,
+                                const IdentifierInfo *Name);
+  void ComparePropertiesInBaseAndSuper(ObjCInterfaceDecl *IDecl);
+
+  void CompareMethodParamsInBaseAndSuper(Decl *IDecl,
+                                         ObjCMethodDecl *MethodDecl,
+                                         bool IsInstance);
+
+  void CompareProperties(Decl *CDecl, DeclPtrTy MergeProtocols);
+
+  void DiagnoseClassExtensionDupMethods(ObjCCategoryDecl *CAT,
+                                        ObjCInterfaceDecl *ID);
+
+  void MatchOneProtocolPropertiesInClass(Decl *CDecl,
+                                         ObjCProtocolDecl *PDecl);
+
+  virtual void ActOnAtEnd(SourceRange AtEnd,
+                          DeclPtrTy classDecl,
+                          DeclPtrTy *allMethods = 0, unsigned allNum = 0,
+                          DeclPtrTy *allProperties = 0, unsigned pNum = 0,
+                          DeclGroupPtrTy *allTUVars = 0, unsigned tuvNum = 0);
+
+  virtual DeclPtrTy ActOnProperty(Scope *S, SourceLocation AtLoc,
+                                  FieldDeclarator &FD, ObjCDeclSpec &ODS,
+                                  Selector GetterSel, Selector SetterSel,
+                                  DeclPtrTy ClassCategory,
+                                  bool *OverridingProperty,
+                                  tok::ObjCKeywordKind MethodImplKind);
+
+  virtual DeclPtrTy ActOnPropertyImplDecl(SourceLocation AtLoc,
+                                          SourceLocation PropertyLoc,
+                                          bool ImplKind,DeclPtrTy ClassImplDecl,
+                                          IdentifierInfo *PropertyId,
+                                          IdentifierInfo *PropertyIvar);
+
+  virtual DeclPtrTy ActOnMethodDeclaration(
+    SourceLocation BeginLoc, // location of the + or -.
+    SourceLocation EndLoc,   // location of the ; or {.
+    tok::TokenKind MethodType,
+    DeclPtrTy ClassDecl, ObjCDeclSpec &ReturnQT, TypeTy *ReturnType,
+    Selector Sel,
+    // optional arguments. The number of types/arguments is obtained
+    // from the Sel.getNumArgs().
+    ObjCArgInfo *ArgInfo,
+    llvm::SmallVectorImpl<Declarator> &Cdecls,
+    AttributeList *AttrList, tok::ObjCKeywordKind MethodImplKind,
+    bool isVariadic = false);
+
+  // Helper method for ActOnClassMethod/ActOnInstanceMethod.
+  // Will search "local" class/category implementations for a method decl.
+  // Will also search in class's root looking for instance method.
+  // Returns 0 if no method is found.
+  ObjCMethodDecl *LookupPrivateClassMethod(Selector Sel,
+                                           ObjCInterfaceDecl *CDecl);
+  ObjCMethodDecl *LookupPrivateInstanceMethod(Selector Sel,
+                                              ObjCInterfaceDecl *ClassDecl);
+
+  virtual OwningExprResult ActOnClassPropertyRefExpr(
+    IdentifierInfo &receiverName,
+    IdentifierInfo &propertyName,
+    SourceLocation &receiverNameLoc,
+    SourceLocation &propertyNameLoc);
+
+  // ActOnClassMessage - used for both unary and keyword messages.
+  // ArgExprs is optional - if it is present, the number of expressions
+  // is obtained from NumArgs.
+  virtual ExprResult ActOnClassMessage(
+    Scope *S,
+    IdentifierInfo *receivingClassName, Selector Sel, SourceLocation lbrac,
+    SourceLocation receiverLoc, SourceLocation selectorLoc,SourceLocation rbrac,
+    ExprTy **ArgExprs, unsigned NumArgs);
+
+  // ActOnInstanceMessage - used for both unary and keyword messages.
+  // ArgExprs is optional - if it is present, the number of expressions
+  // is obtained from NumArgs.
+  virtual ExprResult ActOnInstanceMessage(
+    ExprTy *receiver, Selector Sel,
+    SourceLocation lbrac, SourceLocation receiverLoc, SourceLocation rbrac,
+    ExprTy **ArgExprs, unsigned NumArgs);
+
+  /// ActOnPragmaPack - Called on well formed #pragma pack(...).
+  virtual void ActOnPragmaPack(PragmaPackKind Kind,
+                               IdentifierInfo *Name,
+                               ExprTy *Alignment,
+                               SourceLocation PragmaLoc,
+                               SourceLocation LParenLoc,
+                               SourceLocation RParenLoc);
+
+  /// ActOnPragmaUnused - Called on well-formed '#pragma unused'.
+  virtual void ActOnPragmaUnused(const Token *Identifiers,
+                                 unsigned NumIdentifiers, Scope *curScope,
+                                 SourceLocation PragmaLoc,
+                                 SourceLocation LParenLoc,
+                                 SourceLocation RParenLoc);
+
+  NamedDecl *DeclClonePragmaWeak(NamedDecl *ND, IdentifierInfo *II);
+  void DeclApplyPragmaWeak(Scope *S, NamedDecl *ND, WeakInfo &W);
+
+  /// ActOnPragmaWeakID - Called on well formed #pragma weak ident.
+  virtual void ActOnPragmaWeakID(IdentifierInfo* WeakName,
+                                 SourceLocation PragmaLoc,
+                                 SourceLocation WeakNameLoc);
+
+  /// ActOnPragmaWeakAlias - Called on well formed #pragma weak ident = ident.
+  virtual void ActOnPragmaWeakAlias(IdentifierInfo* WeakName,
+                                    IdentifierInfo* AliasName,
+                                    SourceLocation PragmaLoc,
+                                    SourceLocation WeakNameLoc,
+                                    SourceLocation AliasNameLoc);
+
+  /// getPragmaPackAlignment() - Return the current alignment as specified by
+  /// the current #pragma pack directive, or 0 if none is currently active.
+  unsigned getPragmaPackAlignment() const;
+
+  /// FreePackedContext - Deallocate and null out PackContext.
+  void FreePackedContext();
+
+  /// ImpCastExprToType - If Expr is not of type 'Type', insert an implicit
+  /// cast.  If there is already an implicit cast, merge into the existing one.
+  /// If isLvalue, the result of the cast is an lvalue.
+  void ImpCastExprToType(Expr *&Expr, QualType Type, CastExpr::CastKind Kind,
+                         bool isLvalue = false);
+
+  // UsualUnaryConversions - promotes integers (C99 6.3.1.1p2) and converts
+  // functions and arrays to their respective pointers (C99 6.3.2.1).
+  Expr *UsualUnaryConversions(Expr *&expr);
+
+  // DefaultFunctionArrayConversion - converts functions and arrays
+  // to their respective pointers (C99 6.3.2.1).
+  void DefaultFunctionArrayConversion(Expr *&expr);
+
+  // DefaultFunctionArrayLvalueConversion - converts functions and
+  // arrays to their respective pointers and performs the
+  // lvalue-to-rvalue conversion.
+  void DefaultFunctionArrayLvalueConversion(Expr *&expr);
+
+  // DefaultArgumentPromotion (C99 6.5.2.2p6). Used for function calls that
+  // do not have a prototype. Integer promotions are performed on each
+  // argument, and arguments that have type float are promoted to double.
+  void DefaultArgumentPromotion(Expr *&Expr);
+
+  // Used for emitting the right warning by DefaultVariadicArgumentPromotion
+  enum VariadicCallType {
+    VariadicFunction,
+    VariadicBlock,
+    VariadicMethod,
+    VariadicConstructor,
+    VariadicDoesNotApply
+  };
+
+  /// GatherArgumentsForCall - Collector argument expressions for various
+  /// form of call prototypes.
+  bool GatherArgumentsForCall(SourceLocation CallLoc,
+                              FunctionDecl *FDecl,
+                              const FunctionProtoType *Proto,
+                              unsigned FirstProtoArg,
+                              Expr **Args, unsigned NumArgs,
+                              llvm::SmallVector<Expr *, 8> &AllArgs,
+                              VariadicCallType CallType = VariadicDoesNotApply);
+
+  // DefaultVariadicArgumentPromotion - Like DefaultArgumentPromotion, but
+  // will warn if the resulting type is not a POD type.
+  bool DefaultVariadicArgumentPromotion(Expr *&Expr, VariadicCallType CT);
+
+  // 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(Expr *&lExpr, Expr *&rExpr,
+                                      bool isCompAssign = false);
+
+  /// AssignConvertType - All of the 'assignment' semantic checks return this
+  /// enum to indicate whether the assignment was allowed.  These checks are
+  /// done for simple assignments, as well as initialization, return from
+  /// function, argument passing, etc.  The query is phrased in terms of a
+  /// source and destination type.
+  enum AssignConvertType {
+    /// Compatible - the types are compatible according to the standard.
+    Compatible,
+
+    /// PointerToInt - The assignment converts a pointer to an int, which we
+    /// accept as an extension.
+    PointerToInt,
+
+    /// IntToPointer - The assignment converts an int to a pointer, which we
+    /// accept as an extension.
+    IntToPointer,
+
+    /// FunctionVoidPointer - The assignment is between a function pointer and
+    /// void*, which the standard doesn't allow, but we accept as an extension.
+    FunctionVoidPointer,
+
+    /// IncompatiblePointer - The assignment is between two pointers types that
+    /// are not compatible, but we accept them as an extension.
+    IncompatiblePointer,
+
+    /// IncompatiblePointer - The assignment is between two pointers types which
+    /// point to integers which have a different sign, but are otherwise identical.
+    /// This is a subset of the above, but broken out because it's by far the most
+    /// common case of incompatible pointers.
+    IncompatiblePointerSign,
+
+    /// CompatiblePointerDiscardsQualifiers - The assignment discards
+    /// c/v/r qualifiers, which we accept as an extension.
+    CompatiblePointerDiscardsQualifiers,
+    
+    /// IncompatibleNestedPointerQualifiers - The assignment is between two
+    /// nested pointer types, and the qualifiers other than the first two
+    /// levels differ e.g. char ** -> const char **, but we accept them as an 
+    /// extension. 
+    IncompatibleNestedPointerQualifiers,
+
+    /// IncompatibleVectors - The assignment is between two vector types that
+    /// have the same size, which we accept as an extension.
+    IncompatibleVectors,
+
+    /// IntToBlockPointer - The assignment converts an int to a block
+    /// pointer. We disallow this.
+    IntToBlockPointer,
+
+    /// IncompatibleBlockPointer - The assignment is between two block
+    /// pointers types that are not compatible.
+    IncompatibleBlockPointer,
+
+    /// IncompatibleObjCQualifiedId - The assignment is between a qualified
+    /// id type and something else (that is incompatible with it). For example,
+    /// "id <XXX>" = "Foo *", where "Foo *" doesn't implement the XXX protocol.
+    IncompatibleObjCQualifiedId,
+
+    /// Incompatible - We reject this conversion outright, it is invalid to
+    /// represent it in the AST.
+    Incompatible
+  };
+  
+  /// DiagnoseAssignmentResult - Emit a diagnostic, if required, for the
+  /// assignment conversion type specified by ConvTy.  This returns true if the
+  /// conversion was invalid or false if the conversion was accepted.
+  bool DiagnoseAssignmentResult(AssignConvertType ConvTy,
+                                SourceLocation Loc,
+                                QualType DstType, QualType SrcType,
+                                Expr *SrcExpr, AssignmentAction Action);
+
+  /// CheckAssignmentConstraints - Perform type checking for assignment,
+  /// argument passing, variable initialization, and function return values.
+  /// This routine is only used by the following two methods. C99 6.5.16.
+  AssignConvertType CheckAssignmentConstraints(QualType lhs, QualType rhs);
+
+  // CheckSingleAssignmentConstraints - Currently used by
+  // CheckAssignmentOperands, and ActOnReturnStmt. Prior to type checking,
+  // this routine performs the default function/array converions.
+  AssignConvertType CheckSingleAssignmentConstraints(QualType lhs,
+                                                     Expr *&rExpr);
+
+  // \brief If the lhs type is a transparent union, check whether we
+  // can initialize the transparent union with the given expression.
+  AssignConvertType CheckTransparentUnionArgumentConstraints(QualType lhs,
+                                                             Expr *&rExpr);
+
+  // Helper function for CheckAssignmentConstraints (C99 6.5.16.1p1)
+  AssignConvertType CheckPointerTypesForAssignment(QualType lhsType,
+                                                   QualType rhsType);
+
+  AssignConvertType CheckObjCPointerTypesForAssignment(QualType lhsType,
+                                                       QualType rhsType);
+
+  // Helper function for CheckAssignmentConstraints involving two
+  // block pointer types.
+  AssignConvertType CheckBlockPointerTypesForAssignment(QualType lhsType,
+                                                        QualType rhsType);
+
+  bool IsStringLiteralToNonConstPointerConversion(Expr *From, QualType ToType);
+
+  bool CheckExceptionSpecCompatibility(Expr *From, QualType ToType);
+
+  bool PerformImplicitConversion(Expr *&From, QualType ToType,
+                                 AssignmentAction Action,
+                                 bool AllowExplicit = false,
+                                 bool Elidable = false);
+  bool PerformImplicitConversion(Expr *&From, QualType ToType,
+                                 AssignmentAction Action,
+                                 bool AllowExplicit,
+                                 bool Elidable,
+                                 ImplicitConversionSequence& ICS);
+  bool PerformImplicitConversion(Expr *&From, QualType ToType,
+                                 const ImplicitConversionSequence& ICS,
+                                 AssignmentAction Action,
+                                 bool IgnoreBaseAccess = false);
+  bool PerformImplicitConversion(Expr *&From, QualType ToType,
+                                 const StandardConversionSequence& SCS,
+                                 AssignmentAction Action, bool IgnoreBaseAccess);
+
+  /// 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 CreateBuiltinBinOp).
+  QualType InvalidOperands(SourceLocation l, Expr *&lex, Expr *&rex);
+  QualType CheckPointerToMemberOperands( // C++ 5.5
+    Expr *&lex, Expr *&rex, SourceLocation OpLoc, bool isIndirect);
+  QualType CheckMultiplyDivideOperands( // C99 6.5.5
+    Expr *&lex, Expr *&rex, SourceLocation OpLoc, bool isCompAssign,
+                                       bool isDivide);
+  QualType CheckRemainderOperands( // C99 6.5.5
+    Expr *&lex, Expr *&rex, SourceLocation OpLoc, bool isCompAssign = false);
+  QualType CheckAdditionOperands( // C99 6.5.6
+    Expr *&lex, Expr *&rex, SourceLocation OpLoc, QualType* CompLHSTy = 0);
+  QualType CheckSubtractionOperands( // C99 6.5.6
+    Expr *&lex, Expr *&rex, SourceLocation OpLoc, QualType* CompLHSTy = 0);
+  QualType CheckShiftOperands( // C99 6.5.7
+    Expr *&lex, Expr *&rex, SourceLocation OpLoc, bool isCompAssign = false);
+  QualType CheckCompareOperands( // C99 6.5.8/9
+    Expr *&lex, Expr *&rex, SourceLocation OpLoc, unsigned Opc, bool isRelational);
+  QualType CheckBitwiseOperands( // C99 6.5.[10...12]
+    Expr *&lex, Expr *&rex, SourceLocation OpLoc, bool isCompAssign = false);
+  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.
+  QualType CheckAssignmentOperands( // C99 6.5.16.[1,2]
+    Expr *lex, Expr *&rex, SourceLocation OpLoc, QualType convertedType);
+  QualType CheckCommaOperands( // C99 6.5.17
+    Expr *lex, Expr *&rex, SourceLocation OpLoc);
+  QualType CheckConditionalOperands( // C99 6.5.15
+    Expr *&cond, Expr *&lhs, Expr *&rhs, SourceLocation questionLoc);
+  QualType CXXCheckConditionalOperands( // C++ 5.16
+    Expr *&cond, Expr *&lhs, Expr *&rhs, SourceLocation questionLoc);
+  QualType FindCompositePointerType(Expr *&E1, Expr *&E2); // C++ 5.9
+
+  QualType FindCompositeObjCPointerType(Expr *&LHS, Expr *&RHS,
+                                        SourceLocation questionLoc);
+  
+  /// type checking for vector binary operators.
+  inline QualType CheckVectorOperands(SourceLocation l, Expr *&lex, Expr *&rex);
+  inline QualType CheckVectorCompareOperands(Expr *&lex, Expr *&rx,
+                                             SourceLocation l, bool isRel);
+
+  /// type checking unary operators (subroutines of ActOnUnaryOp).
+  /// C99 6.5.3.1, 6.5.3.2, 6.5.3.4
+  QualType CheckIncrementDecrementOperand(Expr *op, SourceLocation OpLoc,
+                                          bool isInc);
+  QualType CheckAddressOfOperand(Expr *op, SourceLocation OpLoc);
+  QualType CheckIndirectionOperand(Expr *op, SourceLocation OpLoc);
+  QualType CheckRealImagOperand(Expr *&Op, SourceLocation OpLoc, bool isReal);
+
+  /// type checking primary expressions.
+  QualType CheckExtVectorComponent(QualType baseType, SourceLocation OpLoc,
+                                   const IdentifierInfo *Comp,
+                                   SourceLocation CmpLoc);
+
+  /// type checking declaration initializers (C99 6.7.8)
+  bool CheckInitList(const InitializedEntity &Entity,
+                     InitListExpr *&InitList, QualType &DeclType);
+  bool CheckForConstantInitializer(Expr *e, QualType t);
+
+  // type checking C++ declaration initializers (C++ [dcl.init]).
+
+  /// ReferenceCompareResult - Expresses the result of comparing two
+  /// types (cv1 T1 and cv2 T2) to determine their compatibility for the
+  /// purposes of initialization by reference (C++ [dcl.init.ref]p4).
+  enum ReferenceCompareResult {
+    /// Ref_Incompatible - The two types are incompatible, so direct
+    /// reference binding is not possible.
+    Ref_Incompatible = 0,
+    /// Ref_Related - The two types are reference-related, which means
+    /// that their unqualified forms (T1 and T2) are either the same
+    /// or T1 is a base class of T2.
+    Ref_Related,
+    /// Ref_Compatible_With_Added_Qualification - The two types are
+    /// reference-compatible with added qualification, meaning that
+    /// they are reference-compatible and the qualifiers on T1 (cv1)
+    /// are greater than the qualifiers on T2 (cv2).
+    Ref_Compatible_With_Added_Qualification,
+    /// Ref_Compatible - The two types are reference-compatible and
+    /// have equivalent qualifiers (cv1 == cv2).
+    Ref_Compatible
+  };
+
+  ReferenceCompareResult CompareReferenceRelationship(SourceLocation Loc,
+                                                      QualType T1, QualType T2,
+                                                      bool& DerivedToBase);
+
+  bool CheckReferenceInit(Expr *&simpleInit_or_initList, QualType declType,
+                          SourceLocation DeclLoc,
+                          bool SuppressUserConversions,
+                          bool AllowExplicit,
+                          bool ForceRValue,
+                          ImplicitConversionSequence *ICS = 0,
+                          bool IgnoreBaseAccess = false);
+
+  /// CheckCastTypes - Check type constraints for casting between types under
+  /// C semantics, or forward to CXXCheckCStyleCast in C++.
+  bool CheckCastTypes(SourceRange TyRange, QualType CastTy, Expr *&CastExpr,
+                      CastExpr::CastKind &Kind,
+                      CXXMethodDecl *& ConversionDecl,
+                      bool FunctionalStyle = false);
+
+  // CheckVectorCast - check type constraints for vectors.
+  // Since vectors are an extension, there are no C standard reference for this.
+  // We allow casting between vectors and integer datatypes of the same size.
+  // returns true if the cast is invalid
+  bool CheckVectorCast(SourceRange R, QualType VectorTy, QualType Ty,
+                       CastExpr::CastKind &Kind);
+
+  // CheckExtVectorCast - check type constraints for extended vectors.
+  // Since vectors are an extension, there are no C standard reference for this.
+  // We allow casting between vectors and integer datatypes of the same size,
+  // or vectors and the element type of that vector.
+  // returns true if the cast is invalid
+  bool CheckExtVectorCast(SourceRange R, QualType VectorTy, Expr *&CastExpr,
+                          CastExpr::CastKind &Kind);
+
+  /// CXXCheckCStyleCast - Check constraints of a C-style or function-style
+  /// cast under C++ semantics.
+  bool CXXCheckCStyleCast(SourceRange R, QualType CastTy, Expr *&CastExpr,
+                          CastExpr::CastKind &Kind, bool FunctionalStyle,
+                          CXXMethodDecl *&ConversionDecl);
+
+  /// CheckMessageArgumentTypes - Check types in an Obj-C message send.
+  /// \param Method - May be null.
+  /// \param [out] ReturnType - The return type of the send.
+  /// \return true iff there were any incompatible types.
+  bool CheckMessageArgumentTypes(Expr **Args, unsigned NumArgs, Selector Sel,
+                                 ObjCMethodDecl *Method, bool isClassMessage,
+                                 SourceLocation lbrac, SourceLocation rbrac,
+                                 QualType &ReturnType);
+
+  /// CheckBooleanCondition - Diagnose problems involving the use of
+  /// the given expression as a boolean condition (e.g. in an if
+  /// statement).  Also performs the standard function and array
+  /// decays, possibly changing the input variable.
+  ///
+  /// \param Loc - A location associated with the condition, e.g. the
+  /// 'if' keyword.
+  /// \return true iff there were any errors
+  bool CheckBooleanCondition(Expr *&CondExpr, SourceLocation Loc);
+
+  /// DiagnoseAssignmentAsCondition - Given that an expression is
+  /// being used as a boolean condition, warn if it's an assignment.
+  void DiagnoseAssignmentAsCondition(Expr *E);
+
+  /// CheckCXXBooleanCondition - Returns true if conversion to bool is invalid.
+  bool CheckCXXBooleanCondition(Expr *&CondExpr);
+
+  /// ConvertIntegerToTypeWarnOnOverflow - Convert the specified APInt to have
+  /// the specified width and sign.  If an overflow occurs, detect it and emit
+  /// the specified diagnostic.
+  void ConvertIntegerToTypeWarnOnOverflow(llvm::APSInt &OldVal,
+                                          unsigned NewWidth, bool NewSign,
+                                          SourceLocation Loc, unsigned DiagID);
+
+  /// Checks that the Objective-C declaration is declared in the global scope.
+  /// Emits an error and marks the declaration as invalid if it's not declared
+  /// in the global scope.
+  bool CheckObjCDeclScope(Decl *D);
+
+  void InitBuiltinVaListType();
+
+  /// VerifyIntegerConstantExpression - verifies that an expression is an ICE,
+  /// and reports the appropriate diagnostics. Returns false on success.
+  /// Can optionally return the value of the expression.
+  bool VerifyIntegerConstantExpression(const Expr *E, llvm::APSInt *Result = 0);
+
+  /// VerifyBitField - verifies that a bit field expression is an ICE and has
+  /// the correct width, and that the field type is valid.
+  /// Returns false on success.
+  /// Can optionally return whether the bit-field is of width 0
+  bool VerifyBitField(SourceLocation FieldLoc, IdentifierInfo *FieldName,
+                      QualType FieldTy, const Expr *BitWidth,
+                      bool *ZeroWidth = 0);
+
+  /// \name Code completion
+  //@{
+  virtual void CodeCompleteOrdinaryName(Scope *S, 
+                                     CodeCompletionContext CompletionContext);
+  virtual void CodeCompleteMemberReferenceExpr(Scope *S, ExprTy *Base,
+                                               SourceLocation OpLoc,
+                                               bool IsArrow);
+  virtual void CodeCompleteTag(Scope *S, unsigned TagSpec);
+  virtual void CodeCompleteCase(Scope *S);
+  virtual void CodeCompleteCall(Scope *S, ExprTy *Fn,
+                                ExprTy **Args, unsigned NumArgs);
+  virtual void CodeCompleteQualifiedId(Scope *S, const CXXScopeSpec &SS,
+                                       bool EnteringContext);
+  virtual void CodeCompleteUsing(Scope *S);
+  virtual void CodeCompleteUsingDirective(Scope *S);
+  virtual void CodeCompleteNamespaceDecl(Scope *S);
+  virtual void CodeCompleteNamespaceAliasDecl(Scope *S);
+  virtual void CodeCompleteOperatorName(Scope *S);
+  
+  virtual void CodeCompleteObjCAtDirective(Scope *S, DeclPtrTy ObjCImpDecl,
+                                           bool InInterface);
+  virtual void CodeCompleteObjCAtVisibility(Scope *S);
+  virtual void CodeCompleteObjCAtStatement(Scope *S);
+  virtual void CodeCompleteObjCAtExpression(Scope *S);
+  virtual void CodeCompleteObjCPropertyFlags(Scope *S, ObjCDeclSpec &ODS);
+  virtual void CodeCompleteObjCPropertyGetter(Scope *S, DeclPtrTy ClassDecl,
+                                              DeclPtrTy *Methods,
+                                              unsigned NumMethods);
+  virtual void CodeCompleteObjCPropertySetter(Scope *S, DeclPtrTy ClassDecl,
+                                              DeclPtrTy *Methods,
+                                              unsigned NumMethods);
+
+  virtual void CodeCompleteObjCClassMessage(Scope *S, IdentifierInfo *FName,
+                                            SourceLocation FNameLoc,
+                                            IdentifierInfo **SelIdents, 
+                                            unsigned NumSelIdents);
+  virtual void CodeCompleteObjCInstanceMessage(Scope *S, ExprTy *Receiver,
+                                               IdentifierInfo **SelIdents,
+                                               unsigned NumSelIdents);
+  virtual void CodeCompleteObjCProtocolReferences(IdentifierLocPair *Protocols,
+                                                  unsigned NumProtocols);
+  virtual void CodeCompleteObjCProtocolDecl(Scope *S);
+  virtual void CodeCompleteObjCInterfaceDecl(Scope *S);
+  virtual void CodeCompleteObjCSuperclass(Scope *S, 
+                                          IdentifierInfo *ClassName);
+  virtual void CodeCompleteObjCImplementationDecl(Scope *S);
+  virtual void CodeCompleteObjCInterfaceCategory(Scope *S, 
+                                                 IdentifierInfo *ClassName);
+  virtual void CodeCompleteObjCImplementationCategory(Scope *S, 
+                                                    IdentifierInfo *ClassName);
+  virtual void CodeCompleteObjCPropertyDefinition(Scope *S, 
+                                                  DeclPtrTy ObjCImpDecl);
+  virtual void CodeCompleteObjCPropertySynthesizeIvar(Scope *S, 
+                                                  IdentifierInfo *PropertyName,
+                                                      DeclPtrTy ObjCImpDecl);
+  //@}
+  
+  //===--------------------------------------------------------------------===//
+  // Extra semantic analysis beyond the C type system
+
+public:
+  SourceLocation getLocationOfStringLiteralByte(const StringLiteral *SL,
+                                                unsigned ByteNo) const;
+
+private:
+  bool CheckFunctionCall(FunctionDecl *FDecl, CallExpr *TheCall);
+  bool CheckBlockCall(NamedDecl *NDecl, CallExpr *TheCall);
+
+  bool CheckablePrintfAttr(const FormatAttr *Format, CallExpr *TheCall);
+  bool CheckObjCString(Expr *Arg);
+
+  Action::OwningExprResult CheckBuiltinFunctionCall(unsigned BuiltinID,
+                                                    CallExpr *TheCall);
+  bool SemaBuiltinVAStart(CallExpr *TheCall);
+  bool SemaBuiltinUnorderedCompare(CallExpr *TheCall);
+  bool SemaBuiltinUnaryFP(CallExpr *TheCall);
+  bool SemaBuiltinStackAddress(CallExpr *TheCall);
+
+public:
+  // Used by C++ template instantiation.
+  Action::OwningExprResult SemaBuiltinShuffleVector(CallExpr *TheCall);
+
+private:
+  bool SemaBuiltinPrefetch(CallExpr *TheCall);
+  bool SemaBuiltinObjectSize(CallExpr *TheCall);
+  bool SemaBuiltinLongjmp(CallExpr *TheCall);
+  bool SemaBuiltinAtomicOverloaded(CallExpr *TheCall);
+  bool SemaBuiltinEHReturnDataRegNo(CallExpr *TheCall);
+  bool SemaCheckStringLiteral(const Expr *E, const CallExpr *TheCall,
+                              bool HasVAListArg, unsigned format_idx,
+                              unsigned firstDataArg);
+  void CheckPrintfString(const StringLiteral *FExpr, const Expr *OrigFormatExpr,
+                         const CallExpr *TheCall, bool HasVAListArg,
+                         unsigned format_idx, unsigned firstDataArg);
+  void CheckNonNullArguments(const NonNullAttr *NonNull,
+                             const CallExpr *TheCall);
+  void CheckPrintfArguments(const CallExpr *TheCall, bool HasVAListArg,
+                            unsigned format_idx, unsigned firstDataArg);
+  void CheckReturnStackAddr(Expr *RetValExp, QualType lhsType,
+                            SourceLocation ReturnLoc);
+  void CheckFloatComparison(SourceLocation loc, Expr* lex, Expr* rex);
+  void CheckSignCompare(Expr *LHS, Expr *RHS, SourceLocation Loc,
+                        const PartialDiagnostic &PD,
+                        bool Equality = false);
+  void CheckImplicitConversion(Expr *E, QualType Target);
+};
+
+//===--------------------------------------------------------------------===//
+// Typed version of Parser::ExprArg (smart pointer for wrapping Expr pointers).
+template <typename T>
+class ExprOwningPtr : public Action::ExprArg {
+public:
+  ExprOwningPtr(Sema *S, T *expr) : Action::ExprArg(*S, expr) {}
+
+  void reset(T* p) { Action::ExprArg::operator=(p); }
+  T* get() const { return static_cast<T*>(Action::ExprArg::get()); }
+  T* take() { return static_cast<T*>(Action::ExprArg::take()); }
+  T* release() { return take(); }
+
+  T& operator*() const { return *get(); }
+  T* operator->() const { return get(); }
+};
+
+}  // end namespace clang
+
+#endif
diff --git a/lib/Sema/SemaAccess.cpp b/lib/Sema/SemaAccess.cpp
new file mode 100644
index 0000000..eca8bb4
--- /dev/null
+++ b/lib/Sema/SemaAccess.cpp
@@ -0,0 +1,548 @@
+//===---- SemaAccess.cpp - C++ Access Control -------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file provides Sema routines for C++ access control semantics.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Sema.h"
+#include "Lookup.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/CXXInheritance.h"
+#include "clang/AST/DeclCXX.h"
+#include "clang/AST/ExprCXX.h"
+
+using namespace clang;
+
+/// SetMemberAccessSpecifier - Set the access specifier of a member.
+/// Returns true on error (when the previous member decl access specifier
+/// is different from the new member decl access specifier).
+bool Sema::SetMemberAccessSpecifier(NamedDecl *MemberDecl,
+                                    NamedDecl *PrevMemberDecl,
+                                    AccessSpecifier LexicalAS) {
+  if (!PrevMemberDecl) {
+    // Use the lexical access specifier.
+    MemberDecl->setAccess(LexicalAS);
+    return false;
+  }
+
+  // C++ [class.access.spec]p3: When a member is redeclared its access
+  // specifier must be same as its initial declaration.
+  if (LexicalAS != AS_none && LexicalAS != PrevMemberDecl->getAccess()) {
+    Diag(MemberDecl->getLocation(),
+         diag::err_class_redeclared_with_different_access)
+      << MemberDecl << LexicalAS;
+    Diag(PrevMemberDecl->getLocation(), diag::note_previous_access_declaration)
+      << PrevMemberDecl << PrevMemberDecl->getAccess();
+
+    MemberDecl->setAccess(LexicalAS);
+    return true;
+  }
+
+  MemberDecl->setAccess(PrevMemberDecl->getAccess());
+  return false;
+}
+
+namespace {
+struct EffectiveContext {
+  EffectiveContext() : Record(0), Function(0) {}
+
+  explicit EffectiveContext(DeclContext *DC) {
+    if (isa<FunctionDecl>(DC)) {
+      Function = cast<FunctionDecl>(DC);
+      DC = Function->getDeclContext();
+    } else
+      Function = 0;
+    
+    if (isa<CXXRecordDecl>(DC))
+      Record = cast<CXXRecordDecl>(DC)->getCanonicalDecl();
+    else
+      Record = 0;
+  }
+
+  bool isClass(const CXXRecordDecl *R) const {
+    return R->getCanonicalDecl() == Record;
+  }
+
+  CXXRecordDecl *Record;
+  FunctionDecl *Function;
+};
+}
+
+static CXXRecordDecl *FindDeclaringClass(NamedDecl *D) {
+  CXXRecordDecl *DeclaringClass = cast<CXXRecordDecl>(D->getDeclContext());
+  while (DeclaringClass->isAnonymousStructOrUnion())
+    DeclaringClass = cast<CXXRecordDecl>(DeclaringClass->getDeclContext());
+  return DeclaringClass;
+}
+
+static Sema::AccessResult GetFriendKind(Sema &S,
+                                        const EffectiveContext &EC,
+                                        const CXXRecordDecl *Class) {
+  if (EC.isClass(Class))
+    return Sema::AR_accessible;
+
+  // FIXME: implement
+  return Sema::AR_inaccessible;
+}
+
+/// Finds the best path from the naming class to the declaring class,
+/// taking friend declarations into account.
+///
+/// \return null if friendship is dependent
+static CXXBasePath *FindBestPath(Sema &S,
+                                 const EffectiveContext &EC,
+                                 CXXRecordDecl *Derived,
+                                 CXXRecordDecl *Base,
+                                 CXXBasePaths &Paths) {
+  // Derive the paths to the desired base.
+  bool isDerived = Derived->isDerivedFrom(Base, Paths);
+  assert(isDerived && "derived class not actually derived from base");
+  (void) isDerived;
+
+  CXXBasePath *BestPath = 0;
+
+  // Derive the friend-modified access along each path.
+  for (CXXBasePaths::paths_iterator PI = Paths.begin(), PE = Paths.end();
+         PI != PE; ++PI) {
+
+    // Walk through the path backwards.
+    AccessSpecifier PathAccess = AS_public;
+    CXXBasePath::iterator I = PI->end(), E = PI->begin();
+    while (I != E) {
+      --I;
+
+      AccessSpecifier BaseAccess = I->Base->getAccessSpecifier();
+      if (BaseAccess != AS_public) {
+        switch (GetFriendKind(S, EC, I->Class)) {
+        case Sema::AR_inaccessible: break;
+        case Sema::AR_accessible: BaseAccess = AS_public; break;
+        case Sema::AR_dependent: return 0;
+        case Sema::AR_delayed:
+          llvm_unreachable("friend resolution is never delayed"); break;
+        }
+      }
+
+      PathAccess = CXXRecordDecl::MergeAccess(BaseAccess, PathAccess);
+    }
+
+    // Note that we modify the path's Access field to the
+    // friend-modified access.
+    if (BestPath == 0 || PathAccess < BestPath->Access) {
+      BestPath = &*PI;
+      BestPath->Access = PathAccess;
+    }
+  }
+
+  return BestPath;
+}
+
+/// Diagnose the path which caused the given declaration or base class
+/// to become inaccessible.
+static void DiagnoseAccessPath(Sema &S,
+                               const EffectiveContext &EC,
+                               CXXRecordDecl *NamingClass,
+                               CXXRecordDecl *DeclaringClass,
+                               NamedDecl *D, AccessSpecifier Access) {
+  // Easy case: the decl's natural access determined its path access.
+  // We have to check against AS_private here in case Access is AS_none,
+  // indicating a non-public member of a private base class.
+  //
+  // DependentFriend should be impossible here.
+  if (D && (Access == D->getAccess() || D->getAccess() == AS_private)) {
+    switch (GetFriendKind(S, EC, DeclaringClass)) {
+    case Sema::AR_inaccessible: {
+      S.Diag(D->getLocation(), diag::note_access_natural)
+        << (unsigned) (Access == AS_protected)
+        << /*FIXME: not implicitly*/ 0;
+      return;
+    }
+
+    case Sema::AR_accessible: break;
+
+    case Sema::AR_dependent:
+    case Sema::AR_delayed:
+      llvm_unreachable("dependent/delayed not allowed");
+      return;
+    }
+  }
+
+  CXXBasePaths Paths;
+  CXXBasePath &Path = *FindBestPath(S, EC, NamingClass, DeclaringClass, Paths);
+
+  CXXBasePath::iterator I = Path.end(), E = Path.begin();
+  while (I != E) {
+    --I;
+
+    const CXXBaseSpecifier *BS = I->Base;
+    AccessSpecifier BaseAccess = BS->getAccessSpecifier();
+
+    // If this is public inheritance, or the derived class is a friend,
+    // skip this step.
+    if (BaseAccess == AS_public)
+      continue;
+
+    switch (GetFriendKind(S, EC, I->Class)) {
+    case Sema::AR_accessible: continue;
+    case Sema::AR_inaccessible: break;
+
+    case Sema::AR_dependent:
+    case Sema::AR_delayed:
+      llvm_unreachable("dependent friendship, should not be diagnosing");
+    }
+
+    // Check whether this base specifier is the tighest point
+    // constraining access.  We have to check against AS_private for
+    // the same reasons as above.
+    if (BaseAccess == AS_private || BaseAccess >= Access) {
+
+      // We're constrained by inheritance, but we want to say
+      // "declared private here" if we're diagnosing a hierarchy
+      // conversion and this is the final step.
+      unsigned diagnostic;
+      if (D) diagnostic = diag::note_access_constrained_by_path;
+      else if (I + 1 == Path.end()) diagnostic = diag::note_access_natural;
+      else diagnostic = diag::note_access_constrained_by_path;
+
+      S.Diag(BS->getSourceRange().getBegin(), diagnostic)
+        << BS->getSourceRange()
+        << (BaseAccess == AS_protected)
+        << (BS->getAccessSpecifierAsWritten() == AS_none);
+      return;
+    }
+  }
+
+  llvm_unreachable("access not apparently constrained by path");
+}
+
+/// Diagnose an inaccessible class member.
+static void DiagnoseInaccessibleMember(Sema &S, SourceLocation Loc,
+                                       const EffectiveContext &EC,
+                                       CXXRecordDecl *NamingClass,
+                                       AccessSpecifier Access,
+                                       const Sema::AccessedEntity &Entity) {
+  NamedDecl *D = Entity.getTargetDecl();
+  CXXRecordDecl *DeclaringClass = FindDeclaringClass(D);
+
+  if (isa<CXXConstructorDecl>(D)) {
+    unsigned DiagID = (Access == AS_protected ? diag::err_access_ctor_protected
+                                              : diag::err_access_ctor_private);
+    S.Diag(Loc, DiagID)
+      << S.Context.getTypeDeclType(DeclaringClass);
+  } else {
+    unsigned DiagID = (Access == AS_protected ? diag::err_access_protected
+                                              : diag::err_access_private);
+    S.Diag(Loc, DiagID)
+      << D->getDeclName()
+      << S.Context.getTypeDeclType(DeclaringClass);
+  }
+  DiagnoseAccessPath(S, EC, NamingClass, DeclaringClass, D, Access);
+}
+
+/// Diagnose an inaccessible hierarchy conversion.
+static void DiagnoseInaccessibleBase(Sema &S, SourceLocation Loc,
+                                     const EffectiveContext &EC,
+                                     AccessSpecifier Access,
+                                     const Sema::AccessedEntity &Entity,
+                                     Sema::AccessDiagnosticsKind ADK) {
+  if (ADK == Sema::ADK_covariance) {
+    S.Diag(Loc, diag::err_covariant_return_inaccessible_base)
+      << S.Context.getTypeDeclType(Entity.getDerivedClass())
+      << S.Context.getTypeDeclType(Entity.getBaseClass())
+      << (Access == AS_protected);
+  } else if (Entity.getKind() == Sema::AccessedEntity::BaseToDerivedConversion) {
+    S.Diag(Loc, diag::err_downcast_from_inaccessible_base)
+      << S.Context.getTypeDeclType(Entity.getDerivedClass())
+      << S.Context.getTypeDeclType(Entity.getBaseClass())
+      << (Access == AS_protected);
+  } else {
+    S.Diag(Loc, diag::err_upcast_to_inaccessible_base)
+      << S.Context.getTypeDeclType(Entity.getDerivedClass())
+      << S.Context.getTypeDeclType(Entity.getBaseClass())
+      << (Access == AS_protected);
+  }
+  DiagnoseAccessPath(S, EC, Entity.getDerivedClass(),
+                     Entity.getBaseClass(), 0, Access);
+}
+
+static void DiagnoseBadAccess(Sema &S,
+                              SourceLocation Loc,
+                              const EffectiveContext &EC,
+                              CXXRecordDecl *NamingClass,
+                              AccessSpecifier Access,
+                              const Sema::AccessedEntity &Entity,
+                              Sema::AccessDiagnosticsKind ADK) {
+  if (Entity.isMemberAccess())
+    DiagnoseInaccessibleMember(S, Loc, EC, NamingClass, Access, Entity);
+  else
+    DiagnoseInaccessibleBase(S, Loc, EC, Access, Entity, ADK);
+}
+
+
+/// Try to elevate access using friend declarations.  This is
+/// potentially quite expensive.
+static void TryElevateAccess(Sema &S,
+                             const EffectiveContext &EC,
+                             const Sema::AccessedEntity &Entity,
+                             AccessSpecifier &Access) {
+  CXXRecordDecl *DeclaringClass;
+  if (Entity.isMemberAccess()) {
+    DeclaringClass = FindDeclaringClass(Entity.getTargetDecl());
+  } else {
+    DeclaringClass = Entity.getBaseClass();
+  }
+  CXXRecordDecl *NamingClass = Entity.getNamingClass();
+
+  // Adjust the declaration of the referred entity.
+  AccessSpecifier DeclAccess = AS_none;
+  if (Entity.isMemberAccess()) {
+    NamedDecl *Target = Entity.getTargetDecl();
+
+    DeclAccess = Target->getAccess();
+    if (DeclAccess != AS_public) {
+      switch (GetFriendKind(S, EC, DeclaringClass)) {
+      case Sema::AR_accessible: DeclAccess = AS_public; break;
+      case Sema::AR_inaccessible: break;
+      case Sema::AR_dependent: /* FIXME: delay dependent friendship */ return;
+      case Sema::AR_delayed: llvm_unreachable("friend status is never delayed");
+      }
+    }
+
+    if (DeclaringClass == NamingClass) {
+      Access = DeclAccess;
+      return;
+    }
+  }
+
+  assert(DeclaringClass != NamingClass);
+
+  // Append the declaration's access if applicable.
+  CXXBasePaths Paths;
+  CXXBasePath *Path = FindBestPath(S, EC, Entity.getNamingClass(),
+                                   DeclaringClass, Paths);
+  if (!Path) {
+    // FIXME: delay dependent friendship
+    return;
+  }
+
+  // Grab the access along the best path.
+  AccessSpecifier NewAccess = Path->Access;
+  if (Entity.isMemberAccess())
+    NewAccess = CXXRecordDecl::MergeAccess(NewAccess, DeclAccess);
+  
+  assert(NewAccess <= Access && "access along best path worse than direct?");
+  Access = NewAccess;
+}
+
+/// Checks access to an entity from the given effective context.
+static Sema::AccessResult CheckEffectiveAccess(Sema &S,
+                                               const EffectiveContext &EC,
+                                               SourceLocation Loc,
+                                         Sema::AccessedEntity const &Entity,
+                                         Sema::AccessDiagnosticsKind ADK) {
+  AccessSpecifier Access = Entity.getAccess();
+  assert(Access != AS_public);
+
+  CXXRecordDecl *NamingClass = Entity.getNamingClass();
+  while (NamingClass->isAnonymousStructOrUnion())
+    // This should be guaranteed by the fact that the decl has
+    // non-public access.  If not, we should make it guaranteed!
+    NamingClass = cast<CXXRecordDecl>(NamingClass);
+
+  if (!EC.Record) {
+    TryElevateAccess(S, EC, Entity, Access);
+    if (Access == AS_public) return Sema::AR_accessible;
+
+    if (ADK != Sema::ADK_quiet)
+      DiagnoseBadAccess(S, Loc, EC, NamingClass, Access, Entity, ADK);
+    return Sema::AR_inaccessible;
+  }
+
+  // White-list accesses from within the declaring class.
+  if (Access != AS_none && EC.isClass(NamingClass))
+    return Sema::AR_accessible;
+  
+  // If the access is worse than 'protected', try to promote to it using
+  // friend declarations.
+  bool TriedElevation = false;
+  if (Access != AS_protected) {
+    TryElevateAccess(S, EC, Entity, Access);
+    if (Access == AS_public) return Sema::AR_accessible;
+    TriedElevation = true;
+  }
+
+  // Protected access.
+  if (Access == AS_protected) {
+    // FIXME: implement [class.protected]p1
+    if (EC.Record->isDerivedFrom(NamingClass))
+      return Sema::AR_accessible;
+
+    // FIXME: delay dependent classes
+  }
+
+  // We're about to reject;  one last chance to promote access.
+  if (!TriedElevation) {
+    TryElevateAccess(S, EC, Entity, Access);
+    if (Access == AS_public) return Sema::AR_accessible;
+  }
+    
+  // Okay, that's it, reject it.
+  if (ADK != Sema::ADK_quiet)
+    DiagnoseBadAccess(S, Loc, EC, NamingClass, Access, Entity, ADK);
+  return Sema::AR_inaccessible;
+}
+
+static Sema::AccessResult CheckAccess(Sema &S, SourceLocation Loc,
+                                      const Sema::AccessedEntity &Entity,
+                                      Sema::AccessDiagnosticsKind ADK
+                                        = Sema::ADK_normal) {
+  // If the access path is public, it's accessible everywhere.
+  if (Entity.getAccess() == AS_public)
+    return Sema::AR_accessible;
+
+  // If we're currently parsing a top-level declaration, delay
+  // diagnostics.  This is the only case where parsing a declaration
+  // can actually change our effective context for the purposes of
+  // access control.
+  if (S.CurContext->isFileContext() && S.ParsingDeclDepth) {
+    assert(ADK == Sema::ADK_normal && "delaying abnormal access check");
+    S.DelayedDiagnostics.push_back(
+        Sema::DelayedDiagnostic::makeAccess(Loc, Entity));
+    return Sema::AR_delayed;
+  }
+
+  return CheckEffectiveAccess(S, EffectiveContext(S.CurContext),
+                              Loc, Entity, ADK);
+}
+
+void Sema::HandleDelayedAccessCheck(DelayedDiagnostic &DD, Decl *Ctx) {
+  // Pretend we did this from the context of the newly-parsed
+  // declaration.
+  EffectiveContext EC(Ctx->getDeclContext());
+
+  if (CheckEffectiveAccess(*this, EC, DD.Loc, DD.AccessData, ADK_normal))
+    DD.Triggered = true;
+}
+
+Sema::AccessResult Sema::CheckUnresolvedLookupAccess(UnresolvedLookupExpr *E,
+                                                     NamedDecl *D,
+                                                     AccessSpecifier Access) {
+  if (!getLangOptions().AccessControl || !E->getNamingClass())
+    return AR_accessible;
+
+  return CheckAccess(*this, E->getNameLoc(),
+                 AccessedEntity::makeMember(E->getNamingClass(), Access, D));
+}
+
+/// Perform access-control checking on a previously-unresolved member
+/// access which has now been resolved to a member.
+Sema::AccessResult Sema::CheckUnresolvedMemberAccess(UnresolvedMemberExpr *E,
+                                                     NamedDecl *D,
+                                                     AccessSpecifier Access) {
+  if (!getLangOptions().AccessControl)
+    return AR_accessible;
+
+  return CheckAccess(*this, E->getMemberLoc(),
+                 AccessedEntity::makeMember(E->getNamingClass(), Access, D));
+}
+
+Sema::AccessResult Sema::CheckDestructorAccess(SourceLocation Loc,
+                                               const RecordType *RT) {
+  if (!getLangOptions().AccessControl)
+    return AR_accessible;
+
+  CXXRecordDecl *NamingClass = cast<CXXRecordDecl>(RT->getDecl());
+  CXXDestructorDecl *Dtor = NamingClass->getDestructor(Context);
+
+  AccessSpecifier Access = Dtor->getAccess();
+  if (Access == AS_public)
+    return AR_accessible;
+
+  return CheckAccess(*this, Loc,
+                 AccessedEntity::makeMember(NamingClass, Access, Dtor));
+}
+
+/// Checks access to a constructor.
+Sema::AccessResult Sema::CheckConstructorAccess(SourceLocation UseLoc,
+                                  CXXConstructorDecl *Constructor,
+                                  AccessSpecifier Access) {
+  if (!getLangOptions().AccessControl)
+    return AR_accessible;
+
+  CXXRecordDecl *NamingClass = Constructor->getParent();
+  return CheckAccess(*this, UseLoc,
+                 AccessedEntity::makeMember(NamingClass, Access, Constructor));
+}
+
+/// Checks access to an overloaded member operator, including
+/// conversion operators.
+Sema::AccessResult Sema::CheckMemberOperatorAccess(SourceLocation OpLoc,
+                                                   Expr *ObjectExpr,
+                                                   NamedDecl *MemberOperator,
+                                                   AccessSpecifier Access) {
+  if (!getLangOptions().AccessControl)
+    return AR_accessible;
+
+  const RecordType *RT = ObjectExpr->getType()->getAs<RecordType>();
+  assert(RT && "found member operator but object expr not of record type");
+  CXXRecordDecl *NamingClass = cast<CXXRecordDecl>(RT->getDecl());
+
+  return CheckAccess(*this, OpLoc,
+            AccessedEntity::makeMember(NamingClass, Access, MemberOperator));
+}
+
+/// Checks access for a hierarchy conversion.
+///
+/// \param IsBaseToDerived whether this is a base-to-derived conversion (true)
+///     or a derived-to-base conversion (false)
+/// \param ForceCheck true if this check should be performed even if access
+///     control is disabled;  some things rely on this for semantics
+/// \param ForceUnprivileged true if this check should proceed as if the
+///     context had no special privileges
+/// \param ADK controls the kind of diagnostics that are used
+Sema::AccessResult Sema::CheckBaseClassAccess(SourceLocation AccessLoc,
+                                              bool IsBaseToDerived,
+                                              QualType Base,
+                                              QualType Derived,
+                                              const CXXBasePath &Path,
+                                              bool ForceCheck,
+                                              bool ForceUnprivileged,
+                                              AccessDiagnosticsKind ADK) {
+  if (!ForceCheck && !getLangOptions().AccessControl)
+    return AR_accessible;
+
+  if (Path.Access == AS_public)
+    return AR_accessible;
+
+  // TODO: preserve the information about which types exactly were used.
+  CXXRecordDecl *BaseD, *DerivedD;
+  BaseD = cast<CXXRecordDecl>(Base->getAs<RecordType>()->getDecl());
+  DerivedD = cast<CXXRecordDecl>(Derived->getAs<RecordType>()->getDecl());
+  AccessedEntity Entity = AccessedEntity::makeBaseClass(IsBaseToDerived,
+                                                        BaseD, DerivedD,
+                                                        Path.Access);
+
+  if (ForceUnprivileged)
+    return CheckEffectiveAccess(*this, EffectiveContext(),
+                                AccessLoc, Entity, ADK);
+  return CheckAccess(*this, AccessLoc, Entity, ADK);
+}
+
+/// Checks access to all the declarations in the given result set.
+void Sema::CheckLookupAccess(const LookupResult &R) {
+  assert(getLangOptions().AccessControl
+         && "performing access check without access control");
+  assert(R.getNamingClass() && "performing access check without naming class");
+
+  for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I)
+    if (I.getAccess() != AS_public)
+      CheckAccess(*this, R.getNameLoc(),
+                  AccessedEntity::makeMember(R.getNamingClass(),
+                                             I.getAccess(), *I));
+}
diff --git a/lib/Sema/SemaAttr.cpp b/lib/Sema/SemaAttr.cpp
new file mode 100644
index 0000000..095f537
--- /dev/null
+++ b/lib/Sema/SemaAttr.cpp
@@ -0,0 +1,201 @@
+//===--- SemaAttr.cpp - Semantic Analysis for Attributes ------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements semantic analysis for non-trivial attributes and
+// pragmas.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Sema.h"
+#include "Lookup.h"
+#include "clang/AST/Expr.h"
+using namespace clang;
+
+//===----------------------------------------------------------------------===//
+// Pragma Packed
+//===----------------------------------------------------------------------===//
+
+namespace {
+  /// PragmaPackStack - Simple class to wrap the stack used by #pragma
+  /// pack.
+  class PragmaPackStack {
+    typedef std::vector< std::pair<unsigned, IdentifierInfo*> > stack_ty;
+
+    /// Alignment - The current user specified alignment.
+    unsigned Alignment;
+
+    /// Stack - Entries in the #pragma pack stack, consisting of saved
+    /// alignments and optional names.
+    stack_ty Stack;
+
+  public:
+    PragmaPackStack() : Alignment(0) {}
+
+    void setAlignment(unsigned A) { Alignment = A; }
+    unsigned getAlignment() { return Alignment; }
+
+    /// push - Push the current alignment onto the stack, optionally
+    /// using the given \arg Name for the record, if non-zero.
+    void push(IdentifierInfo *Name) {
+      Stack.push_back(std::make_pair(Alignment, Name));
+    }
+
+    /// pop - Pop a record from the stack and restore the current
+    /// alignment to the previous value. If \arg Name is non-zero then
+    /// the first such named record is popped, otherwise the top record
+    /// is popped. Returns true if the pop succeeded.
+    bool pop(IdentifierInfo *Name);
+  };
+}  // end anonymous namespace.
+
+bool PragmaPackStack::pop(IdentifierInfo *Name) {
+  if (Stack.empty())
+    return false;
+
+  // If name is empty just pop top.
+  if (!Name) {
+    Alignment = Stack.back().first;
+    Stack.pop_back();
+    return true;
+  }
+
+  // Otherwise, find the named record.
+  for (unsigned i = Stack.size(); i != 0; ) {
+    --i;
+    if (Stack[i].second == Name) {
+      // Found it, pop up to and including this record.
+      Alignment = Stack[i].first;
+      Stack.erase(Stack.begin() + i, Stack.end());
+      return true;
+    }
+  }
+
+  return false;
+}
+
+
+/// FreePackedContext - Deallocate and null out PackContext.
+void Sema::FreePackedContext() {
+  delete static_cast<PragmaPackStack*>(PackContext);
+  PackContext = 0;
+}
+
+/// getPragmaPackAlignment() - Return the current alignment as specified by
+/// the current #pragma pack directive, or 0 if none is currently active.
+unsigned Sema::getPragmaPackAlignment() const {
+  if (PackContext)
+    return static_cast<PragmaPackStack*>(PackContext)->getAlignment();
+  return 0;
+}
+
+void Sema::ActOnPragmaPack(PragmaPackKind Kind, IdentifierInfo *Name,
+                           ExprTy *alignment, SourceLocation PragmaLoc,
+                           SourceLocation LParenLoc, SourceLocation RParenLoc) {
+  Expr *Alignment = static_cast<Expr *>(alignment);
+
+  // If specified then alignment must be a "small" power of two.
+  unsigned AlignmentVal = 0;
+  if (Alignment) {
+    llvm::APSInt Val;
+
+    // pack(0) is like pack(), which just works out since that is what
+    // we use 0 for in PackAttr.
+    if (!Alignment->isIntegerConstantExpr(Val, Context) ||
+        !(Val == 0 || Val.isPowerOf2()) ||
+        Val.getZExtValue() > 16) {
+      Diag(PragmaLoc, diag::warn_pragma_pack_invalid_alignment);
+      Alignment->Destroy(Context);
+      return; // Ignore
+    }
+
+    AlignmentVal = (unsigned) Val.getZExtValue();
+  }
+
+  if (PackContext == 0)
+    PackContext = new PragmaPackStack();
+
+  PragmaPackStack *Context = static_cast<PragmaPackStack*>(PackContext);
+
+  switch (Kind) {
+  case Action::PPK_Default: // pack([n])
+    Context->setAlignment(AlignmentVal);
+    break;
+
+  case Action::PPK_Show: // pack(show)
+    // Show the current alignment, making sure to show the right value
+    // for the default.
+    AlignmentVal = Context->getAlignment();
+    // FIXME: This should come from the target.
+    if (AlignmentVal == 0)
+      AlignmentVal = 8;
+    Diag(PragmaLoc, diag::warn_pragma_pack_show) << AlignmentVal;
+    break;
+
+  case Action::PPK_Push: // pack(push [, id] [, [n])
+    Context->push(Name);
+    // Set the new alignment if specified.
+    if (Alignment)
+      Context->setAlignment(AlignmentVal);
+    break;
+
+  case Action::PPK_Pop: // pack(pop [, id] [,  n])
+    // MSDN, C/C++ Preprocessor Reference > Pragma Directives > pack:
+    // "#pragma pack(pop, identifier, n) is undefined"
+    if (Alignment && Name)
+      Diag(PragmaLoc, diag::warn_pragma_pack_pop_identifer_and_alignment);
+
+    // Do the pop.
+    if (!Context->pop(Name)) {
+      // If a name was specified then failure indicates the name
+      // wasn't found. Otherwise failure indicates the stack was
+      // empty.
+      Diag(PragmaLoc, diag::warn_pragma_pack_pop_failed)
+        << (Name ? "no record matching name" : "stack empty");
+
+      // FIXME: Warn about popping named records as MSVC does.
+    } else {
+      // Pop succeeded, set the new alignment if specified.
+      if (Alignment)
+        Context->setAlignment(AlignmentVal);
+    }
+    break;
+
+  default:
+    assert(0 && "Invalid #pragma pack kind.");
+  }
+}
+
+void Sema::ActOnPragmaUnused(const Token *Identifiers, unsigned NumIdentifiers,
+                             Scope *curScope,
+                             SourceLocation PragmaLoc,
+                             SourceLocation LParenLoc,
+                             SourceLocation RParenLoc) {
+
+  for (unsigned i = 0; i < NumIdentifiers; ++i) {
+    const Token &Tok = Identifiers[i];
+    IdentifierInfo *Name = Tok.getIdentifierInfo();
+    LookupResult Lookup(*this, Name, Tok.getLocation(), LookupOrdinaryName);
+    LookupParsedName(Lookup, curScope, NULL, true);
+
+    if (Lookup.empty()) {
+      Diag(PragmaLoc, diag::warn_pragma_unused_undeclared_var)
+        << Name << SourceRange(Tok.getLocation());
+      continue;
+    }
+
+    VarDecl *VD = Lookup.getAsSingle<VarDecl>();
+    if (!VD || !VD->hasLocalStorage()) {
+      Diag(PragmaLoc, diag::warn_pragma_unused_expected_localvar)
+        << Name << SourceRange(Tok.getLocation());
+      continue;
+    }
+
+    VD->addAttr(::new (Context) UnusedAttr());
+  }
+}
diff --git a/lib/Sema/SemaCXXCast.cpp b/lib/Sema/SemaCXXCast.cpp
new file mode 100644
index 0000000..48258ff
--- /dev/null
+++ b/lib/Sema/SemaCXXCast.cpp
@@ -0,0 +1,1258 @@
+//===--- SemaNamedCast.cpp - Semantic Analysis for Named Casts ------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+//  This file implements semantic analysis for C++ named casts.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Sema.h"
+#include "SemaInit.h"
+#include "clang/AST/ExprCXX.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/CXXInheritance.h"
+#include "clang/Basic/PartialDiagnostic.h"
+#include "llvm/ADT/SmallVector.h"
+#include <set>
+using namespace clang;
+
+enum TryCastResult {
+  TC_NotApplicable, ///< The cast method is not applicable.
+  TC_Success,       ///< The cast method is appropriate and successful.
+  TC_Failed         ///< The cast method is appropriate, but failed. A
+                    ///< diagnostic has been emitted.
+};
+
+enum CastType {
+  CT_Const,       ///< const_cast
+  CT_Static,      ///< static_cast
+  CT_Reinterpret, ///< reinterpret_cast
+  CT_Dynamic,     ///< dynamic_cast
+  CT_CStyle,      ///< (Type)expr
+  CT_Functional   ///< Type(expr)
+};
+
+static void CheckConstCast(Sema &Self, Expr *&SrcExpr, QualType DestType,
+                           const SourceRange &OpRange,
+                           const SourceRange &DestRange);
+static void CheckReinterpretCast(Sema &Self, Expr *&SrcExpr, QualType DestType,
+                                 const SourceRange &OpRange,
+                                 const SourceRange &DestRange,
+                                 CastExpr::CastKind &Kind);
+static void CheckStaticCast(Sema &Self, Expr *&SrcExpr, QualType DestType,
+                            const SourceRange &OpRange,
+                            CastExpr::CastKind &Kind,
+                            CXXMethodDecl *&ConversionDecl);
+static void CheckDynamicCast(Sema &Self, Expr *&SrcExpr, QualType DestType,
+                             const SourceRange &OpRange,
+                             const SourceRange &DestRange,
+                             CastExpr::CastKind &Kind);
+
+static bool CastsAwayConstness(Sema &Self, QualType SrcType, QualType DestType);
+
+// The Try functions attempt a specific way of casting. If they succeed, they
+// return TC_Success. If their way of casting is not appropriate for the given
+// arguments, they return TC_NotApplicable and *may* set diag to a diagnostic
+// to emit if no other way succeeds. If their way of casting is appropriate but
+// fails, they return TC_Failed and *must* set diag; they can set it to 0 if
+// they emit a specialized diagnostic.
+// All diagnostics returned by these functions must expect the same three
+// arguments:
+// %0: Cast Type (a value from the CastType enumeration)
+// %1: Source Type
+// %2: Destination Type
+static TryCastResult TryLValueToRValueCast(Sema &Self, Expr *SrcExpr,
+                                           QualType DestType, unsigned &msg);
+static TryCastResult TryStaticReferenceDowncast(Sema &Self, Expr *SrcExpr,
+                                                QualType DestType, bool CStyle,
+                                                const SourceRange &OpRange,
+                                                unsigned &msg,
+                                                CastExpr::CastKind &Kind);
+static TryCastResult TryStaticPointerDowncast(Sema &Self, QualType SrcType,
+                                              QualType DestType, bool CStyle,
+                                              const SourceRange &OpRange,
+                                              unsigned &msg,
+                                              CastExpr::CastKind &Kind);
+static TryCastResult TryStaticDowncast(Sema &Self, CanQualType SrcType,
+                                       CanQualType DestType, bool CStyle,
+                                       const SourceRange &OpRange,
+                                       QualType OrigSrcType,
+                                       QualType OrigDestType, unsigned &msg,
+                                       CastExpr::CastKind &Kind);
+static TryCastResult TryStaticMemberPointerUpcast(Sema &Self, QualType SrcType,
+                                                  QualType DestType,bool CStyle,
+                                                  const SourceRange &OpRange,
+                                                  unsigned &msg,
+                                                  CastExpr::CastKind &Kind);
+static TryCastResult TryStaticImplicitCast(Sema &Self, Expr *&SrcExpr,
+                                           QualType DestType, bool CStyle,
+                                           const SourceRange &OpRange,
+                                           unsigned &msg,
+                                           CastExpr::CastKind &Kind,
+                                           CXXMethodDecl *&ConversionDecl);
+static TryCastResult TryStaticCast(Sema &Self, Expr *&SrcExpr,
+                                   QualType DestType, bool CStyle,
+                                   const SourceRange &OpRange,
+                                   unsigned &msg,
+                                   CastExpr::CastKind &Kind,
+                                   CXXMethodDecl *&ConversionDecl);
+static TryCastResult TryConstCast(Sema &Self, Expr *SrcExpr, QualType DestType,
+                                  bool CStyle, unsigned &msg);
+static TryCastResult TryReinterpretCast(Sema &Self, Expr *SrcExpr,
+                                        QualType DestType, bool CStyle,
+                                        const SourceRange &OpRange,
+                                        unsigned &msg,
+                                        CastExpr::CastKind &Kind);
+
+/// ActOnCXXNamedCast - Parse {dynamic,static,reinterpret,const}_cast's.
+Action::OwningExprResult
+Sema::ActOnCXXNamedCast(SourceLocation OpLoc, tok::TokenKind Kind,
+                        SourceLocation LAngleBracketLoc, TypeTy *Ty,
+                        SourceLocation RAngleBracketLoc,
+                        SourceLocation LParenLoc, ExprArg E,
+                        SourceLocation RParenLoc) {
+  
+  TypeSourceInfo *DestTInfo;
+  QualType DestType = GetTypeFromParser(Ty, &DestTInfo);
+  if (!DestTInfo)
+    DestTInfo = Context.getTrivialTypeSourceInfo(DestType, SourceLocation());
+
+  return BuildCXXNamedCast(OpLoc, Kind, DestTInfo, move(E),
+                           SourceRange(LAngleBracketLoc, RAngleBracketLoc),
+                           SourceRange(LParenLoc, RParenLoc));
+}
+
+Action::OwningExprResult
+Sema::BuildCXXNamedCast(SourceLocation OpLoc, tok::TokenKind Kind,
+                        TypeSourceInfo *DestTInfo, ExprArg E,
+                        SourceRange AngleBrackets, SourceRange Parens) {
+  Expr *Ex = E.takeAs<Expr>();
+  QualType DestType = DestTInfo->getType();
+
+  SourceRange OpRange(OpLoc, Parens.getEnd());
+  SourceRange DestRange = AngleBrackets;
+
+  // If the type is dependent, we won't do the semantic analysis now.
+  // FIXME: should we check this in a more fine-grained manner?
+  bool TypeDependent = DestType->isDependentType() || Ex->isTypeDependent();
+
+  switch (Kind) {
+  default: assert(0 && "Unknown C++ cast!");
+
+  case tok::kw_const_cast:
+    if (!TypeDependent)
+      CheckConstCast(*this, Ex, DestType, OpRange, DestRange);
+    return Owned(new (Context) CXXConstCastExpr(DestType.getNonReferenceType(),
+                                                Ex, DestTInfo, OpLoc));
+
+  case tok::kw_dynamic_cast: {
+    CastExpr::CastKind Kind = CastExpr::CK_Unknown;
+    if (!TypeDependent)
+      CheckDynamicCast(*this, Ex, DestType, OpRange, DestRange, Kind);
+    return Owned(new (Context)CXXDynamicCastExpr(DestType.getNonReferenceType(),
+                                                 Kind, Ex, DestTInfo, OpLoc));
+  }
+  case tok::kw_reinterpret_cast: {
+    CastExpr::CastKind Kind = CastExpr::CK_Unknown;
+    if (!TypeDependent)
+      CheckReinterpretCast(*this, Ex, DestType, OpRange, DestRange, Kind);
+    return Owned(new (Context) CXXReinterpretCastExpr(
+                                  DestType.getNonReferenceType(),
+                                  Kind, Ex, DestTInfo, OpLoc));
+  }
+  case tok::kw_static_cast: {
+    CastExpr::CastKind Kind = CastExpr::CK_Unknown;
+    if (!TypeDependent) {
+      CXXMethodDecl *Method = 0;
+      
+      CheckStaticCast(*this, Ex, DestType, OpRange, Kind, Method);
+      
+      if (Method) {
+        OwningExprResult CastArg 
+          = BuildCXXCastArgument(OpLoc, DestType.getNonReferenceType(), 
+                                 Kind, Method, Owned(Ex));
+          if (CastArg.isInvalid())
+            return ExprError();
+          
+          Ex = CastArg.takeAs<Expr>();
+      }
+    }
+    
+    return Owned(new (Context) CXXStaticCastExpr(DestType.getNonReferenceType(),
+                                                 Kind, Ex, DestTInfo, OpLoc));
+  }
+  }
+
+  return ExprError();
+}
+
+/// UnwrapDissimilarPointerTypes - Like Sema::UnwrapSimilarPointerTypes,
+/// this removes one level of indirection from both types, provided that they're
+/// the same kind of pointer (plain or to-member). Unlike the Sema function,
+/// this one doesn't care if the two pointers-to-member don't point into the
+/// same class. This is because CastsAwayConstness doesn't care.
+bool UnwrapDissimilarPointerTypes(QualType& T1, QualType& T2) {
+  const PointerType *T1PtrType = T1->getAs<PointerType>(),
+                    *T2PtrType = T2->getAs<PointerType>();
+  if (T1PtrType && T2PtrType) {
+    T1 = T1PtrType->getPointeeType();
+    T2 = T2PtrType->getPointeeType();
+    return true;
+  }
+  const ObjCObjectPointerType *T1ObjCPtrType = 
+                                            T1->getAs<ObjCObjectPointerType>(),
+                              *T2ObjCPtrType = 
+                                            T2->getAs<ObjCObjectPointerType>();
+  if (T1ObjCPtrType) {
+    if (T2ObjCPtrType) {
+      T1 = T1ObjCPtrType->getPointeeType();
+      T2 = T2ObjCPtrType->getPointeeType();
+      return true;
+    }
+    else if (T2PtrType) {
+      T1 = T1ObjCPtrType->getPointeeType();
+      T2 = T2PtrType->getPointeeType();
+      return true;
+    }
+  }
+  else if (T2ObjCPtrType) {
+    if (T1PtrType) {
+      T2 = T2ObjCPtrType->getPointeeType();
+      T1 = T1PtrType->getPointeeType();
+      return true;
+    }
+  }
+  
+  const MemberPointerType *T1MPType = T1->getAs<MemberPointerType>(),
+                          *T2MPType = T2->getAs<MemberPointerType>();
+  if (T1MPType && T2MPType) {
+    T1 = T1MPType->getPointeeType();
+    T2 = T2MPType->getPointeeType();
+    return true;
+  }
+  return false;
+}
+
+/// CastsAwayConstness - Check if the pointer conversion from SrcType to
+/// DestType casts away constness as defined in C++ 5.2.11p8ff. This is used by
+/// the cast checkers.  Both arguments must denote pointer (possibly to member)
+/// types.
+static bool
+CastsAwayConstness(Sema &Self, QualType SrcType, QualType DestType) {
+  // Casting away constness is defined in C++ 5.2.11p8 with reference to
+  // C++ 4.4. We piggyback on Sema::IsQualificationConversion for this, since
+  // the rules are non-trivial. So first we construct Tcv *...cv* as described
+  // in C++ 5.2.11p8.
+  assert((SrcType->isAnyPointerType() || SrcType->isMemberPointerType()) &&
+         "Source type is not pointer or pointer to member.");
+  assert((DestType->isAnyPointerType() || DestType->isMemberPointerType()) &&
+         "Destination type is not pointer or pointer to member.");
+
+  QualType UnwrappedSrcType = Self.Context.getCanonicalType(SrcType), 
+           UnwrappedDestType = Self.Context.getCanonicalType(DestType);
+  llvm::SmallVector<Qualifiers, 8> cv1, cv2;
+
+  // Find the qualifications.
+  while (UnwrapDissimilarPointerTypes(UnwrappedSrcType, UnwrappedDestType)) {
+    cv1.push_back(UnwrappedSrcType.getQualifiers());
+    cv2.push_back(UnwrappedDestType.getQualifiers());
+  }
+  assert(cv1.size() > 0 && "Must have at least one pointer level.");
+
+  // Construct void pointers with those qualifiers (in reverse order of
+  // unwrapping, of course).
+  QualType SrcConstruct = Self.Context.VoidTy;
+  QualType DestConstruct = Self.Context.VoidTy;
+  ASTContext &Context = Self.Context;
+  for (llvm::SmallVector<Qualifiers, 8>::reverse_iterator i1 = cv1.rbegin(),
+                                                          i2 = cv2.rbegin();
+       i1 != cv1.rend(); ++i1, ++i2) {
+    SrcConstruct
+      = Context.getPointerType(Context.getQualifiedType(SrcConstruct, *i1));
+    DestConstruct
+      = Context.getPointerType(Context.getQualifiedType(DestConstruct, *i2));
+  }
+
+  // Test if they're compatible.
+  return SrcConstruct != DestConstruct &&
+    !Self.IsQualificationConversion(SrcConstruct, DestConstruct);
+}
+
+/// CheckDynamicCast - Check that a dynamic_cast\<DestType\>(SrcExpr) is valid.
+/// Refer to C++ 5.2.7 for details. Dynamic casts are used mostly for runtime-
+/// checked downcasts in class hierarchies.
+static void
+CheckDynamicCast(Sema &Self, Expr *&SrcExpr, QualType DestType,
+                 const SourceRange &OpRange,
+                 const SourceRange &DestRange, CastExpr::CastKind &Kind) {
+  QualType OrigDestType = DestType, OrigSrcType = SrcExpr->getType();
+  DestType = Self.Context.getCanonicalType(DestType);
+
+  // C++ 5.2.7p1: T shall be a pointer or reference to a complete class type,
+  //   or "pointer to cv void".
+
+  QualType DestPointee;
+  const PointerType *DestPointer = DestType->getAs<PointerType>();
+  const ReferenceType *DestReference = DestType->getAs<ReferenceType>();
+  if (DestPointer) {
+    DestPointee = DestPointer->getPointeeType();
+  } else if (DestReference) {
+    DestPointee = DestReference->getPointeeType();
+  } else {
+    Self.Diag(OpRange.getBegin(), diag::err_bad_dynamic_cast_not_ref_or_ptr)
+      << OrigDestType << DestRange;
+    return;
+  }
+
+  const RecordType *DestRecord = DestPointee->getAs<RecordType>();
+  if (DestPointee->isVoidType()) {
+    assert(DestPointer && "Reference to void is not possible");
+  } else if (DestRecord) {
+    if (Self.RequireCompleteType(OpRange.getBegin(), DestPointee,
+                                 PDiag(diag::err_bad_dynamic_cast_incomplete)
+                                   << DestRange))
+      return;
+  } else {
+    Self.Diag(OpRange.getBegin(), diag::err_bad_dynamic_cast_not_class)
+      << DestPointee.getUnqualifiedType() << DestRange;
+    return;
+  }
+
+  // C++0x 5.2.7p2: If T is a pointer type, v shall be an rvalue of a pointer to
+  //   complete class type, [...]. If T is an lvalue reference type, v shall be
+  //   an lvalue of a complete class type, [...]. If T is an rvalue reference
+  //   type, v shall be an expression having a complete effective class type,
+  //   [...]
+
+  QualType SrcType = Self.Context.getCanonicalType(OrigSrcType);
+  QualType SrcPointee;
+  if (DestPointer) {
+    if (const PointerType *SrcPointer = SrcType->getAs<PointerType>()) {
+      SrcPointee = SrcPointer->getPointeeType();
+    } else {
+      Self.Diag(OpRange.getBegin(), diag::err_bad_dynamic_cast_not_ptr)
+        << OrigSrcType << SrcExpr->getSourceRange();
+      return;
+    }
+  } else if (DestReference->isLValueReferenceType()) {
+    if (SrcExpr->isLvalue(Self.Context) != Expr::LV_Valid) {
+      Self.Diag(OpRange.getBegin(), diag::err_bad_cxx_cast_rvalue)
+        << CT_Dynamic << OrigSrcType << OrigDestType << OpRange;
+    }
+    SrcPointee = SrcType;
+  } else {
+    SrcPointee = SrcType;
+  }
+
+  const RecordType *SrcRecord = SrcPointee->getAs<RecordType>();
+  if (SrcRecord) {
+    if (Self.RequireCompleteType(OpRange.getBegin(), SrcPointee,
+                                 PDiag(diag::err_bad_dynamic_cast_incomplete)
+                                   << SrcExpr->getSourceRange()))
+      return;
+  } else {
+    Self.Diag(OpRange.getBegin(), diag::err_bad_dynamic_cast_not_class)
+      << SrcPointee.getUnqualifiedType() << SrcExpr->getSourceRange();
+    return;
+  }
+
+  assert((DestPointer || DestReference) &&
+    "Bad destination non-ptr/ref slipped through.");
+  assert((DestRecord || DestPointee->isVoidType()) &&
+    "Bad destination pointee slipped through.");
+  assert(SrcRecord && "Bad source pointee slipped through.");
+
+  // C++ 5.2.7p1: The dynamic_cast operator shall not cast away constness.
+  if (!DestPointee.isAtLeastAsQualifiedAs(SrcPointee)) {
+    Self.Diag(OpRange.getBegin(), diag::err_bad_cxx_cast_const_away)
+      << CT_Dynamic << OrigSrcType << OrigDestType << OpRange;
+    return;
+  }
+
+  // C++ 5.2.7p3: If the type of v is the same as the required result type,
+  //   [except for cv].
+  if (DestRecord == SrcRecord) {
+    return;
+  }
+
+  // C++ 5.2.7p5
+  // Upcasts are resolved statically.
+  if (DestRecord && Self.IsDerivedFrom(SrcPointee, DestPointee)) {
+    Self.CheckDerivedToBaseConversion(SrcPointee, DestPointee,
+                                      OpRange.getBegin(), OpRange);
+    Kind = CastExpr::CK_DerivedToBase;
+    // Diagnostic already emitted on error.
+    return;
+  }
+
+  // C++ 5.2.7p6: Otherwise, v shall be [polymorphic].
+  const RecordDecl *SrcDecl = SrcRecord->getDecl()->getDefinition(Self.Context);
+  assert(SrcDecl && "Definition missing");
+  if (!cast<CXXRecordDecl>(SrcDecl)->isPolymorphic()) {
+    Self.Diag(OpRange.getBegin(), diag::err_bad_dynamic_cast_not_polymorphic)
+      << SrcPointee.getUnqualifiedType() << SrcExpr->getSourceRange();
+  }
+
+  // Done. Everything else is run-time checks.
+  Kind = CastExpr::CK_Dynamic;
+}
+
+/// CheckConstCast - Check that a const_cast\<DestType\>(SrcExpr) is valid.
+/// Refer to C++ 5.2.11 for details. const_cast is typically used in code
+/// like this:
+/// const char *str = "literal";
+/// legacy_function(const_cast\<char*\>(str));
+void
+CheckConstCast(Sema &Self, Expr *&SrcExpr, QualType DestType,
+               const SourceRange &OpRange, const SourceRange &DestRange) {
+  if (!DestType->isLValueReferenceType())
+    Self.DefaultFunctionArrayLvalueConversion(SrcExpr);
+
+  unsigned msg = diag::err_bad_cxx_cast_generic;
+  if (TryConstCast(Self, SrcExpr, DestType, /*CStyle*/false, msg) != TC_Success
+      && msg != 0)
+    Self.Diag(OpRange.getBegin(), msg) << CT_Const
+      << SrcExpr->getType() << DestType << OpRange;
+}
+
+/// CheckReinterpretCast - Check that a reinterpret_cast\<DestType\>(SrcExpr) is
+/// valid.
+/// Refer to C++ 5.2.10 for details. reinterpret_cast is typically used in code
+/// like this:
+/// char *bytes = reinterpret_cast\<char*\>(int_ptr);
+void
+CheckReinterpretCast(Sema &Self, Expr *&SrcExpr, QualType DestType,
+                     const SourceRange &OpRange, const SourceRange &DestRange,
+                     CastExpr::CastKind &Kind) {
+  if (!DestType->isLValueReferenceType())
+    Self.DefaultFunctionArrayLvalueConversion(SrcExpr);
+
+  unsigned msg = diag::err_bad_cxx_cast_generic;
+  if (TryReinterpretCast(Self, SrcExpr, DestType, /*CStyle*/false, OpRange,
+                         msg, Kind)
+      != TC_Success && msg != 0)
+    Self.Diag(OpRange.getBegin(), msg) << CT_Reinterpret
+      << SrcExpr->getType() << DestType << OpRange;
+}
+
+
+/// CheckStaticCast - Check that a static_cast\<DestType\>(SrcExpr) is valid.
+/// Refer to C++ 5.2.9 for details. Static casts are mostly used for making
+/// implicit conversions explicit and getting rid of data loss warnings.
+void
+CheckStaticCast(Sema &Self, Expr *&SrcExpr, QualType DestType,
+                const SourceRange &OpRange, CastExpr::CastKind &Kind,
+                CXXMethodDecl *&ConversionDecl) {
+  // This test is outside everything else because it's the only case where
+  // a non-lvalue-reference target type does not lead to decay.
+  // C++ 5.2.9p4: Any expression can be explicitly converted to type "cv void".
+  if (DestType->isVoidType()) {
+    Kind = CastExpr::CK_ToVoid;
+    return;
+  }
+
+  if (!DestType->isLValueReferenceType() && !DestType->isRecordType())
+    Self.DefaultFunctionArrayLvalueConversion(SrcExpr);
+
+  unsigned msg = diag::err_bad_cxx_cast_generic;
+  if (TryStaticCast(Self, SrcExpr, DestType, /*CStyle*/false, OpRange, msg,
+                    Kind, ConversionDecl)
+      != TC_Success && msg != 0)
+    Self.Diag(OpRange.getBegin(), msg) << CT_Static
+      << SrcExpr->getType() << DestType << OpRange;
+}
+
+/// TryStaticCast - Check if a static cast can be performed, and do so if
+/// possible. If @p CStyle, ignore access restrictions on hierarchy casting
+/// and casting away constness.
+static TryCastResult TryStaticCast(Sema &Self, Expr *&SrcExpr,
+                                   QualType DestType, bool CStyle,
+                                   const SourceRange &OpRange, unsigned &msg,
+                                   CastExpr::CastKind &Kind,
+                                   CXXMethodDecl *&ConversionDecl) {
+  // The order the tests is not entirely arbitrary. There is one conversion
+  // that can be handled in two different ways. Given:
+  // struct A {};
+  // struct B : public A {
+  //   B(); B(const A&);
+  // };
+  // const A &a = B();
+  // the cast static_cast<const B&>(a) could be seen as either a static
+  // reference downcast, or an explicit invocation of the user-defined
+  // conversion using B's conversion constructor.
+  // DR 427 specifies that the downcast is to be applied here.
+
+  // C++ 5.2.9p4: Any expression can be explicitly converted to type "cv void".
+  // Done outside this function.
+
+  TryCastResult tcr;
+
+  // C++ 5.2.9p5, reference downcast.
+  // See the function for details.
+  // DR 427 specifies that this is to be applied before paragraph 2.
+  tcr = TryStaticReferenceDowncast(Self, SrcExpr, DestType, CStyle, OpRange,
+                                   msg, Kind);
+  if (tcr != TC_NotApplicable)
+    return tcr;
+
+  // N2844 5.2.9p3: An lvalue of type "cv1 T1" can be cast to type "rvalue
+  //   reference to cv2 T2" if "cv2 T2" is reference-compatible with "cv1 T1".
+  tcr = TryLValueToRValueCast(Self, SrcExpr, DestType, msg);
+  if (tcr != TC_NotApplicable) {
+    Kind = CastExpr::CK_NoOp;
+    return tcr;
+  }
+
+  // C++ 5.2.9p2: An expression e can be explicitly converted to a type T
+  //   [...] if the declaration "T t(e);" is well-formed, [...].
+  tcr = TryStaticImplicitCast(Self, SrcExpr, DestType, CStyle, OpRange, msg,
+                              Kind, ConversionDecl);
+  if (tcr != TC_NotApplicable)
+    return tcr;
+  
+  // C++ 5.2.9p6: May apply the reverse of any standard conversion, except
+  // lvalue-to-rvalue, array-to-pointer, function-to-pointer, and boolean
+  // conversions, subject to further restrictions.
+  // Also, C++ 5.2.9p1 forbids casting away constness, which makes reversal
+  // of qualification conversions impossible.
+  // In the CStyle case, the earlier attempt to const_cast should have taken
+  // care of reverse qualification conversions.
+
+  QualType OrigSrcType = SrcExpr->getType();
+
+  QualType SrcType = Self.Context.getCanonicalType(SrcExpr->getType());
+
+  // Reverse integral promotion/conversion. All such conversions are themselves
+  // again integral promotions or conversions and are thus already handled by
+  // p2 (TryDirectInitialization above).
+  // (Note: any data loss warnings should be suppressed.)
+  // The exception is the reverse of enum->integer, i.e. integer->enum (and
+  // enum->enum). See also C++ 5.2.9p7.
+  // The same goes for reverse floating point promotion/conversion and
+  // floating-integral conversions. Again, only floating->enum is relevant.
+  if (DestType->isEnumeralType()) {
+    if (SrcType->isComplexType() || SrcType->isVectorType()) {
+      // Fall through - these cannot be converted.
+    } else if (SrcType->isArithmeticType() || SrcType->isEnumeralType()) {
+      Kind = CastExpr::CK_IntegralCast;
+      return TC_Success;
+    }
+  }
+
+  // Reverse pointer upcast. C++ 4.10p3 specifies pointer upcast.
+  // C++ 5.2.9p8 additionally disallows a cast path through virtual inheritance.
+  tcr = TryStaticPointerDowncast(Self, SrcType, DestType, CStyle, OpRange, msg,
+                                 Kind);
+  if (tcr != TC_NotApplicable)
+    return tcr;
+
+  // Reverse member pointer conversion. C++ 4.11 specifies member pointer
+  // conversion. C++ 5.2.9p9 has additional information.
+  // DR54's access restrictions apply here also.
+  tcr = TryStaticMemberPointerUpcast(Self, SrcType, DestType, CStyle,
+                                     OpRange, msg, Kind);
+  if (tcr != TC_NotApplicable)
+    return tcr;
+
+  // Reverse pointer conversion to void*. C++ 4.10.p2 specifies conversion to
+  // void*. C++ 5.2.9p10 specifies additional restrictions, which really is
+  // just the usual constness stuff.
+  if (const PointerType *SrcPointer = SrcType->getAs<PointerType>()) {
+    QualType SrcPointee = SrcPointer->getPointeeType();
+    if (SrcPointee->isVoidType()) {
+      if (const PointerType *DestPointer = DestType->getAs<PointerType>()) {
+        QualType DestPointee = DestPointer->getPointeeType();
+        if (DestPointee->isIncompleteOrObjectType()) {
+          // This is definitely the intended conversion, but it might fail due
+          // to a const violation.
+          if (!CStyle && !DestPointee.isAtLeastAsQualifiedAs(SrcPointee)) {
+            msg = diag::err_bad_cxx_cast_const_away;
+            return TC_Failed;
+          }
+          Kind = CastExpr::CK_BitCast;
+          return TC_Success;
+        }
+      }
+      else if (CStyle && DestType->isObjCObjectPointerType()) {
+        // allow c-style cast of objective-c pointers as they are pervasive.
+        Kind = CastExpr::CK_AnyPointerToObjCPointerCast;
+        return TC_Success;
+      }
+      else if (CStyle && DestType->isBlockPointerType()) {
+        // allow c-style cast of void * to block pointers.
+        Kind = CastExpr::CK_AnyPointerToBlockPointerCast;
+        return TC_Success;
+      }
+    }
+  }
+
+  // We tried everything. Everything! Nothing works! :-(
+  return TC_NotApplicable;
+}
+
+/// Tests whether a conversion according to N2844 is valid.
+TryCastResult
+TryLValueToRValueCast(Sema &Self, Expr *SrcExpr, QualType DestType,
+                      unsigned &msg) {
+  // N2844 5.2.9p3: An lvalue of type "cv1 T1" can be cast to type "rvalue
+  //   reference to cv2 T2" if "cv2 T2" is reference-compatible with "cv1 T1".
+  const RValueReferenceType *R = DestType->getAs<RValueReferenceType>();
+  if (!R)
+    return TC_NotApplicable;
+
+  if (SrcExpr->isLvalue(Self.Context) != Expr::LV_Valid)
+    return TC_NotApplicable;
+
+  // Because we try the reference downcast before this function, from now on
+  // this is the only cast possibility, so we issue an error if we fail now.
+  // FIXME: Should allow casting away constness if CStyle.
+  bool DerivedToBase;
+  if (Self.CompareReferenceRelationship(SrcExpr->getLocStart(),
+                                        SrcExpr->getType(), R->getPointeeType(),
+                                        DerivedToBase) <
+        Sema::Ref_Compatible_With_Added_Qualification) {
+    msg = diag::err_bad_lvalue_to_rvalue_cast;
+    return TC_Failed;
+  }
+
+  // FIXME: Similar to CheckReferenceInit, we actually need more AST annotation
+  // than nothing.
+  return TC_Success;
+}
+
+/// Tests whether a conversion according to C++ 5.2.9p5 is valid.
+TryCastResult
+TryStaticReferenceDowncast(Sema &Self, Expr *SrcExpr, QualType DestType,
+                           bool CStyle, const SourceRange &OpRange,
+                           unsigned &msg, CastExpr::CastKind &Kind) {
+  // C++ 5.2.9p5: An lvalue of type "cv1 B", where B is a class type, can be
+  //   cast to type "reference to cv2 D", where D is a class derived from B,
+  //   if a valid standard conversion from "pointer to D" to "pointer to B"
+  //   exists, cv2 >= cv1, and B is not a virtual base class of D.
+  // In addition, DR54 clarifies that the base must be accessible in the
+  // current context. Although the wording of DR54 only applies to the pointer
+  // variant of this rule, the intent is clearly for it to apply to the this
+  // conversion as well.
+
+  const ReferenceType *DestReference = DestType->getAs<ReferenceType>();
+  if (!DestReference) {
+    return TC_NotApplicable;
+  }
+  bool RValueRef = DestReference->isRValueReferenceType();
+  if (!RValueRef && SrcExpr->isLvalue(Self.Context) != Expr::LV_Valid) {
+    // We know the left side is an lvalue reference, so we can suggest a reason.
+    msg = diag::err_bad_cxx_cast_rvalue;
+    return TC_NotApplicable;
+  }
+
+  QualType DestPointee = DestReference->getPointeeType();
+
+  return TryStaticDowncast(Self, 
+                           Self.Context.getCanonicalType(SrcExpr->getType()), 
+                           Self.Context.getCanonicalType(DestPointee), CStyle,
+                           OpRange, SrcExpr->getType(), DestType, msg, Kind);
+}
+
+/// Tests whether a conversion according to C++ 5.2.9p8 is valid.
+TryCastResult
+TryStaticPointerDowncast(Sema &Self, QualType SrcType, QualType DestType,
+                         bool CStyle, const SourceRange &OpRange,
+                         unsigned &msg, CastExpr::CastKind &Kind) {
+  // C++ 5.2.9p8: An rvalue of type "pointer to cv1 B", where B is a class
+  //   type, can be converted to an rvalue of type "pointer to cv2 D", where D
+  //   is a class derived from B, if a valid standard conversion from "pointer
+  //   to D" to "pointer to B" exists, cv2 >= cv1, and B is not a virtual base
+  //   class of D.
+  // In addition, DR54 clarifies that the base must be accessible in the
+  // current context.
+
+  const PointerType *DestPointer = DestType->getAs<PointerType>();
+  if (!DestPointer) {
+    return TC_NotApplicable;
+  }
+
+  const PointerType *SrcPointer = SrcType->getAs<PointerType>();
+  if (!SrcPointer) {
+    msg = diag::err_bad_static_cast_pointer_nonpointer;
+    return TC_NotApplicable;
+  }
+
+  return TryStaticDowncast(Self, 
+                   Self.Context.getCanonicalType(SrcPointer->getPointeeType()),
+                  Self.Context.getCanonicalType(DestPointer->getPointeeType()), 
+                           CStyle, OpRange, SrcType, DestType, msg, Kind);
+}
+
+/// TryStaticDowncast - Common functionality of TryStaticReferenceDowncast and
+/// TryStaticPointerDowncast. Tests whether a static downcast from SrcType to
+/// DestType is possible and allowed.
+TryCastResult
+TryStaticDowncast(Sema &Self, CanQualType SrcType, CanQualType DestType,
+                  bool CStyle, const SourceRange &OpRange, QualType OrigSrcType,
+                  QualType OrigDestType, unsigned &msg, 
+                  CastExpr::CastKind &Kind) {
+  // We can only work with complete types. But don't complain if it doesn't work
+  if (Self.RequireCompleteType(OpRange.getBegin(), SrcType, PDiag(0)) ||
+      Self.RequireCompleteType(OpRange.getBegin(), DestType, PDiag(0)))
+    return TC_NotApplicable;
+
+  // Downcast can only happen in class hierarchies, so we need classes.
+  if (!DestType->getAs<RecordType>() || !SrcType->getAs<RecordType>()) {
+    return TC_NotApplicable;
+  }
+
+  CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/!CStyle,
+                     /*DetectVirtual=*/true);
+  if (!Self.IsDerivedFrom(DestType, SrcType, Paths)) {
+    return TC_NotApplicable;
+  }
+
+  // Target type does derive from source type. Now we're serious. If an error
+  // appears now, it's not ignored.
+  // This may not be entirely in line with the standard. Take for example:
+  // struct A {};
+  // struct B : virtual A {
+  //   B(A&);
+  // };
+  //
+  // void f()
+  // {
+  //   (void)static_cast<const B&>(*((A*)0));
+  // }
+  // As far as the standard is concerned, p5 does not apply (A is virtual), so
+  // p2 should be used instead - "const B& t(*((A*)0));" is perfectly valid.
+  // However, both GCC and Comeau reject this example, and accepting it would
+  // mean more complex code if we're to preserve the nice error message.
+  // FIXME: Being 100% compliant here would be nice to have.
+
+  // Must preserve cv, as always, unless we're in C-style mode.
+  if (!CStyle && !DestType.isAtLeastAsQualifiedAs(SrcType)) {
+    msg = diag::err_bad_cxx_cast_const_away;
+    return TC_Failed;
+  }
+
+  if (Paths.isAmbiguous(SrcType.getUnqualifiedType())) {
+    // This code is analoguous to that in CheckDerivedToBaseConversion, except
+    // that it builds the paths in reverse order.
+    // To sum up: record all paths to the base and build a nice string from
+    // them. Use it to spice up the error message.
+    if (!Paths.isRecordingPaths()) {
+      Paths.clear();
+      Paths.setRecordingPaths(true);
+      Self.IsDerivedFrom(DestType, SrcType, Paths);
+    }
+    std::string PathDisplayStr;
+    std::set<unsigned> DisplayedPaths;
+    for (CXXBasePaths::paths_iterator PI = Paths.begin(), PE = Paths.end();
+         PI != PE; ++PI) {
+      if (DisplayedPaths.insert(PI->back().SubobjectNumber).second) {
+        // We haven't displayed a path to this particular base
+        // class subobject yet.
+        PathDisplayStr += "\n    ";
+        for (CXXBasePath::const_reverse_iterator EI = PI->rbegin(),
+                                                 EE = PI->rend();
+             EI != EE; ++EI)
+          PathDisplayStr += EI->Base->getType().getAsString() + " -> ";
+        PathDisplayStr += QualType(DestType).getAsString();
+      }
+    }
+
+    Self.Diag(OpRange.getBegin(), diag::err_ambiguous_base_to_derived_cast)
+      << QualType(SrcType).getUnqualifiedType() 
+      << QualType(DestType).getUnqualifiedType()
+      << PathDisplayStr << OpRange;
+    msg = 0;
+    return TC_Failed;
+  }
+
+  if (Paths.getDetectedVirtual() != 0) {
+    QualType VirtualBase(Paths.getDetectedVirtual(), 0);
+    Self.Diag(OpRange.getBegin(), diag::err_static_downcast_via_virtual)
+      << OrigSrcType << OrigDestType << VirtualBase << OpRange;
+    msg = 0;
+    return TC_Failed;
+  }
+
+  if (!CStyle && Self.CheckBaseClassAccess(OpRange.getBegin(),
+                                           /*IsBaseToDerived*/ true,
+                                           SrcType, DestType,
+                                           Paths.front())) {
+    msg = 0;
+    return TC_Failed;
+  }
+
+  Kind = CastExpr::CK_BaseToDerived;
+  return TC_Success;
+}
+
+/// TryStaticMemberPointerUpcast - Tests whether a conversion according to
+/// C++ 5.2.9p9 is valid:
+///
+///   An rvalue of type "pointer to member of D of type cv1 T" can be
+///   converted to an rvalue of type "pointer to member of B of type cv2 T",
+///   where B is a base class of D [...].
+///
+TryCastResult
+TryStaticMemberPointerUpcast(Sema &Self, QualType SrcType, QualType DestType,
+                             bool CStyle, const SourceRange &OpRange,
+                             unsigned &msg, CastExpr::CastKind &Kind) {
+  const MemberPointerType *DestMemPtr = DestType->getAs<MemberPointerType>();
+  if (!DestMemPtr)
+    return TC_NotApplicable;
+  const MemberPointerType *SrcMemPtr = SrcType->getAs<MemberPointerType>();
+  if (!SrcMemPtr) {
+    msg = diag::err_bad_static_cast_member_pointer_nonmp;
+    return TC_NotApplicable;
+  }
+
+  // T == T, modulo cv
+  if (!Self.Context.hasSameUnqualifiedType(SrcMemPtr->getPointeeType(),
+                                           DestMemPtr->getPointeeType()))
+    return TC_NotApplicable;
+
+  // B base of D
+  QualType SrcClass(SrcMemPtr->getClass(), 0);
+  QualType DestClass(DestMemPtr->getClass(), 0);
+  CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/!CStyle,
+                  /*DetectVirtual=*/true);
+  if (!Self.IsDerivedFrom(SrcClass, DestClass, Paths)) {
+    return TC_NotApplicable;
+  }
+
+  // B is a base of D. But is it an allowed base? If not, it's a hard error.
+  if (Paths.isAmbiguous(DestClass)) {
+    Paths.clear();
+    Paths.setRecordingPaths(true);
+    bool StillOkay = Self.IsDerivedFrom(SrcClass, DestClass, Paths);
+    assert(StillOkay);
+    StillOkay = StillOkay;
+    std::string PathDisplayStr = Self.getAmbiguousPathsDisplayString(Paths);
+    Self.Diag(OpRange.getBegin(), diag::err_ambiguous_memptr_conv)
+      << 1 << SrcClass << DestClass << PathDisplayStr << OpRange;
+    msg = 0;
+    return TC_Failed;
+  }
+
+  if (const RecordType *VBase = Paths.getDetectedVirtual()) {
+    Self.Diag(OpRange.getBegin(), diag::err_memptr_conv_via_virtual)
+      << SrcClass << DestClass << QualType(VBase, 0) << OpRange;
+    msg = 0;
+    return TC_Failed;
+  }
+
+  if (!CStyle && Self.CheckBaseClassAccess(OpRange.getBegin(),
+                                           /*IsBaseToDerived*/ false,
+                                           DestType, SrcType,
+                                           Paths.front())) {
+    msg = 0;
+    return TC_Failed;
+  }
+
+  Kind = CastExpr::CK_DerivedToBaseMemberPointer;
+  return TC_Success;
+}
+
+/// TryStaticImplicitCast - Tests whether a conversion according to C++ 5.2.9p2
+/// is valid:
+///
+///   An expression e can be explicitly converted to a type T using a
+///   @c static_cast if the declaration "T t(e);" is well-formed [...].
+TryCastResult
+TryStaticImplicitCast(Sema &Self, Expr *&SrcExpr, QualType DestType,
+                      bool CStyle, const SourceRange &OpRange, unsigned &msg,
+                      CastExpr::CastKind &Kind, 
+                      CXXMethodDecl *&ConversionDecl) {
+  if (DestType->isRecordType()) {
+    if (Self.RequireCompleteType(OpRange.getBegin(), DestType,
+                                 diag::err_bad_dynamic_cast_incomplete)) {
+      msg = 0;
+      return TC_Failed;
+    }
+  }
+
+  if (DestType->isReferenceType()) {
+    // All reference bindings insert implicit casts above that do the actual
+    // casting.
+    Kind = CastExpr::CK_NoOp;
+
+    // At this point of CheckStaticCast, if the destination is a reference,
+    // this has to work. There is no other way that works.
+    // On the other hand, if we're checking a C-style cast, we've still got
+    // the reinterpret_cast way. So in C-style mode, we first try the call
+    // with an ICS to suppress errors.
+    if (CStyle) {
+      ImplicitConversionSequence ICS;
+      if(Self.CheckReferenceInit(SrcExpr, DestType, OpRange.getBegin(),
+                                 /*SuppressUserConversions=*/false,
+                                 /*AllowExplicit=*/false, /*ForceRValue=*/false,
+                                 &ICS))
+        return TC_NotApplicable;
+    }
+    // Now we're committed either way.
+    if(!Self.CheckReferenceInit(SrcExpr, DestType, OpRange.getBegin(),
+                                /*SuppressUserConversions=*/false,
+                                /*AllowExplicit=*/false,
+                                /*ForceRValue=*/false, 0,
+                                /*IgnoreBaseAccess=*/CStyle))
+      return TC_Success;
+
+    // We already got an error message.
+    msg = 0;
+    return TC_Failed;
+  }
+
+  if (DestType->isRecordType()) {
+    if (CXXConstructorDecl *Constructor
+          = Self.TryInitializationByConstructor(DestType, &SrcExpr, 1,
+                                                OpRange.getBegin(),
+              InitializationKind::CreateDirect(OpRange.getBegin(),
+                                               OpRange.getBegin(), 
+                                               OpRange.getEnd()))) {
+      ConversionDecl = Constructor;
+      Kind = CastExpr::CK_ConstructorConversion;
+      return TC_Success;
+    }
+    
+    return TC_NotApplicable;
+  }
+
+  // FIXME: To get a proper error from invalid conversions here, we need to
+  // reimplement more of this.
+  // FIXME: This does not actually perform the conversion, and thus does not
+  // check for ambiguity or access.
+  ImplicitConversionSequence ICS =
+    Self.TryImplicitConversion(SrcExpr, DestType,
+                               /*SuppressUserConversions=*/false,
+                               /*AllowExplicit=*/true,
+                               /*ForceRValue=*/false,
+                               /*InOverloadResolution=*/false,
+                               /*one of user provided casts*/true);
+
+  if (ICS.isBad())
+    return TC_NotApplicable;
+
+  // The conversion is possible, so commit to it.
+  Kind = CastExpr::CK_NoOp;
+  msg = 0;
+  return Self.PerformImplicitConversion(SrcExpr, DestType, ICS, Sema::AA_Casting,
+                                        /*IgnoreBaseAccess*/CStyle) ?
+      TC_Failed : TC_Success;
+}
+
+/// TryConstCast - See if a const_cast from source to destination is allowed,
+/// and perform it if it is.
+static TryCastResult TryConstCast(Sema &Self, Expr *SrcExpr, QualType DestType,
+                                  bool CStyle, unsigned &msg) {
+  DestType = Self.Context.getCanonicalType(DestType);
+  QualType SrcType = SrcExpr->getType();
+  if (const LValueReferenceType *DestTypeTmp =
+        DestType->getAs<LValueReferenceType>()) {
+    if (SrcExpr->isLvalue(Self.Context) != Expr::LV_Valid) {
+      // Cannot const_cast non-lvalue to lvalue reference type. But if this
+      // is C-style, static_cast might find a way, so we simply suggest a
+      // message and tell the parent to keep searching.
+      msg = diag::err_bad_cxx_cast_rvalue;
+      return TC_NotApplicable;
+    }
+
+    // C++ 5.2.11p4: An lvalue of type T1 can be [cast] to an lvalue of type T2
+    //   [...] if a pointer to T1 can be [cast] to the type pointer to T2.
+    DestType = Self.Context.getPointerType(DestTypeTmp->getPointeeType());
+    SrcType = Self.Context.getPointerType(SrcType);
+  }
+
+  // C++ 5.2.11p5: For a const_cast involving pointers to data members [...]
+  //   the rules for const_cast are the same as those used for pointers.
+
+  if (!DestType->isPointerType() && !DestType->isMemberPointerType()) {
+    // Cannot cast to non-pointer, non-reference type. Note that, if DestType
+    // was a reference type, we converted it to a pointer above.
+    // The status of rvalue references isn't entirely clear, but it looks like
+    // conversion to them is simply invalid.
+    // C++ 5.2.11p3: For two pointer types [...]
+    if (!CStyle)
+      msg = diag::err_bad_const_cast_dest;
+    return TC_NotApplicable;
+  }
+  if (DestType->isFunctionPointerType() ||
+      DestType->isMemberFunctionPointerType()) {
+    // Cannot cast direct function pointers.
+    // C++ 5.2.11p2: [...] where T is any object type or the void type [...]
+    // T is the ultimate pointee of source and target type.
+    if (!CStyle)
+      msg = diag::err_bad_const_cast_dest;
+    return TC_NotApplicable;
+  }
+  SrcType = Self.Context.getCanonicalType(SrcType);
+
+  // Unwrap the pointers. Ignore qualifiers. Terminate early if the types are
+  // completely equal.
+  // FIXME: const_cast should probably not be able to convert between pointers
+  // to different address spaces.
+  // C++ 5.2.11p3 describes the core semantics of const_cast. All cv specifiers
+  // in multi-level pointers may change, but the level count must be the same,
+  // as must be the final pointee type.
+  while (SrcType != DestType &&
+         Self.UnwrapSimilarPointerTypes(SrcType, DestType)) {
+    Qualifiers Quals;
+    SrcType = Self.Context.getUnqualifiedArrayType(SrcType, Quals);
+    DestType = Self.Context.getUnqualifiedArrayType(DestType, Quals);
+  }
+
+  // Since we're dealing in canonical types, the remainder must be the same.
+  if (SrcType != DestType)
+    return TC_NotApplicable;
+
+  return TC_Success;
+}
+
+static TryCastResult TryReinterpretCast(Sema &Self, Expr *SrcExpr,
+                                        QualType DestType, bool CStyle,
+                                        const SourceRange &OpRange,
+                                        unsigned &msg,
+                                        CastExpr::CastKind &Kind) {
+  DestType = Self.Context.getCanonicalType(DestType);
+  QualType SrcType = SrcExpr->getType();
+  if (const ReferenceType *DestTypeTmp = DestType->getAs<ReferenceType>()) {
+    bool LValue = DestTypeTmp->isLValueReferenceType();
+    if (LValue && SrcExpr->isLvalue(Self.Context) != Expr::LV_Valid) {
+      // Cannot cast non-lvalue to reference type. See the similar comment in
+      // const_cast.
+      msg = diag::err_bad_cxx_cast_rvalue;
+      return TC_NotApplicable;
+    }
+
+    // C++ 5.2.10p10: [...] a reference cast reinterpret_cast<T&>(x) has the
+    //   same effect as the conversion *reinterpret_cast<T*>(&x) with the
+    //   built-in & and * operators.
+    // This code does this transformation for the checked types.
+    DestType = Self.Context.getPointerType(DestTypeTmp->getPointeeType());
+    SrcType = Self.Context.getPointerType(SrcType);
+  }
+
+  // Canonicalize source for comparison.
+  SrcType = Self.Context.getCanonicalType(SrcType);
+
+  const MemberPointerType *DestMemPtr = DestType->getAs<MemberPointerType>(),
+                          *SrcMemPtr = SrcType->getAs<MemberPointerType>();
+  if (DestMemPtr && SrcMemPtr) {
+    // C++ 5.2.10p9: An rvalue of type "pointer to member of X of type T1"
+    //   can be explicitly converted to an rvalue of type "pointer to member
+    //   of Y of type T2" if T1 and T2 are both function types or both object
+    //   types.
+    if (DestMemPtr->getPointeeType()->isFunctionType() !=
+        SrcMemPtr->getPointeeType()->isFunctionType())
+      return TC_NotApplicable;
+
+    // C++ 5.2.10p2: The reinterpret_cast operator shall not cast away
+    //   constness.
+    // A reinterpret_cast followed by a const_cast can, though, so in C-style,
+    // we accept it.
+    if (!CStyle && CastsAwayConstness(Self, SrcType, DestType)) {
+      msg = diag::err_bad_cxx_cast_const_away;
+      return TC_Failed;
+    }
+
+    // A valid member pointer cast.
+    Kind = CastExpr::CK_BitCast;
+    return TC_Success;
+  }
+
+  // See below for the enumeral issue.
+  if (SrcType->isNullPtrType() && DestType->isIntegralType() &&
+      !DestType->isEnumeralType()) {
+    // C++0x 5.2.10p4: A pointer can be explicitly converted to any integral
+    //   type large enough to hold it. A value of std::nullptr_t can be
+    //   converted to an integral type; the conversion has the same meaning
+    //   and validity as a conversion of (void*)0 to the integral type.
+    if (Self.Context.getTypeSize(SrcType) >
+        Self.Context.getTypeSize(DestType)) {
+      msg = diag::err_bad_reinterpret_cast_small_int;
+      return TC_Failed;
+    }
+    Kind = CastExpr::CK_PointerToIntegral;
+    return TC_Success;
+  }
+
+  bool destIsVector = DestType->isVectorType();
+  bool srcIsVector = SrcType->isVectorType();
+  if (srcIsVector || destIsVector) {
+    bool srcIsScalar = SrcType->isIntegralType() && !SrcType->isEnumeralType();
+    bool destIsScalar = 
+      DestType->isIntegralType() && !DestType->isEnumeralType();
+    
+    // Check if this is a cast between a vector and something else.
+    if (!(srcIsScalar && destIsVector) && !(srcIsVector && destIsScalar) &&
+        !(srcIsVector && destIsVector))
+      return TC_NotApplicable;
+
+    // If both types have the same size, we can successfully cast.
+    if (Self.Context.getTypeSize(SrcType)
+          == Self.Context.getTypeSize(DestType)) {
+      Kind = CastExpr::CK_BitCast;
+      return TC_Success;
+    }
+    
+    if (destIsScalar)
+      msg = diag::err_bad_cxx_cast_vector_to_scalar_different_size;
+    else if (srcIsScalar)
+      msg = diag::err_bad_cxx_cast_scalar_to_vector_different_size;
+    else
+      msg = diag::err_bad_cxx_cast_vector_to_vector_different_size;
+    
+    return TC_Failed;
+  }
+  
+  bool destIsPtr = DestType->isAnyPointerType();
+  bool srcIsPtr = SrcType->isAnyPointerType();
+  if (!destIsPtr && !srcIsPtr) {
+    // Except for std::nullptr_t->integer and lvalue->reference, which are
+    // handled above, at least one of the two arguments must be a pointer.
+    return TC_NotApplicable;
+  }
+
+  if (SrcType == DestType) {
+    // C++ 5.2.10p2 has a note that mentions that, subject to all other
+    // restrictions, a cast to the same type is allowed. The intent is not
+    // entirely clear here, since all other paragraphs explicitly forbid casts
+    // to the same type. However, the behavior of compilers is pretty consistent
+    // on this point: allow same-type conversion if the involved types are
+    // pointers, disallow otherwise.
+    Kind = CastExpr::CK_NoOp;
+    return TC_Success;
+  }
+
+  // Note: Clang treats enumeration types as integral types. If this is ever
+  // changed for C++, the additional check here will be redundant.
+  if (DestType->isIntegralType() && !DestType->isEnumeralType()) {
+    assert(srcIsPtr && "One type must be a pointer");
+    // C++ 5.2.10p4: A pointer can be explicitly converted to any integral
+    //   type large enough to hold it.
+    if (Self.Context.getTypeSize(SrcType) >
+        Self.Context.getTypeSize(DestType)) {
+      msg = diag::err_bad_reinterpret_cast_small_int;
+      return TC_Failed;
+    }
+    Kind = CastExpr::CK_PointerToIntegral;
+    return TC_Success;
+  }
+
+  if (SrcType->isIntegralType() || SrcType->isEnumeralType()) {
+    assert(destIsPtr && "One type must be a pointer");
+    // C++ 5.2.10p5: A value of integral or enumeration type can be explicitly
+    //   converted to a pointer.
+    Kind = CastExpr::CK_IntegralToPointer;
+    return TC_Success;
+  }
+
+  if (!destIsPtr || !srcIsPtr) {
+    // With the valid non-pointer conversions out of the way, we can be even
+    // more stringent.
+    return TC_NotApplicable;
+  }
+
+  // C++ 5.2.10p2: The reinterpret_cast operator shall not cast away constness.
+  // The C-style cast operator can.
+  if (!CStyle && CastsAwayConstness(Self, SrcType, DestType)) {
+    msg = diag::err_bad_cxx_cast_const_away;
+    return TC_Failed;
+  }
+  if (CStyle && DestType->isObjCObjectPointerType()) {
+    Kind = CastExpr::CK_AnyPointerToObjCPointerCast;
+    return TC_Success;
+  }
+  
+  // Not casting away constness, so the only remaining check is for compatible
+  // pointer categories.
+  Kind = CastExpr::CK_BitCast;
+
+  if (SrcType->isFunctionPointerType()) {
+    if (DestType->isFunctionPointerType()) {
+      // C++ 5.2.10p6: A pointer to a function can be explicitly converted to
+      // a pointer to a function of a different type.
+      return TC_Success;
+    }
+
+    // C++0x 5.2.10p8: Converting a pointer to a function into a pointer to
+    //   an object type or vice versa is conditionally-supported.
+    // Compilers support it in C++03 too, though, because it's necessary for
+    // casting the return value of dlsym() and GetProcAddress().
+    // FIXME: Conditionally-supported behavior should be configurable in the
+    // TargetInfo or similar.
+    if (!Self.getLangOptions().CPlusPlus0x)
+      Self.Diag(OpRange.getBegin(), diag::ext_cast_fn_obj) << OpRange;
+    return TC_Success;
+  }
+
+  if (DestType->isFunctionPointerType()) {
+    // See above.
+    if (!Self.getLangOptions().CPlusPlus0x)
+      Self.Diag(OpRange.getBegin(), diag::ext_cast_fn_obj) << OpRange;
+    return TC_Success;
+  }
+
+  // C++ 5.2.10p7: A pointer to an object can be explicitly converted to
+  //   a pointer to an object of different type.
+  // Void pointers are not specified, but supported by every compiler out there.
+  // So we finish by allowing everything that remains - it's got to be two
+  // object pointers.
+  return TC_Success;
+}
+
+bool Sema::CXXCheckCStyleCast(SourceRange R, QualType CastTy, Expr *&CastExpr,
+                              CastExpr::CastKind &Kind, bool FunctionalStyle,
+                              CXXMethodDecl *&ConversionDecl) {
+  // This test is outside everything else because it's the only case where
+  // a non-lvalue-reference target type does not lead to decay.
+  // C++ 5.2.9p4: Any expression can be explicitly converted to type "cv void".
+  if (CastTy->isVoidType()) {
+    Kind = CastExpr::CK_ToVoid;
+    return false;
+  }
+
+  // If the type is dependent, we won't do any other semantic analysis now.
+  if (CastTy->isDependentType() || CastExpr->isTypeDependent())
+    return false;
+
+  if (!CastTy->isLValueReferenceType() && !CastTy->isRecordType())
+    DefaultFunctionArrayLvalueConversion(CastExpr);
+
+  // C++ [expr.cast]p5: The conversions performed by
+  //   - a const_cast,
+  //   - a static_cast,
+  //   - a static_cast followed by a const_cast,
+  //   - a reinterpret_cast, or
+  //   - a reinterpret_cast followed by a const_cast,
+  //   can be performed using the cast notation of explicit type conversion.
+  //   [...] If a conversion can be interpreted in more than one of the ways
+  //   listed above, the interpretation that appears first in the list is used,
+  //   even if a cast resulting from that interpretation is ill-formed.
+  // In plain language, this means trying a const_cast ...
+  unsigned msg = diag::err_bad_cxx_cast_generic;
+  TryCastResult tcr = TryConstCast(*this, CastExpr, CastTy, /*CStyle*/true,
+                                   msg);
+  if (tcr == TC_Success)
+    Kind = CastExpr::CK_NoOp;
+
+  if (tcr == TC_NotApplicable) {
+    // ... or if that is not possible, a static_cast, ignoring const, ...
+    tcr = TryStaticCast(*this, CastExpr, CastTy, /*CStyle*/true, R, msg,
+                        Kind, ConversionDecl);
+    if (tcr == TC_NotApplicable) {
+      // ... and finally a reinterpret_cast, ignoring const.
+      tcr = TryReinterpretCast(*this, CastExpr, CastTy, /*CStyle*/true, R, msg,
+                               Kind);
+    }
+  }
+
+  if (tcr != TC_Success && msg != 0)
+    Diag(R.getBegin(), msg) << (FunctionalStyle ? CT_Functional : CT_CStyle)
+      << CastExpr->getType() << CastTy << R;
+
+  return tcr != TC_Success;
+}
diff --git a/lib/Sema/SemaCXXScopeSpec.cpp b/lib/Sema/SemaCXXScopeSpec.cpp
new file mode 100644
index 0000000..52e9e9b
--- /dev/null
+++ b/lib/Sema/SemaCXXScopeSpec.cpp
@@ -0,0 +1,665 @@
+//===--- SemaCXXScopeSpec.cpp - Semantic Analysis for C++ scope specifiers-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements C++ semantic analysis for scope specifiers.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Sema.h"
+#include "Lookup.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/DeclTemplate.h"
+#include "clang/AST/ExprCXX.h"
+#include "clang/AST/NestedNameSpecifier.h"
+#include "clang/Basic/PartialDiagnostic.h"
+#include "clang/Parse/DeclSpec.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/Support/raw_ostream.h"
+using namespace clang;
+
+/// \brief Find the current instantiation that associated with the given type.
+static CXXRecordDecl *
+getCurrentInstantiationOf(ASTContext &Context, DeclContext *CurContext, 
+                          QualType T) {
+  if (T.isNull())
+    return 0;
+  
+  T = Context.getCanonicalType(T).getUnqualifiedType();
+  
+  for (DeclContext *Ctx = CurContext; Ctx; Ctx = Ctx->getLookupParent()) {
+    // If we've hit a namespace or the global scope, then the
+    // nested-name-specifier can't refer to the current instantiation.
+    if (Ctx->isFileContext())
+      return 0;
+    
+    // Skip non-class contexts.
+    CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(Ctx);
+    if (!Record)
+      continue;
+    
+    // If this record type is not dependent,
+    if (!Record->isDependentType())
+      return 0;
+    
+    // C++ [temp.dep.type]p1:
+    //
+    //   In the definition of a class template, a nested class of a
+    //   class template, a member of a class template, or a member of a
+    //   nested class of a class template, a name refers to the current
+    //   instantiation if it is
+    //     -- the injected-class-name (9) of the class template or
+    //        nested class,
+    //     -- in the definition of a primary class template, the name
+    //        of the class template followed by the template argument
+    //        list of the primary template (as described below)
+    //        enclosed in <>,
+    //     -- in the definition of a nested class of a class template,
+    //        the name of the nested class referenced as a member of
+    //        the current instantiation, or
+    //     -- in the definition of a partial specialization, the name
+    //        of the class template followed by the template argument
+    //        list of the partial specialization enclosed in <>. If
+    //        the nth template parameter is a parameter pack, the nth
+    //        template argument is a pack expansion (14.6.3) whose
+    //        pattern is the name of the parameter pack.
+    //        (FIXME: parameter packs)
+    //
+    // All of these options come down to having the
+    // nested-name-specifier type that is equivalent to the
+    // injected-class-name of one of the types that is currently in
+    // our context.
+    if (Context.getCanonicalType(Context.getTypeDeclType(Record)) == T)
+      return Record;
+    
+    if (ClassTemplateDecl *Template = Record->getDescribedClassTemplate()) {
+      QualType InjectedClassName
+        = Template->getInjectedClassNameType(Context);
+      if (T == Context.getCanonicalType(InjectedClassName))
+        return Template->getTemplatedDecl();
+    }
+    // FIXME: check for class template partial specializations
+  }  
+  
+  return 0;
+}
+
+/// \brief Compute the DeclContext that is associated with the given type.
+///
+/// \param T the type for which we are attempting to find a DeclContext.
+///
+/// \returns the declaration context represented by the type T,
+/// or NULL if the declaration context cannot be computed (e.g., because it is
+/// dependent and not the current instantiation).
+DeclContext *Sema::computeDeclContext(QualType T) {
+  if (const TagType *Tag = T->getAs<TagType>())
+    return Tag->getDecl();
+
+  return ::getCurrentInstantiationOf(Context, CurContext, T);
+}
+
+/// \brief Compute the DeclContext that is associated with the given
+/// scope specifier.
+///
+/// \param SS the C++ scope specifier as it appears in the source
+///
+/// \param EnteringContext when true, we will be entering the context of
+/// this scope specifier, so we can retrieve the declaration context of a
+/// class template or class template partial specialization even if it is
+/// not the current instantiation.
+///
+/// \returns the declaration context represented by the scope specifier @p SS,
+/// or NULL if the declaration context cannot be computed (e.g., because it is
+/// dependent and not the current instantiation).
+DeclContext *Sema::computeDeclContext(const CXXScopeSpec &SS,
+                                      bool EnteringContext) {
+  if (!SS.isSet() || SS.isInvalid())
+    return 0;
+
+  NestedNameSpecifier *NNS
+    = static_cast<NestedNameSpecifier *>(SS.getScopeRep());
+  if (NNS->isDependent()) {
+    // If this nested-name-specifier refers to the current
+    // instantiation, return its DeclContext.
+    if (CXXRecordDecl *Record = getCurrentInstantiationOf(NNS))
+      return Record;
+
+    if (EnteringContext) {
+      if (const TemplateSpecializationType *SpecType
+            = dyn_cast_or_null<TemplateSpecializationType>(NNS->getAsType())) {
+        // We are entering the context of the nested name specifier, so try to
+        // match the nested name specifier to either a primary class template
+        // or a class template partial specialization.
+        if (ClassTemplateDecl *ClassTemplate
+              = dyn_cast_or_null<ClassTemplateDecl>(
+                            SpecType->getTemplateName().getAsTemplateDecl())) {
+          QualType ContextType
+            = Context.getCanonicalType(QualType(SpecType, 0));
+
+          // If the type of the nested name specifier is the same as the
+          // injected class name of the named class template, we're entering
+          // into that class template definition.
+          QualType Injected = ClassTemplate->getInjectedClassNameType(Context);
+          if (Context.hasSameType(Injected, ContextType))
+            return ClassTemplate->getTemplatedDecl();
+
+          // If the type of the nested name specifier is the same as the
+          // type of one of the class template's class template partial
+          // specializations, we're entering into the definition of that
+          // class template partial specialization.
+          if (ClassTemplatePartialSpecializationDecl *PartialSpec
+                = ClassTemplate->findPartialSpecialization(ContextType))
+            return PartialSpec;
+        }
+      } else if (const RecordType *RecordT
+                   = dyn_cast_or_null<RecordType>(NNS->getAsType())) {
+        // The nested name specifier refers to a member of a class template.
+        return RecordT->getDecl();
+      }
+    }
+
+    return 0;
+  }
+
+  switch (NNS->getKind()) {
+  case NestedNameSpecifier::Identifier:
+    assert(false && "Dependent nested-name-specifier has no DeclContext");
+    break;
+
+  case NestedNameSpecifier::Namespace:
+    return NNS->getAsNamespace();
+
+  case NestedNameSpecifier::TypeSpec:
+  case NestedNameSpecifier::TypeSpecWithTemplate: {
+    const TagType *Tag = NNS->getAsType()->getAs<TagType>();
+    assert(Tag && "Non-tag type in nested-name-specifier");
+    return Tag->getDecl();
+  } break;
+
+  case NestedNameSpecifier::Global:
+    return Context.getTranslationUnitDecl();
+  }
+
+  // Required to silence a GCC warning.
+  return 0;
+}
+
+bool Sema::isDependentScopeSpecifier(const CXXScopeSpec &SS) {
+  if (!SS.isSet() || SS.isInvalid())
+    return false;
+
+  NestedNameSpecifier *NNS
+    = static_cast<NestedNameSpecifier *>(SS.getScopeRep());
+  return NNS->isDependent();
+}
+
+// \brief Determine whether this C++ scope specifier refers to an
+// unknown specialization, i.e., a dependent type that is not the
+// current instantiation.
+bool Sema::isUnknownSpecialization(const CXXScopeSpec &SS) {
+  if (!isDependentScopeSpecifier(SS))
+    return false;
+
+  NestedNameSpecifier *NNS
+    = static_cast<NestedNameSpecifier *>(SS.getScopeRep());
+  return getCurrentInstantiationOf(NNS) == 0;
+}
+
+/// \brief If the given nested name specifier refers to the current
+/// instantiation, return the declaration that corresponds to that
+/// current instantiation (C++0x [temp.dep.type]p1).
+///
+/// \param NNS a dependent nested name specifier.
+CXXRecordDecl *Sema::getCurrentInstantiationOf(NestedNameSpecifier *NNS) {
+  assert(getLangOptions().CPlusPlus && "Only callable in C++");
+  assert(NNS->isDependent() && "Only dependent nested-name-specifier allowed");
+
+  if (!NNS->getAsType())
+    return 0;
+
+  QualType T = QualType(NNS->getAsType(), 0);
+  return ::getCurrentInstantiationOf(Context, CurContext, T);
+}
+
+/// \brief Require that the context specified by SS be complete.
+///
+/// If SS refers to a type, this routine checks whether the type is
+/// complete enough (or can be made complete enough) for name lookup
+/// into the DeclContext. A type that is not yet completed can be
+/// considered "complete enough" if it is a class/struct/union/enum
+/// that is currently being defined. Or, if we have a type that names
+/// a class template specialization that is not a complete type, we
+/// will attempt to instantiate that class template.
+bool Sema::RequireCompleteDeclContext(const CXXScopeSpec &SS) {
+  if (!SS.isSet() || SS.isInvalid())
+    return false;
+
+  DeclContext *DC = computeDeclContext(SS, true);
+  if (TagDecl *Tag = dyn_cast<TagDecl>(DC)) {
+    // If this is a dependent type, then we consider it complete.
+    if (Tag->isDependentContext())
+      return false;
+
+    // If we're currently defining this type, then lookup into the
+    // type is okay: don't complain that it isn't complete yet.
+    const TagType *TagT = Context.getTypeDeclType(Tag)->getAs<TagType>();
+    if (TagT->isBeingDefined())
+      return false;
+
+    // The type must be complete.
+    return RequireCompleteType(SS.getRange().getBegin(),
+                               Context.getTypeDeclType(Tag),
+                               PDiag(diag::err_incomplete_nested_name_spec)
+                                 << SS.getRange());
+  }
+
+  return false;
+}
+
+/// ActOnCXXGlobalScopeSpecifier - Return the object that represents the
+/// global scope ('::').
+Sema::CXXScopeTy *Sema::ActOnCXXGlobalScopeSpecifier(Scope *S,
+                                                     SourceLocation CCLoc) {
+  return NestedNameSpecifier::GlobalSpecifier(Context);
+}
+
+/// \brief Determines whether the given declaration is an valid acceptable
+/// result for name lookup of a nested-name-specifier.
+bool Sema::isAcceptableNestedNameSpecifier(NamedDecl *SD) {
+  if (!SD)
+    return false;
+
+  // Namespace and namespace aliases are fine.
+  if (isa<NamespaceDecl>(SD) || isa<NamespaceAliasDecl>(SD))
+    return true;
+
+  if (!isa<TypeDecl>(SD))
+    return false;
+
+  // Determine whether we have a class (or, in C++0x, an enum) or
+  // a typedef thereof. If so, build the nested-name-specifier.
+  QualType T = Context.getTypeDeclType(cast<TypeDecl>(SD));
+  if (T->isDependentType())
+    return true;
+  else if (TypedefDecl *TD = dyn_cast<TypedefDecl>(SD)) {
+    if (TD->getUnderlyingType()->isRecordType() ||
+        (Context.getLangOptions().CPlusPlus0x &&
+         TD->getUnderlyingType()->isEnumeralType()))
+      return true;
+  } else if (isa<RecordDecl>(SD) ||
+             (Context.getLangOptions().CPlusPlus0x && isa<EnumDecl>(SD)))
+    return true;
+
+  return false;
+}
+
+/// \brief If the given nested-name-specifier begins with a bare identifier
+/// (e.g., Base::), perform name lookup for that identifier as a
+/// nested-name-specifier within the given scope, and return the result of that
+/// name lookup.
+NamedDecl *Sema::FindFirstQualifierInScope(Scope *S, NestedNameSpecifier *NNS) {
+  if (!S || !NNS)
+    return 0;
+
+  while (NNS->getPrefix())
+    NNS = NNS->getPrefix();
+
+  if (NNS->getKind() != NestedNameSpecifier::Identifier)
+    return 0;
+
+  LookupResult Found(*this, NNS->getAsIdentifier(), SourceLocation(),
+                     LookupNestedNameSpecifierName);
+  LookupName(Found, S);
+  assert(!Found.isAmbiguous() && "Cannot handle ambiguities here yet");
+
+  if (!Found.isSingleResult())
+    return 0;
+
+  NamedDecl *Result = Found.getFoundDecl();
+  if (isAcceptableNestedNameSpecifier(Result))
+    return Result;
+
+  return 0;
+}
+
+/// \brief Build a new nested-name-specifier for "identifier::", as described
+/// by ActOnCXXNestedNameSpecifier.
+///
+/// This routine differs only slightly from ActOnCXXNestedNameSpecifier, in
+/// that it contains an extra parameter \p ScopeLookupResult, which provides
+/// the result of name lookup within the scope of the nested-name-specifier
+/// that was computed at template definition time.
+///
+/// If ErrorRecoveryLookup is true, then this call is used to improve error
+/// recovery.  This means that it should not emit diagnostics, it should
+/// just return null on failure.  It also means it should only return a valid
+/// scope if it *knows* that the result is correct.  It should not return in a
+/// dependent context, for example.
+Sema::CXXScopeTy *Sema::BuildCXXNestedNameSpecifier(Scope *S,
+                                                    const CXXScopeSpec &SS,
+                                                    SourceLocation IdLoc,
+                                                    SourceLocation CCLoc,
+                                                    IdentifierInfo &II,
+                                                    QualType ObjectType,
+                                                  NamedDecl *ScopeLookupResult,
+                                                    bool EnteringContext,
+                                                    bool ErrorRecoveryLookup) {
+  NestedNameSpecifier *Prefix
+    = static_cast<NestedNameSpecifier *>(SS.getScopeRep());
+
+  LookupResult Found(*this, &II, IdLoc, LookupNestedNameSpecifierName);
+
+  // Determine where to perform name lookup
+  DeclContext *LookupCtx = 0;
+  bool isDependent = false;
+  if (!ObjectType.isNull()) {
+    // This nested-name-specifier occurs in a member access expression, e.g.,
+    // x->B::f, and we are looking into the type of the object.
+    assert(!SS.isSet() && "ObjectType and scope specifier cannot coexist");
+    LookupCtx = computeDeclContext(ObjectType);
+    isDependent = ObjectType->isDependentType();
+  } else if (SS.isSet()) {
+    // This nested-name-specifier occurs after another nested-name-specifier,
+    // so long into the context associated with the prior nested-name-specifier.
+    LookupCtx = computeDeclContext(SS, EnteringContext);
+    isDependent = isDependentScopeSpecifier(SS);
+    Found.setContextRange(SS.getRange());
+  }
+
+
+  bool ObjectTypeSearchedInScope = false;
+  if (LookupCtx) {
+    // Perform "qualified" name lookup into the declaration context we
+    // computed, which is either the type of the base of a member access
+    // expression or the declaration context associated with a prior
+    // nested-name-specifier.
+
+    // The declaration context must be complete.
+    if (!LookupCtx->isDependentContext() && RequireCompleteDeclContext(SS))
+      return 0;
+
+    LookupQualifiedName(Found, LookupCtx);
+
+    if (!ObjectType.isNull() && Found.empty()) {
+      // C++ [basic.lookup.classref]p4:
+      //   If the id-expression in a class member access is a qualified-id of
+      //   the form
+      //
+      //        class-name-or-namespace-name::...
+      //
+      //   the class-name-or-namespace-name following the . or -> operator is
+      //   looked up both in the context of the entire postfix-expression and in
+      //   the scope of the class of the object expression. If the name is found
+      //   only in the scope of the class of the object expression, the name
+      //   shall refer to a class-name. If the name is found only in the
+      //   context of the entire postfix-expression, the name shall refer to a
+      //   class-name or namespace-name. [...]
+      //
+      // Qualified name lookup into a class will not find a namespace-name,
+      // so we do not need to diagnoste that case specifically. However,
+      // this qualified name lookup may find nothing. In that case, perform
+      // unqualified name lookup in the given scope (if available) or
+      // reconstruct the result from when name lookup was performed at template
+      // definition time.
+      if (S)
+        LookupName(Found, S);
+      else if (ScopeLookupResult)
+        Found.addDecl(ScopeLookupResult);
+
+      ObjectTypeSearchedInScope = true;
+    }
+  } else if (isDependent) {
+    // Don't speculate if we're just trying to improve error recovery.
+    if (ErrorRecoveryLookup)
+      return 0;
+    
+    // We were not able to compute the declaration context for a dependent
+    // base object type or prior nested-name-specifier, so this
+    // nested-name-specifier refers to an unknown specialization. Just build
+    // a dependent nested-name-specifier.
+    if (!Prefix)
+      return NestedNameSpecifier::Create(Context, &II);
+
+    return NestedNameSpecifier::Create(Context, Prefix, &II);
+  } else {
+    // Perform unqualified name lookup in the current scope.
+    LookupName(Found, S);
+  }
+
+  // FIXME: Deal with ambiguities cleanly.
+
+  if (Found.empty() && !ErrorRecoveryLookup) {
+    // We haven't found anything, and we're not recovering from a
+    // different kind of error, so look for typos.
+    DeclarationName Name = Found.getLookupName();
+    if (CorrectTypo(Found, S, &SS, LookupCtx, EnteringContext) &&
+        Found.isSingleResult() &&
+        isAcceptableNestedNameSpecifier(Found.getAsSingle<NamedDecl>())) {
+      if (LookupCtx)
+        Diag(Found.getNameLoc(), diag::err_no_member_suggest)
+          << Name << LookupCtx << Found.getLookupName() << SS.getRange()
+          << CodeModificationHint::CreateReplacement(Found.getNameLoc(),
+                                           Found.getLookupName().getAsString());
+      else
+        Diag(Found.getNameLoc(), diag::err_undeclared_var_use_suggest)
+          << Name << Found.getLookupName()
+          << CodeModificationHint::CreateReplacement(Found.getNameLoc(),
+                                           Found.getLookupName().getAsString());
+      
+      if (NamedDecl *ND = Found.getAsSingle<NamedDecl>())
+        Diag(ND->getLocation(), diag::note_previous_decl)
+          << ND->getDeclName();
+    } else
+      Found.clear();
+  }
+
+  NamedDecl *SD = Found.getAsSingle<NamedDecl>();
+  if (isAcceptableNestedNameSpecifier(SD)) {
+    if (!ObjectType.isNull() && !ObjectTypeSearchedInScope) {
+      // C++ [basic.lookup.classref]p4:
+      //   [...] If the name is found in both contexts, the
+      //   class-name-or-namespace-name shall refer to the same entity.
+      //
+      // We already found the name in the scope of the object. Now, look
+      // into the current scope (the scope of the postfix-expression) to
+      // see if we can find the same name there. As above, if there is no
+      // scope, reconstruct the result from the template instantiation itself.
+      NamedDecl *OuterDecl;
+      if (S) {
+        LookupResult FoundOuter(*this, &II, IdLoc, LookupNestedNameSpecifierName);
+        LookupName(FoundOuter, S);
+        OuterDecl = FoundOuter.getAsSingle<NamedDecl>();
+      } else
+        OuterDecl = ScopeLookupResult;
+
+      if (isAcceptableNestedNameSpecifier(OuterDecl) &&
+          OuterDecl->getCanonicalDecl() != SD->getCanonicalDecl() &&
+          (!isa<TypeDecl>(OuterDecl) || !isa<TypeDecl>(SD) ||
+           !Context.hasSameType(
+                            Context.getTypeDeclType(cast<TypeDecl>(OuterDecl)),
+                               Context.getTypeDeclType(cast<TypeDecl>(SD))))) {
+             if (ErrorRecoveryLookup)
+               return 0;
+             
+             Diag(IdLoc, diag::err_nested_name_member_ref_lookup_ambiguous)
+               << &II;
+             Diag(SD->getLocation(), diag::note_ambig_member_ref_object_type)
+               << ObjectType;
+             Diag(OuterDecl->getLocation(), diag::note_ambig_member_ref_scope);
+
+             // Fall through so that we'll pick the name we found in the object
+             // type, since that's probably what the user wanted anyway.
+           }
+    }
+
+    if (NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(SD))
+      return NestedNameSpecifier::Create(Context, Prefix, Namespace);
+
+    // FIXME: It would be nice to maintain the namespace alias name, then
+    // see through that alias when resolving the nested-name-specifier down to
+    // a declaration context.
+    if (NamespaceAliasDecl *Alias = dyn_cast<NamespaceAliasDecl>(SD))
+      return NestedNameSpecifier::Create(Context, Prefix,
+
+                                         Alias->getNamespace());
+
+    QualType T = Context.getTypeDeclType(cast<TypeDecl>(SD));
+    return NestedNameSpecifier::Create(Context, Prefix, false,
+                                       T.getTypePtr());
+  }
+
+  // Otherwise, we have an error case.  If we don't want diagnostics, just
+  // return an error now.
+  if (ErrorRecoveryLookup)
+    return 0;
+
+  // If we didn't find anything during our lookup, try again with
+  // ordinary name lookup, which can help us produce better error
+  // messages.
+  if (Found.empty()) {
+    Found.clear(LookupOrdinaryName);
+    LookupName(Found, S);
+  }
+
+  unsigned DiagID;
+  if (!Found.empty())
+    DiagID = diag::err_expected_class_or_namespace;
+  else if (SS.isSet()) {
+    Diag(IdLoc, diag::err_no_member) << &II << LookupCtx << SS.getRange();
+    return 0;
+  } else
+    DiagID = diag::err_undeclared_var_use;
+
+  if (SS.isSet())
+    Diag(IdLoc, DiagID) << &II << SS.getRange();
+  else
+    Diag(IdLoc, DiagID) << &II;
+
+  return 0;
+}
+
+/// ActOnCXXNestedNameSpecifier - Called during parsing of a
+/// nested-name-specifier. e.g. for "foo::bar::" we parsed "foo::" and now
+/// we want to resolve "bar::". 'SS' is empty or the previously parsed
+/// nested-name part ("foo::"), 'IdLoc' is the source location of 'bar',
+/// 'CCLoc' is the location of '::' and 'II' is the identifier for 'bar'.
+/// Returns a CXXScopeTy* object representing the C++ scope.
+Sema::CXXScopeTy *Sema::ActOnCXXNestedNameSpecifier(Scope *S,
+                                                    const CXXScopeSpec &SS,
+                                                    SourceLocation IdLoc,
+                                                    SourceLocation CCLoc,
+                                                    IdentifierInfo &II,
+                                                    TypeTy *ObjectTypePtr,
+                                                    bool EnteringContext) {
+  return BuildCXXNestedNameSpecifier(S, SS, IdLoc, CCLoc, II,
+                                     QualType::getFromOpaquePtr(ObjectTypePtr),
+                                     /*ScopeLookupResult=*/0, EnteringContext,
+                                     false);
+}
+
+/// IsInvalidUnlessNestedName - This method is used for error recovery
+/// purposes to determine whether the specified identifier is only valid as
+/// a nested name specifier, for example a namespace name.  It is
+/// conservatively correct to always return false from this method.
+///
+/// The arguments are the same as those passed to ActOnCXXNestedNameSpecifier.
+bool Sema::IsInvalidUnlessNestedName(Scope *S, const CXXScopeSpec &SS,
+                                     IdentifierInfo &II, TypeTy *ObjectType,
+                                     bool EnteringContext) {
+  return BuildCXXNestedNameSpecifier(S, SS, SourceLocation(), SourceLocation(),
+                                     II, QualType::getFromOpaquePtr(ObjectType),
+                                     /*ScopeLookupResult=*/0, EnteringContext,
+                                     true);
+}
+
+Sema::CXXScopeTy *Sema::ActOnCXXNestedNameSpecifier(Scope *S,
+                                                    const CXXScopeSpec &SS,
+                                                    TypeTy *Ty,
+                                                    SourceRange TypeRange,
+                                                    SourceLocation CCLoc) {
+  NestedNameSpecifier *Prefix
+    = static_cast<NestedNameSpecifier *>(SS.getScopeRep());
+  QualType T = GetTypeFromParser(Ty);
+  return NestedNameSpecifier::Create(Context, Prefix, /*FIXME:*/false,
+                                     T.getTypePtr());
+}
+
+bool Sema::ShouldEnterDeclaratorScope(Scope *S, const CXXScopeSpec &SS) {
+  assert(SS.isSet() && "Parser passed invalid CXXScopeSpec.");
+
+  NestedNameSpecifier *Qualifier =
+    static_cast<NestedNameSpecifier*>(SS.getScopeRep());
+
+  // There are only two places a well-formed program may qualify a
+  // declarator: first, when defining a namespace or class member
+  // out-of-line, and second, when naming an explicitly-qualified
+  // friend function.  The latter case is governed by
+  // C++03 [basic.lookup.unqual]p10:
+  //   In a friend declaration naming a member function, a name used
+  //   in the function declarator and not part of a template-argument
+  //   in a template-id is first looked up in the scope of the member
+  //   function's class. If it is not found, or if the name is part of
+  //   a template-argument in a template-id, the look up is as
+  //   described for unqualified names in the definition of the class
+  //   granting friendship.
+  // i.e. we don't push a scope unless it's a class member.
+
+  switch (Qualifier->getKind()) {
+  case NestedNameSpecifier::Global:
+  case NestedNameSpecifier::Namespace:
+    // These are always namespace scopes.  We never want to enter a
+    // namespace scope from anything but a file context.
+    return CurContext->getLookupContext()->isFileContext();
+
+  case NestedNameSpecifier::Identifier:
+  case NestedNameSpecifier::TypeSpec:
+  case NestedNameSpecifier::TypeSpecWithTemplate:
+    // These are never namespace scopes.
+    return true;
+  }
+
+  // Silence bogus warning.
+  return false;
+}
+
+/// ActOnCXXEnterDeclaratorScope - Called when a C++ scope specifier (global
+/// scope or nested-name-specifier) is parsed, part of a declarator-id.
+/// After this method is called, according to [C++ 3.4.3p3], names should be
+/// looked up in the declarator-id's scope, until the declarator is parsed and
+/// ActOnCXXExitDeclaratorScope is called.
+/// The 'SS' should be a non-empty valid CXXScopeSpec.
+bool Sema::ActOnCXXEnterDeclaratorScope(Scope *S, const CXXScopeSpec &SS) {
+  assert(SS.isSet() && "Parser passed invalid CXXScopeSpec.");
+
+  if (SS.isInvalid()) return true;
+
+  DeclContext *DC = computeDeclContext(SS, true);
+  if (!DC) return true;
+
+  // Before we enter a declarator's context, we need to make sure that
+  // it is a complete declaration context.
+  if (!DC->isDependentContext() && RequireCompleteDeclContext(SS))
+    return true;
+    
+  EnterDeclaratorContext(S, DC);
+  return false;
+}
+
+/// ActOnCXXExitDeclaratorScope - Called when a declarator that previously
+/// invoked ActOnCXXEnterDeclaratorScope(), is finished. 'SS' is the same
+/// CXXScopeSpec that was passed to ActOnCXXEnterDeclaratorScope as well.
+/// Used to indicate that names should revert to being looked up in the
+/// defining scope.
+void Sema::ActOnCXXExitDeclaratorScope(Scope *S, const CXXScopeSpec &SS) {
+  assert(SS.isSet() && "Parser passed invalid CXXScopeSpec.");
+  if (SS.isInvalid())
+    return;
+  assert(!SS.isInvalid() && computeDeclContext(SS, true) &&
+         "exiting declarator scope we never really entered");
+  ExitDeclaratorContext(S);
+}
diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp
new file mode 100644
index 0000000..8451023
--- /dev/null
+++ b/lib/Sema/SemaChecking.cpp
@@ -0,0 +1,2650 @@
+//===--- SemaChecking.cpp - Extra Semantic Checking -----------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+//  This file implements extra semantic analysis beyond what is enforced
+//  by the C type system.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Sema.h"
+#include "clang/Analysis/CFG.h"
+#include "clang/Analysis/AnalysisContext.h"
+#include "clang/Analysis/Analyses/PrintfFormatString.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/CharUnits.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/AST/ExprCXX.h"
+#include "clang/AST/ExprObjC.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/AST/StmtCXX.h"
+#include "clang/AST/StmtObjC.h"
+#include "clang/Lex/LiteralSupport.h"
+#include "clang/Lex/Preprocessor.h"
+#include "llvm/ADT/BitVector.h"
+#include "llvm/ADT/STLExtras.h"
+#include <limits>
+#include <queue>
+using namespace clang;
+
+/// getLocationOfStringLiteralByte - Return a source location that points to the
+/// specified byte of the specified string literal.
+///
+/// Strings are amazingly complex.  They can be formed from multiple tokens and
+/// can have escape sequences in them in addition to the usual trigraph and
+/// escaped newline business.  This routine handles this complexity.
+///
+SourceLocation Sema::getLocationOfStringLiteralByte(const StringLiteral *SL,
+                                                    unsigned ByteNo) const {
+  assert(!SL->isWide() && "This doesn't work for wide strings yet");
+
+  // Loop over all of the tokens in this string until we find the one that
+  // contains the byte we're looking for.
+  unsigned TokNo = 0;
+  while (1) {
+    assert(TokNo < SL->getNumConcatenated() && "Invalid byte number!");
+    SourceLocation StrTokLoc = SL->getStrTokenLoc(TokNo);
+
+    // Get the spelling of the string so that we can get the data that makes up
+    // the string literal, not the identifier for the macro it is potentially
+    // expanded through.
+    SourceLocation StrTokSpellingLoc = SourceMgr.getSpellingLoc(StrTokLoc);
+
+    // Re-lex the token to get its length and original spelling.
+    std::pair<FileID, unsigned> LocInfo =
+      SourceMgr.getDecomposedLoc(StrTokSpellingLoc);
+    std::pair<const char *,const char *> Buffer =
+      SourceMgr.getBufferData(LocInfo.first);
+    const char *StrData = Buffer.first+LocInfo.second;
+
+    // Create a langops struct and enable trigraphs.  This is sufficient for
+    // relexing tokens.
+    LangOptions LangOpts;
+    LangOpts.Trigraphs = true;
+
+    // Create a lexer starting at the beginning of this token.
+    Lexer TheLexer(StrTokSpellingLoc, LangOpts, Buffer.first, StrData,
+                   Buffer.second);
+    Token TheTok;
+    TheLexer.LexFromRawLexer(TheTok);
+
+    // Use the StringLiteralParser to compute the length of the string in bytes.
+    StringLiteralParser SLP(&TheTok, 1, PP);
+    unsigned TokNumBytes = SLP.GetStringLength();
+
+    // If the byte is in this token, return the location of the byte.
+    if (ByteNo < TokNumBytes ||
+        (ByteNo == TokNumBytes && TokNo == SL->getNumConcatenated())) {
+      unsigned Offset =
+        StringLiteralParser::getOffsetOfStringByte(TheTok, ByteNo, PP);
+
+      // Now that we know the offset of the token in the spelling, use the
+      // preprocessor to get the offset in the original source.
+      return PP.AdvanceToTokenCharacter(StrTokLoc, Offset);
+    }
+
+    // Move to the next string token.
+    ++TokNo;
+    ByteNo -= TokNumBytes;
+  }
+}
+
+/// CheckablePrintfAttr - does a function call have a "printf" attribute
+/// and arguments that merit checking?
+bool Sema::CheckablePrintfAttr(const FormatAttr *Format, CallExpr *TheCall) {
+  if (Format->getType() == "printf") return true;
+  if (Format->getType() == "printf0") {
+    // printf0 allows null "format" string; if so don't check format/args
+    unsigned format_idx = Format->getFormatIdx() - 1;
+    // Does the index refer to the implicit object argument?
+    if (isa<CXXMemberCallExpr>(TheCall)) {
+      if (format_idx == 0)
+        return false;
+      --format_idx;
+    }
+    if (format_idx < TheCall->getNumArgs()) {
+      Expr *Format = TheCall->getArg(format_idx)->IgnoreParenCasts();
+      if (!Format->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull))
+        return true;
+    }
+  }
+  return false;
+}
+
+Action::OwningExprResult
+Sema::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
+  OwningExprResult TheCallResult(Owned(TheCall));
+
+  switch (BuiltinID) {
+  case Builtin::BI__builtin___CFStringMakeConstantString:
+    assert(TheCall->getNumArgs() == 1 &&
+           "Wrong # arguments to builtin CFStringMakeConstantString");
+    if (CheckObjCString(TheCall->getArg(0)))
+      return ExprError();
+    break;
+  case Builtin::BI__builtin_stdarg_start:
+  case Builtin::BI__builtin_va_start:
+    if (SemaBuiltinVAStart(TheCall))
+      return ExprError();
+    break;
+  case Builtin::BI__builtin_isgreater:
+  case Builtin::BI__builtin_isgreaterequal:
+  case Builtin::BI__builtin_isless:
+  case Builtin::BI__builtin_islessequal:
+  case Builtin::BI__builtin_islessgreater:
+  case Builtin::BI__builtin_isunordered:
+    if (SemaBuiltinUnorderedCompare(TheCall))
+      return ExprError();
+    break;
+  case Builtin::BI__builtin_isfinite:
+  case Builtin::BI__builtin_isinf:
+  case Builtin::BI__builtin_isinf_sign:
+  case Builtin::BI__builtin_isnan:
+  case Builtin::BI__builtin_isnormal:
+    if (SemaBuiltinUnaryFP(TheCall))
+      return ExprError();
+    break;
+  case Builtin::BI__builtin_return_address:
+  case Builtin::BI__builtin_frame_address:
+    if (SemaBuiltinStackAddress(TheCall))
+      return ExprError();
+    break;
+  case Builtin::BI__builtin_eh_return_data_regno:
+    if (SemaBuiltinEHReturnDataRegNo(TheCall))
+      return ExprError();
+    break;
+  case Builtin::BI__builtin_shufflevector:
+    return SemaBuiltinShuffleVector(TheCall);
+    // TheCall will be freed by the smart pointer here, but that's fine, since
+    // SemaBuiltinShuffleVector guts it, but then doesn't release it.
+  case Builtin::BI__builtin_prefetch:
+    if (SemaBuiltinPrefetch(TheCall))
+      return ExprError();
+    break;
+  case Builtin::BI__builtin_object_size:
+    if (SemaBuiltinObjectSize(TheCall))
+      return ExprError();
+    break;
+  case Builtin::BI__builtin_longjmp:
+    if (SemaBuiltinLongjmp(TheCall))
+      return ExprError();
+    break;
+  case Builtin::BI__sync_fetch_and_add:
+  case Builtin::BI__sync_fetch_and_sub:
+  case Builtin::BI__sync_fetch_and_or:
+  case Builtin::BI__sync_fetch_and_and:
+  case Builtin::BI__sync_fetch_and_xor:
+  case Builtin::BI__sync_fetch_and_nand:
+  case Builtin::BI__sync_add_and_fetch:
+  case Builtin::BI__sync_sub_and_fetch:
+  case Builtin::BI__sync_and_and_fetch:
+  case Builtin::BI__sync_or_and_fetch:
+  case Builtin::BI__sync_xor_and_fetch:
+  case Builtin::BI__sync_nand_and_fetch:
+  case Builtin::BI__sync_val_compare_and_swap:
+  case Builtin::BI__sync_bool_compare_and_swap:
+  case Builtin::BI__sync_lock_test_and_set:
+  case Builtin::BI__sync_lock_release:
+    if (SemaBuiltinAtomicOverloaded(TheCall))
+      return ExprError();
+    break;
+  }
+
+  return move(TheCallResult);
+}
+
+/// CheckFunctionCall - Check a direct function call for various correctness
+/// and safety properties not strictly enforced by the C type system.
+bool Sema::CheckFunctionCall(FunctionDecl *FDecl, CallExpr *TheCall) {
+  // Get the IdentifierInfo* for the called function.
+  IdentifierInfo *FnInfo = FDecl->getIdentifier();
+
+  // None of the checks below are needed for functions that don't have
+  // simple names (e.g., C++ conversion functions).
+  if (!FnInfo)
+    return false;
+
+  // FIXME: This mechanism should be abstracted to be less fragile and
+  // more efficient. For example, just map function ids to custom
+  // handlers.
+
+  // Printf checking.
+  if (const FormatAttr *Format = FDecl->getAttr<FormatAttr>()) {
+    if (CheckablePrintfAttr(Format, TheCall)) {
+      bool HasVAListArg = Format->getFirstArg() == 0;
+      if (!HasVAListArg) {
+        if (const FunctionProtoType *Proto
+            = FDecl->getType()->getAs<FunctionProtoType>())
+          HasVAListArg = !Proto->isVariadic();
+      }
+      CheckPrintfArguments(TheCall, HasVAListArg, Format->getFormatIdx() - 1,
+                           HasVAListArg ? 0 : Format->getFirstArg() - 1);
+    }
+  }
+
+  for (const NonNullAttr *NonNull = FDecl->getAttr<NonNullAttr>(); NonNull;
+       NonNull = NonNull->getNext<NonNullAttr>())
+    CheckNonNullArguments(NonNull, TheCall);
+
+  return false;
+}
+
+bool Sema::CheckBlockCall(NamedDecl *NDecl, CallExpr *TheCall) {
+  // Printf checking.
+  const FormatAttr *Format = NDecl->getAttr<FormatAttr>();
+  if (!Format)
+    return false;
+
+  const VarDecl *V = dyn_cast<VarDecl>(NDecl);
+  if (!V)
+    return false;
+
+  QualType Ty = V->getType();
+  if (!Ty->isBlockPointerType())
+    return false;
+
+  if (!CheckablePrintfAttr(Format, TheCall))
+    return false;
+
+  bool HasVAListArg = Format->getFirstArg() == 0;
+  if (!HasVAListArg) {
+    const FunctionType *FT =
+      Ty->getAs<BlockPointerType>()->getPointeeType()->getAs<FunctionType>();
+    if (const FunctionProtoType *Proto = dyn_cast<FunctionProtoType>(FT))
+      HasVAListArg = !Proto->isVariadic();
+  }
+  CheckPrintfArguments(TheCall, HasVAListArg, Format->getFormatIdx() - 1,
+                       HasVAListArg ? 0 : Format->getFirstArg() - 1);
+
+  return false;
+}
+
+/// SemaBuiltinAtomicOverloaded - We have a call to a function like
+/// __sync_fetch_and_add, which is an overloaded function based on the pointer
+/// type of its first argument.  The main ActOnCallExpr routines have already
+/// promoted the types of arguments because all of these calls are prototyped as
+/// void(...).
+///
+/// This function goes through and does final semantic checking for these
+/// builtins,
+bool Sema::SemaBuiltinAtomicOverloaded(CallExpr *TheCall) {
+  DeclRefExpr *DRE =cast<DeclRefExpr>(TheCall->getCallee()->IgnoreParenCasts());
+  FunctionDecl *FDecl = cast<FunctionDecl>(DRE->getDecl());
+
+  // Ensure that we have at least one argument to do type inference from.
+  if (TheCall->getNumArgs() < 1)
+    return Diag(TheCall->getLocEnd(), diag::err_typecheck_call_too_few_args)
+              << 0 << TheCall->getCallee()->getSourceRange();
+
+  // Inspect the first argument of the atomic builtin.  This should always be
+  // a pointer type, whose element is an integral scalar or pointer type.
+  // Because it is a pointer type, we don't have to worry about any implicit
+  // casts here.
+  Expr *FirstArg = TheCall->getArg(0);
+  if (!FirstArg->getType()->isPointerType())
+    return Diag(DRE->getLocStart(), diag::err_atomic_builtin_must_be_pointer)
+             << FirstArg->getType() << FirstArg->getSourceRange();
+
+  QualType ValType = FirstArg->getType()->getAs<PointerType>()->getPointeeType();
+  if (!ValType->isIntegerType() && !ValType->isPointerType() &&
+      !ValType->isBlockPointerType())
+    return Diag(DRE->getLocStart(),
+                diag::err_atomic_builtin_must_be_pointer_intptr)
+             << FirstArg->getType() << FirstArg->getSourceRange();
+
+  // We need to figure out which concrete builtin this maps onto.  For example,
+  // __sync_fetch_and_add with a 2 byte object turns into
+  // __sync_fetch_and_add_2.
+#define BUILTIN_ROW(x) \
+  { Builtin::BI##x##_1, Builtin::BI##x##_2, Builtin::BI##x##_4, \
+    Builtin::BI##x##_8, Builtin::BI##x##_16 }
+
+  static const unsigned BuiltinIndices[][5] = {
+    BUILTIN_ROW(__sync_fetch_and_add),
+    BUILTIN_ROW(__sync_fetch_and_sub),
+    BUILTIN_ROW(__sync_fetch_and_or),
+    BUILTIN_ROW(__sync_fetch_and_and),
+    BUILTIN_ROW(__sync_fetch_and_xor),
+    BUILTIN_ROW(__sync_fetch_and_nand),
+
+    BUILTIN_ROW(__sync_add_and_fetch),
+    BUILTIN_ROW(__sync_sub_and_fetch),
+    BUILTIN_ROW(__sync_and_and_fetch),
+    BUILTIN_ROW(__sync_or_and_fetch),
+    BUILTIN_ROW(__sync_xor_and_fetch),
+    BUILTIN_ROW(__sync_nand_and_fetch),
+
+    BUILTIN_ROW(__sync_val_compare_and_swap),
+    BUILTIN_ROW(__sync_bool_compare_and_swap),
+    BUILTIN_ROW(__sync_lock_test_and_set),
+    BUILTIN_ROW(__sync_lock_release)
+  };
+#undef BUILTIN_ROW
+
+  // Determine the index of the size.
+  unsigned SizeIndex;
+  switch (Context.getTypeSizeInChars(ValType).getQuantity()) {
+  case 1: SizeIndex = 0; break;
+  case 2: SizeIndex = 1; break;
+  case 4: SizeIndex = 2; break;
+  case 8: SizeIndex = 3; break;
+  case 16: SizeIndex = 4; break;
+  default:
+    return Diag(DRE->getLocStart(), diag::err_atomic_builtin_pointer_size)
+             << FirstArg->getType() << FirstArg->getSourceRange();
+  }
+
+  // Each of these builtins has one pointer argument, followed by some number of
+  // values (0, 1 or 2) followed by a potentially empty varags list of stuff
+  // that we ignore.  Find out which row of BuiltinIndices to read from as well
+  // as the number of fixed args.
+  unsigned BuiltinID = FDecl->getBuiltinID();
+  unsigned BuiltinIndex, NumFixed = 1;
+  switch (BuiltinID) {
+  default: assert(0 && "Unknown overloaded atomic builtin!");
+  case Builtin::BI__sync_fetch_and_add: BuiltinIndex = 0; break;
+  case Builtin::BI__sync_fetch_and_sub: BuiltinIndex = 1; break;
+  case Builtin::BI__sync_fetch_and_or:  BuiltinIndex = 2; break;
+  case Builtin::BI__sync_fetch_and_and: BuiltinIndex = 3; break;
+  case Builtin::BI__sync_fetch_and_xor: BuiltinIndex = 4; break;
+  case Builtin::BI__sync_fetch_and_nand:BuiltinIndex = 5; break;
+
+  case Builtin::BI__sync_add_and_fetch: BuiltinIndex = 6; break;
+  case Builtin::BI__sync_sub_and_fetch: BuiltinIndex = 7; break;
+  case Builtin::BI__sync_and_and_fetch: BuiltinIndex = 8; break;
+  case Builtin::BI__sync_or_and_fetch:  BuiltinIndex = 9; break;
+  case Builtin::BI__sync_xor_and_fetch: BuiltinIndex =10; break;
+  case Builtin::BI__sync_nand_and_fetch:BuiltinIndex =11; break;
+
+  case Builtin::BI__sync_val_compare_and_swap:
+    BuiltinIndex = 12;
+    NumFixed = 2;
+    break;
+  case Builtin::BI__sync_bool_compare_and_swap:
+    BuiltinIndex = 13;
+    NumFixed = 2;
+    break;
+  case Builtin::BI__sync_lock_test_and_set: BuiltinIndex = 14; break;
+  case Builtin::BI__sync_lock_release:
+    BuiltinIndex = 15;
+    NumFixed = 0;
+    break;
+  }
+
+  // Now that we know how many fixed arguments we expect, first check that we
+  // have at least that many.
+  if (TheCall->getNumArgs() < 1+NumFixed)
+    return Diag(TheCall->getLocEnd(), diag::err_typecheck_call_too_few_args)
+            << 0 << TheCall->getCallee()->getSourceRange();
+
+
+  // Get the decl for the concrete builtin from this, we can tell what the
+  // concrete integer type we should convert to is.
+  unsigned NewBuiltinID = BuiltinIndices[BuiltinIndex][SizeIndex];
+  const char *NewBuiltinName = Context.BuiltinInfo.GetName(NewBuiltinID);
+  IdentifierInfo *NewBuiltinII = PP.getIdentifierInfo(NewBuiltinName);
+  FunctionDecl *NewBuiltinDecl =
+    cast<FunctionDecl>(LazilyCreateBuiltin(NewBuiltinII, NewBuiltinID,
+                                           TUScope, false, DRE->getLocStart()));
+  const FunctionProtoType *BuiltinFT =
+    NewBuiltinDecl->getType()->getAs<FunctionProtoType>();
+  ValType = BuiltinFT->getArgType(0)->getAs<PointerType>()->getPointeeType();
+
+  // If the first type needs to be converted (e.g. void** -> int*), do it now.
+  if (BuiltinFT->getArgType(0) != FirstArg->getType()) {
+    ImpCastExprToType(FirstArg, BuiltinFT->getArgType(0), CastExpr::CK_BitCast);
+    TheCall->setArg(0, FirstArg);
+  }
+
+  // Next, walk the valid ones promoting to the right type.
+  for (unsigned i = 0; i != NumFixed; ++i) {
+    Expr *Arg = TheCall->getArg(i+1);
+
+    // If the argument is an implicit cast, then there was a promotion due to
+    // "...", just remove it now.
+    if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(Arg)) {
+      Arg = ICE->getSubExpr();
+      ICE->setSubExpr(0);
+      ICE->Destroy(Context);
+      TheCall->setArg(i+1, Arg);
+    }
+
+    // GCC does an implicit conversion to the pointer or integer ValType.  This
+    // can fail in some cases (1i -> int**), check for this error case now.
+    CastExpr::CastKind Kind = CastExpr::CK_Unknown;
+    CXXMethodDecl *ConversionDecl = 0;
+    if (CheckCastTypes(Arg->getSourceRange(), ValType, Arg, Kind,
+                       ConversionDecl))
+      return true;
+
+    // Okay, we have something that *can* be converted to the right type.  Check
+    // to see if there is a potentially weird extension going on here.  This can
+    // happen when you do an atomic operation on something like an char* and
+    // pass in 42.  The 42 gets converted to char.  This is even more strange
+    // for things like 45.123 -> char, etc.
+    // FIXME: Do this check.
+    ImpCastExprToType(Arg, ValType, Kind, /*isLvalue=*/false);
+    TheCall->setArg(i+1, Arg);
+  }
+
+  // Switch the DeclRefExpr to refer to the new decl.
+  DRE->setDecl(NewBuiltinDecl);
+  DRE->setType(NewBuiltinDecl->getType());
+
+  // Set the callee in the CallExpr.
+  // FIXME: This leaks the original parens and implicit casts.
+  Expr *PromotedCall = DRE;
+  UsualUnaryConversions(PromotedCall);
+  TheCall->setCallee(PromotedCall);
+
+
+  // Change the result type of the call to match the result type of the decl.
+  TheCall->setType(NewBuiltinDecl->getResultType());
+  return false;
+}
+
+
+/// CheckObjCString - Checks that the argument to the builtin
+/// CFString constructor is correct
+/// FIXME: GCC currently emits the following warning:
+/// "warning: input conversion stopped due to an input byte that does not
+///           belong to the input codeset UTF-8"
+/// Note: It might also make sense to do the UTF-16 conversion here (would
+/// simplify the backend).
+bool Sema::CheckObjCString(Expr *Arg) {
+  Arg = Arg->IgnoreParenCasts();
+  StringLiteral *Literal = dyn_cast<StringLiteral>(Arg);
+
+  if (!Literal || Literal->isWide()) {
+    Diag(Arg->getLocStart(), diag::err_cfstring_literal_not_string_constant)
+      << Arg->getSourceRange();
+    return true;
+  }
+
+  const char *Data = Literal->getStrData();
+  unsigned Length = Literal->getByteLength();
+
+  for (unsigned i = 0; i < Length; ++i) {
+    if (!Data[i]) {
+      Diag(getLocationOfStringLiteralByte(Literal, i),
+           diag::warn_cfstring_literal_contains_nul_character)
+        << Arg->getSourceRange();
+      break;
+    }
+  }
+
+  return false;
+}
+
+/// SemaBuiltinVAStart - Check the arguments to __builtin_va_start for validity.
+/// Emit an error and return true on failure, return false on success.
+bool Sema::SemaBuiltinVAStart(CallExpr *TheCall) {
+  Expr *Fn = TheCall->getCallee();
+  if (TheCall->getNumArgs() > 2) {
+    Diag(TheCall->getArg(2)->getLocStart(),
+         diag::err_typecheck_call_too_many_args)
+      << 0 /*function call*/ << Fn->getSourceRange()
+      << SourceRange(TheCall->getArg(2)->getLocStart(),
+                     (*(TheCall->arg_end()-1))->getLocEnd());
+    return true;
+  }
+
+  if (TheCall->getNumArgs() < 2) {
+    return Diag(TheCall->getLocEnd(), diag::err_typecheck_call_too_few_args)
+      << 0 /*function call*/;
+  }
+
+  // Determine whether the current function is variadic or not.
+  bool isVariadic;
+  if (CurBlock)
+    isVariadic = CurBlock->isVariadic;
+  else if (getCurFunctionDecl()) {
+    if (FunctionProtoType* FTP =
+            dyn_cast<FunctionProtoType>(getCurFunctionDecl()->getType()))
+      isVariadic = FTP->isVariadic();
+    else
+      isVariadic = false;
+  } else {
+    isVariadic = getCurMethodDecl()->isVariadic();
+  }
+
+  if (!isVariadic) {
+    Diag(Fn->getLocStart(), diag::err_va_start_used_in_non_variadic_function);
+    return true;
+  }
+
+  // Verify that the second argument to the builtin is the last argument of the
+  // current function or method.
+  bool SecondArgIsLastNamedArgument = false;
+  const Expr *Arg = TheCall->getArg(1)->IgnoreParenCasts();
+
+  if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(Arg)) {
+    if (const ParmVarDecl *PV = dyn_cast<ParmVarDecl>(DR->getDecl())) {
+      // FIXME: This isn't correct for methods (results in bogus warning).
+      // Get the last formal in the current function.
+      const ParmVarDecl *LastArg;
+      if (CurBlock)
+        LastArg = *(CurBlock->TheDecl->param_end()-1);
+      else if (FunctionDecl *FD = getCurFunctionDecl())
+        LastArg = *(FD->param_end()-1);
+      else
+        LastArg = *(getCurMethodDecl()->param_end()-1);
+      SecondArgIsLastNamedArgument = PV == LastArg;
+    }
+  }
+
+  if (!SecondArgIsLastNamedArgument)
+    Diag(TheCall->getArg(1)->getLocStart(),
+         diag::warn_second_parameter_of_va_start_not_last_named_argument);
+  return false;
+}
+
+/// SemaBuiltinUnorderedCompare - Handle functions like __builtin_isgreater and
+/// friends.  This is declared to take (...), so we have to check everything.
+bool Sema::SemaBuiltinUnorderedCompare(CallExpr *TheCall) {
+  if (TheCall->getNumArgs() < 2)
+    return Diag(TheCall->getLocEnd(), diag::err_typecheck_call_too_few_args)
+      << 0 /*function call*/;
+  if (TheCall->getNumArgs() > 2)
+    return Diag(TheCall->getArg(2)->getLocStart(),
+                diag::err_typecheck_call_too_many_args)
+      << 0 /*function call*/
+      << SourceRange(TheCall->getArg(2)->getLocStart(),
+                     (*(TheCall->arg_end()-1))->getLocEnd());
+
+  Expr *OrigArg0 = TheCall->getArg(0);
+  Expr *OrigArg1 = TheCall->getArg(1);
+
+  // Do standard promotions between the two arguments, returning their common
+  // type.
+  QualType Res = UsualArithmeticConversions(OrigArg0, OrigArg1, false);
+
+  // Make sure any conversions are pushed back into the call; this is
+  // type safe since unordered compare builtins are declared as "_Bool
+  // foo(...)".
+  TheCall->setArg(0, OrigArg0);
+  TheCall->setArg(1, OrigArg1);
+
+  if (OrigArg0->isTypeDependent() || OrigArg1->isTypeDependent())
+    return false;
+
+  // If the common type isn't a real floating type, then the arguments were
+  // invalid for this operation.
+  if (!Res->isRealFloatingType())
+    return Diag(OrigArg0->getLocStart(),
+                diag::err_typecheck_call_invalid_ordered_compare)
+      << OrigArg0->getType() << OrigArg1->getType()
+      << SourceRange(OrigArg0->getLocStart(), OrigArg1->getLocEnd());
+
+  return false;
+}
+
+/// SemaBuiltinUnorderedCompare - Handle functions like __builtin_isnan and
+/// friends.  This is declared to take (...), so we have to check everything.
+bool Sema::SemaBuiltinUnaryFP(CallExpr *TheCall) {
+  if (TheCall->getNumArgs() < 1)
+    return Diag(TheCall->getLocEnd(), diag::err_typecheck_call_too_few_args)
+      << 0 /*function call*/;
+  if (TheCall->getNumArgs() > 1)
+    return Diag(TheCall->getArg(1)->getLocStart(),
+                diag::err_typecheck_call_too_many_args)
+      << 0 /*function call*/
+      << SourceRange(TheCall->getArg(1)->getLocStart(),
+                     (*(TheCall->arg_end()-1))->getLocEnd());
+
+  Expr *OrigArg = TheCall->getArg(0);
+
+  if (OrigArg->isTypeDependent())
+    return false;
+
+  // This operation requires a floating-point number
+  if (!OrigArg->getType()->isRealFloatingType())
+    return Diag(OrigArg->getLocStart(),
+                diag::err_typecheck_call_invalid_unary_fp)
+      << OrigArg->getType() << OrigArg->getSourceRange();
+
+  return false;
+}
+
+bool Sema::SemaBuiltinStackAddress(CallExpr *TheCall) {
+  // The signature for these builtins is exact; the only thing we need
+  // to check is that the argument is a constant.
+  SourceLocation Loc;
+  if (!TheCall->getArg(0)->isTypeDependent() &&
+      !TheCall->getArg(0)->isValueDependent() &&
+      !TheCall->getArg(0)->isIntegerConstantExpr(Context, &Loc))
+    return Diag(Loc, diag::err_stack_const_level) << TheCall->getSourceRange();
+
+  return false;
+}
+
+/// SemaBuiltinShuffleVector - Handle __builtin_shufflevector.
+// This is declared to take (...), so we have to check everything.
+Action::OwningExprResult Sema::SemaBuiltinShuffleVector(CallExpr *TheCall) {
+  if (TheCall->getNumArgs() < 3)
+    return ExprError(Diag(TheCall->getLocEnd(),
+                          diag::err_typecheck_call_too_few_args)
+      << 0 /*function call*/ << TheCall->getSourceRange());
+
+  unsigned numElements = std::numeric_limits<unsigned>::max();
+  if (!TheCall->getArg(0)->isTypeDependent() &&
+      !TheCall->getArg(1)->isTypeDependent()) {
+    QualType FAType = TheCall->getArg(0)->getType();
+    QualType SAType = TheCall->getArg(1)->getType();
+
+    if (!FAType->isVectorType() || !SAType->isVectorType()) {
+      Diag(TheCall->getLocStart(), diag::err_shufflevector_non_vector)
+        << SourceRange(TheCall->getArg(0)->getLocStart(),
+                       TheCall->getArg(1)->getLocEnd());
+      return ExprError();
+    }
+
+    if (!Context.hasSameUnqualifiedType(FAType, SAType)) {
+      Diag(TheCall->getLocStart(), diag::err_shufflevector_incompatible_vector)
+        << SourceRange(TheCall->getArg(0)->getLocStart(),
+                       TheCall->getArg(1)->getLocEnd());
+      return ExprError();
+    }
+
+    numElements = FAType->getAs<VectorType>()->getNumElements();
+    if (TheCall->getNumArgs() != numElements+2) {
+      if (TheCall->getNumArgs() < numElements+2)
+        return ExprError(Diag(TheCall->getLocEnd(),
+                              diag::err_typecheck_call_too_few_args)
+                 << 0 /*function call*/ << TheCall->getSourceRange());
+      return ExprError(Diag(TheCall->getLocEnd(),
+                            diag::err_typecheck_call_too_many_args)
+                 << 0 /*function call*/ << TheCall->getSourceRange());
+    }
+  }
+
+  for (unsigned i = 2; i < TheCall->getNumArgs(); i++) {
+    if (TheCall->getArg(i)->isTypeDependent() ||
+        TheCall->getArg(i)->isValueDependent())
+      continue;
+
+    llvm::APSInt Result(32);
+    if (!TheCall->getArg(i)->isIntegerConstantExpr(Result, Context))
+      return ExprError(Diag(TheCall->getLocStart(),
+                  diag::err_shufflevector_nonconstant_argument)
+                << TheCall->getArg(i)->getSourceRange());
+
+    if (Result.getActiveBits() > 64 || Result.getZExtValue() >= numElements*2)
+      return ExprError(Diag(TheCall->getLocStart(),
+                  diag::err_shufflevector_argument_too_large)
+               << TheCall->getArg(i)->getSourceRange());
+  }
+
+  llvm::SmallVector<Expr*, 32> exprs;
+
+  for (unsigned i = 0, e = TheCall->getNumArgs(); i != e; i++) {
+    exprs.push_back(TheCall->getArg(i));
+    TheCall->setArg(i, 0);
+  }
+
+  return Owned(new (Context) ShuffleVectorExpr(Context, exprs.begin(),
+                                            exprs.size(), exprs[0]->getType(),
+                                            TheCall->getCallee()->getLocStart(),
+                                            TheCall->getRParenLoc()));
+}
+
+/// SemaBuiltinPrefetch - Handle __builtin_prefetch.
+// This is declared to take (const void*, ...) and can take two
+// optional constant int args.
+bool Sema::SemaBuiltinPrefetch(CallExpr *TheCall) {
+  unsigned NumArgs = TheCall->getNumArgs();
+
+  if (NumArgs > 3)
+    return Diag(TheCall->getLocEnd(), diag::err_typecheck_call_too_many_args)
+             << 0 /*function call*/ << TheCall->getSourceRange();
+
+  // Argument 0 is checked for us and the remaining arguments must be
+  // constant integers.
+  for (unsigned i = 1; i != NumArgs; ++i) {
+    Expr *Arg = TheCall->getArg(i);
+    if (Arg->isTypeDependent())
+      continue;
+
+    if (!Arg->getType()->isIntegralType())
+      return Diag(TheCall->getLocStart(), diag::err_prefetch_invalid_arg_type)
+              << Arg->getSourceRange();
+
+    ImpCastExprToType(Arg, Context.IntTy, CastExpr::CK_IntegralCast);
+    TheCall->setArg(i, Arg);
+
+    if (Arg->isValueDependent())
+      continue;
+
+    llvm::APSInt Result;
+    if (!Arg->isIntegerConstantExpr(Result, Context))
+      return Diag(TheCall->getLocStart(), diag::err_prefetch_invalid_arg_ice)
+        << SourceRange(Arg->getLocStart(), Arg->getLocEnd());
+
+    // FIXME: gcc issues a warning and rewrites these to 0. These
+    // seems especially odd for the third argument since the default
+    // is 3.
+    if (i == 1) {
+      if (Result.getLimitedValue() > 1)
+        return Diag(TheCall->getLocStart(), diag::err_argument_invalid_range)
+             << "0" << "1" << Arg->getSourceRange();
+    } else {
+      if (Result.getLimitedValue() > 3)
+        return Diag(TheCall->getLocStart(), diag::err_argument_invalid_range)
+            << "0" << "3" << Arg->getSourceRange();
+    }
+  }
+
+  return false;
+}
+
+/// SemaBuiltinEHReturnDataRegNo - Handle __builtin_eh_return_data_regno, the
+/// operand must be an integer constant.
+bool Sema::SemaBuiltinEHReturnDataRegNo(CallExpr *TheCall) {
+  llvm::APSInt Result;
+  if (!TheCall->getArg(0)->isIntegerConstantExpr(Result, Context))
+    return Diag(TheCall->getLocStart(), diag::err_expr_not_ice)
+      << TheCall->getArg(0)->getSourceRange();
+  
+  return false;
+}
+
+
+/// SemaBuiltinObjectSize - Handle __builtin_object_size(void *ptr,
+/// int type). This simply type checks that type is one of the defined
+/// constants (0-3).
+// For compatability check 0-3, llvm only handles 0 and 2.
+bool Sema::SemaBuiltinObjectSize(CallExpr *TheCall) {
+  Expr *Arg = TheCall->getArg(1);
+  if (Arg->isTypeDependent())
+    return false;
+
+  QualType ArgType = Arg->getType();
+  const BuiltinType *BT = ArgType->getAs<BuiltinType>();
+  llvm::APSInt Result(32);
+  if (!BT || BT->getKind() != BuiltinType::Int)
+    return Diag(TheCall->getLocStart(), diag::err_object_size_invalid_argument)
+             << SourceRange(Arg->getLocStart(), Arg->getLocEnd());
+
+  if (Arg->isValueDependent())
+    return false;
+
+  if (!Arg->isIntegerConstantExpr(Result, Context)) {
+    return Diag(TheCall->getLocStart(), diag::err_object_size_invalid_argument)
+             << SourceRange(Arg->getLocStart(), Arg->getLocEnd());
+  }
+
+  if (Result.getSExtValue() < 0 || Result.getSExtValue() > 3) {
+    return Diag(TheCall->getLocStart(), diag::err_argument_invalid_range)
+             << "0" << "3" << SourceRange(Arg->getLocStart(), Arg->getLocEnd());
+  }
+
+  return false;
+}
+
+/// SemaBuiltinLongjmp - Handle __builtin_longjmp(void *env[5], int val).
+/// This checks that val is a constant 1.
+bool Sema::SemaBuiltinLongjmp(CallExpr *TheCall) {
+  Expr *Arg = TheCall->getArg(1);
+  if (Arg->isTypeDependent() || Arg->isValueDependent())
+    return false;
+
+  llvm::APSInt Result(32);
+  if (!Arg->isIntegerConstantExpr(Result, Context) || Result != 1)
+    return Diag(TheCall->getLocStart(), diag::err_builtin_longjmp_invalid_val)
+             << SourceRange(Arg->getLocStart(), Arg->getLocEnd());
+
+  return false;
+}
+
+// Handle i > 1 ? "x" : "y", recursivelly
+bool Sema::SemaCheckStringLiteral(const Expr *E, const CallExpr *TheCall,
+                                  bool HasVAListArg,
+                                  unsigned format_idx, unsigned firstDataArg) {
+  if (E->isTypeDependent() || E->isValueDependent())
+    return false;
+
+  switch (E->getStmtClass()) {
+  case Stmt::ConditionalOperatorClass: {
+    const ConditionalOperator *C = cast<ConditionalOperator>(E);
+    return SemaCheckStringLiteral(C->getTrueExpr(), TheCall,
+                                  HasVAListArg, format_idx, firstDataArg)
+        && SemaCheckStringLiteral(C->getRHS(), TheCall,
+                                  HasVAListArg, format_idx, firstDataArg);
+  }
+
+  case Stmt::ImplicitCastExprClass: {
+    const ImplicitCastExpr *Expr = cast<ImplicitCastExpr>(E);
+    return SemaCheckStringLiteral(Expr->getSubExpr(), TheCall, HasVAListArg,
+                                  format_idx, firstDataArg);
+  }
+
+  case Stmt::ParenExprClass: {
+    const ParenExpr *Expr = cast<ParenExpr>(E);
+    return SemaCheckStringLiteral(Expr->getSubExpr(), TheCall, HasVAListArg,
+                                  format_idx, firstDataArg);
+  }
+
+  case Stmt::DeclRefExprClass: {
+    const DeclRefExpr *DR = cast<DeclRefExpr>(E);
+
+    // As an exception, do not flag errors for variables binding to
+    // const string literals.
+    if (const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl())) {
+      bool isConstant = false;
+      QualType T = DR->getType();
+
+      if (const ArrayType *AT = Context.getAsArrayType(T)) {
+        isConstant = AT->getElementType().isConstant(Context);
+      } else if (const PointerType *PT = T->getAs<PointerType>()) {
+        isConstant = T.isConstant(Context) &&
+                     PT->getPointeeType().isConstant(Context);
+      }
+
+      if (isConstant) {
+        if (const Expr *Init = VD->getAnyInitializer())
+          return SemaCheckStringLiteral(Init, TheCall,
+                                        HasVAListArg, format_idx, firstDataArg);
+      }
+
+      // For vprintf* functions (i.e., HasVAListArg==true), we add a
+      // special check to see if the format string is a function parameter
+      // of the function calling the printf function.  If the function
+      // has an attribute indicating it is a printf-like function, then we
+      // should suppress warnings concerning non-literals being used in a call
+      // to a vprintf function.  For example:
+      //
+      // void
+      // logmessage(char const *fmt __attribute__ (format (printf, 1, 2)), ...){
+      //      va_list ap;
+      //      va_start(ap, fmt);
+      //      vprintf(fmt, ap);  // Do NOT emit a warning about "fmt".
+      //      ...
+      //
+      //
+      //  FIXME: We don't have full attribute support yet, so just check to see
+      //    if the argument is a DeclRefExpr that references a parameter.  We'll
+      //    add proper support for checking the attribute later.
+      if (HasVAListArg)
+        if (isa<ParmVarDecl>(VD))
+          return true;
+    }
+
+    return false;
+  }
+
+  case Stmt::CallExprClass: {
+    const CallExpr *CE = cast<CallExpr>(E);
+    if (const ImplicitCastExpr *ICE
+          = dyn_cast<ImplicitCastExpr>(CE->getCallee())) {
+      if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(ICE->getSubExpr())) {
+        if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(DRE->getDecl())) {
+          if (const FormatArgAttr *FA = FD->getAttr<FormatArgAttr>()) {
+            unsigned ArgIndex = FA->getFormatIdx();
+            const Expr *Arg = CE->getArg(ArgIndex - 1);
+
+            return SemaCheckStringLiteral(Arg, TheCall, HasVAListArg,
+                                          format_idx, firstDataArg);
+          }
+        }
+      }
+    }
+
+    return false;
+  }
+  case Stmt::ObjCStringLiteralClass:
+  case Stmt::StringLiteralClass: {
+    const StringLiteral *StrE = NULL;
+
+    if (const ObjCStringLiteral *ObjCFExpr = dyn_cast<ObjCStringLiteral>(E))
+      StrE = ObjCFExpr->getString();
+    else
+      StrE = cast<StringLiteral>(E);
+
+    if (StrE) {
+      CheckPrintfString(StrE, E, TheCall, HasVAListArg, format_idx,
+                        firstDataArg);
+      return true;
+    }
+
+    return false;
+  }
+
+  default:
+    return false;
+  }
+}
+
+void
+Sema::CheckNonNullArguments(const NonNullAttr *NonNull,
+                            const CallExpr *TheCall) {
+  for (NonNullAttr::iterator i = NonNull->begin(), e = NonNull->end();
+       i != e; ++i) {
+    const Expr *ArgExpr = TheCall->getArg(*i);
+    if (ArgExpr->isNullPointerConstant(Context, 
+                                       Expr::NPC_ValueDependentIsNotNull))
+      Diag(TheCall->getCallee()->getLocStart(), diag::warn_null_arg)
+        << ArgExpr->getSourceRange();
+  }
+}
+
+/// CheckPrintfArguments - Check calls to printf (and similar functions) for
+/// correct use of format strings.
+///
+///  HasVAListArg - A predicate indicating whether the printf-like
+///    function is passed an explicit va_arg argument (e.g., vprintf)
+///
+///  format_idx - The index into Args for the format string.
+///
+/// Improper format strings to functions in the printf family can be
+/// the source of bizarre bugs and very serious security holes.  A
+/// good source of information is available in the following paper
+/// (which includes additional references):
+///
+///  FormatGuard: Automatic Protection From printf Format String
+///  Vulnerabilities, Proceedings of the 10th USENIX Security Symposium, 2001.
+///
+/// Functionality implemented:
+///
+///  We can statically check the following properties for string
+///  literal format strings for non v.*printf functions (where the
+///  arguments are passed directly):
+//
+///  (1) Are the number of format conversions equal to the number of
+///      data arguments?
+///
+///  (2) Does each format conversion correctly match the type of the
+///      corresponding data argument?  (TODO)
+///
+/// Moreover, for all printf functions we can:
+///
+///  (3) Check for a missing format string (when not caught by type checking).
+///
+///  (4) Check for no-operation flags; e.g. using "#" with format
+///      conversion 'c'  (TODO)
+///
+///  (5) Check the use of '%n', a major source of security holes.
+///
+///  (6) Check for malformed format conversions that don't specify anything.
+///
+///  (7) Check for empty format strings.  e.g: printf("");
+///
+///  (8) Check that the format string is a wide literal.
+///
+/// All of these checks can be done by parsing the format string.
+///
+/// For now, we ONLY do (1), (3), (5), (6), (7), and (8).
+void
+Sema::CheckPrintfArguments(const CallExpr *TheCall, bool HasVAListArg,
+                           unsigned format_idx, unsigned firstDataArg) {
+  const Expr *Fn = TheCall->getCallee();
+
+  // The way the format attribute works in GCC, the implicit this argument
+  // of member functions is counted. However, it doesn't appear in our own
+  // lists, so decrement format_idx in that case.
+  if (isa<CXXMemberCallExpr>(TheCall)) {
+    // Catch a format attribute mistakenly referring to the object argument.
+    if (format_idx == 0)
+      return;
+    --format_idx;
+    if(firstDataArg != 0)
+      --firstDataArg;
+  }
+
+  // CHECK: printf-like function is called with no format string.
+  if (format_idx >= TheCall->getNumArgs()) {
+    Diag(TheCall->getRParenLoc(), diag::warn_printf_missing_format_string)
+      << Fn->getSourceRange();
+    return;
+  }
+
+  const Expr *OrigFormatExpr = TheCall->getArg(format_idx)->IgnoreParenCasts();
+
+  // CHECK: format string is not a string literal.
+  //
+  // Dynamically generated format strings are difficult to
+  // automatically vet at compile time.  Requiring that format strings
+  // are string literals: (1) permits the checking of format strings by
+  // the compiler and thereby (2) can practically remove the source of
+  // many format string exploits.
+
+  // Format string can be either ObjC string (e.g. @"%d") or
+  // C string (e.g. "%d")
+  // ObjC string uses the same format specifiers as C string, so we can use
+  // the same format string checking logic for both ObjC and C strings.
+  if (SemaCheckStringLiteral(OrigFormatExpr, TheCall, HasVAListArg, format_idx,
+                             firstDataArg))
+    return;  // Literal format string found, check done!
+
+  // If there are no arguments specified, warn with -Wformat-security, otherwise
+  // warn only with -Wformat-nonliteral.
+  if (TheCall->getNumArgs() == format_idx+1)
+    Diag(TheCall->getArg(format_idx)->getLocStart(),
+         diag::warn_printf_nonliteral_noargs)
+      << OrigFormatExpr->getSourceRange();
+  else
+    Diag(TheCall->getArg(format_idx)->getLocStart(),
+         diag::warn_printf_nonliteral)
+           << OrigFormatExpr->getSourceRange();
+}
+
+namespace {
+class CheckPrintfHandler : public analyze_printf::FormatStringHandler {
+  Sema &S;
+  const StringLiteral *FExpr;
+  const Expr *OrigFormatExpr;
+  unsigned NumConversions;
+  const unsigned NumDataArgs;
+  const bool IsObjCLiteral;
+  const char *Beg; // Start of format string.
+  const bool HasVAListArg;
+  const CallExpr *TheCall;
+  unsigned FormatIdx;
+public:  
+  CheckPrintfHandler(Sema &s, const StringLiteral *fexpr,
+                     const Expr *origFormatExpr,
+                     unsigned numDataArgs, bool isObjCLiteral,
+                     const char *beg, bool hasVAListArg,
+                     const CallExpr *theCall, unsigned formatIdx)
+    : S(s), FExpr(fexpr), OrigFormatExpr(origFormatExpr),
+      NumConversions(0), NumDataArgs(numDataArgs),
+      IsObjCLiteral(isObjCLiteral), Beg(beg),
+      HasVAListArg(hasVAListArg),
+      TheCall(theCall), FormatIdx(formatIdx) {}
+  
+  void DoneProcessing();
+     
+  void HandleIncompleteFormatSpecifier(const char *startSpecifier,
+                                       unsigned specifierLen);
+  
+  void
+  HandleInvalidConversionSpecifier(const analyze_printf::FormatSpecifier &FS,
+                                   const char *startSpecifier,
+                                   unsigned specifierLen);
+  
+  void HandleNullChar(const char *nullCharacter);
+  
+  bool HandleFormatSpecifier(const analyze_printf::FormatSpecifier &FS,
+                             const char *startSpecifier,
+                             unsigned specifierLen);
+private:
+  SourceRange getFormatStringRange();
+  SourceRange getFormatSpecifierRange(const char *startSpecifier,
+                                      unsigned specifierLen);
+  SourceLocation getLocationOfByte(const char *x);
+  
+  bool HandleAmount(const analyze_printf::OptionalAmount &Amt,
+                    unsigned MissingArgDiag, unsigned BadTypeDiag,
+          const char *startSpecifier, unsigned specifierLen);
+  
+  bool MatchType(QualType A, QualType B, bool ignoreSign);
+  
+  const Expr *getDataArg(unsigned i) const;
+};
+}
+
+SourceRange CheckPrintfHandler::getFormatStringRange() {
+  return OrigFormatExpr->getSourceRange();
+}
+
+SourceRange CheckPrintfHandler::
+getFormatSpecifierRange(const char *startSpecifier, unsigned specifierLen) {
+  return SourceRange(getLocationOfByte(startSpecifier),
+                     getLocationOfByte(startSpecifier+specifierLen-1));
+}
+
+SourceLocation CheckPrintfHandler::getLocationOfByte(const char *x) {
+  return S.getLocationOfStringLiteralByte(FExpr, x - Beg);  
+}
+
+void CheckPrintfHandler::
+HandleIncompleteFormatSpecifier(const char *startSpecifier,
+                                unsigned specifierLen) {  
+  SourceLocation Loc = getLocationOfByte(startSpecifier);
+  S.Diag(Loc, diag::warn_printf_incomplete_specifier)
+    << getFormatSpecifierRange(startSpecifier, specifierLen);
+}
+
+void CheckPrintfHandler::
+HandleInvalidConversionSpecifier(const analyze_printf::FormatSpecifier &FS,
+                                 const char *startSpecifier,
+                                 unsigned specifierLen) {
+  
+  ++NumConversions;
+  const analyze_printf::ConversionSpecifier &CS =
+    FS.getConversionSpecifier();  
+  SourceLocation Loc = getLocationOfByte(CS.getStart());
+  S.Diag(Loc, diag::warn_printf_invalid_conversion)
+      << llvm::StringRef(CS.getStart(), CS.getLength())
+      << getFormatSpecifierRange(startSpecifier, specifierLen);  
+}
+
+void CheckPrintfHandler::HandleNullChar(const char *nullCharacter) {
+  // The presence of a null character is likely an error.
+  S.Diag(getLocationOfByte(nullCharacter),
+         diag::warn_printf_format_string_contains_null_char)
+    << getFormatStringRange();
+}
+
+const Expr *CheckPrintfHandler::getDataArg(unsigned i) const {
+  return TheCall->getArg(FormatIdx + i);  
+}
+
+bool CheckPrintfHandler::MatchType(QualType A, QualType B, bool ignoreSign) {
+  A = S.Context.getCanonicalType(A).getUnqualifiedType();
+  B = S.Context.getCanonicalType(B).getUnqualifiedType();
+  
+  if (A == B)
+    return true;
+  
+  if (ignoreSign) {
+    if (const BuiltinType *BT = B->getAs<BuiltinType>()) {
+      switch (BT->getKind()) {
+        default:
+          return false;
+        case BuiltinType::Char_S:          
+        case BuiltinType::SChar:
+          return A == S.Context.UnsignedCharTy;
+        case BuiltinType::Char_U:
+        case BuiltinType::UChar:
+          return A == S.Context.SignedCharTy;
+        case BuiltinType::Short:
+          return A == S.Context.UnsignedShortTy;
+        case BuiltinType::UShort:
+          return A == S.Context.ShortTy;          
+        case BuiltinType::Int:
+          return A == S.Context.UnsignedIntTy;
+        case BuiltinType::UInt:
+          return A == S.Context.IntTy;
+        case BuiltinType::Long:
+          return A == S.Context.UnsignedLongTy;
+        case BuiltinType::ULong:
+          return A == S.Context.LongTy;
+        case BuiltinType::LongLong:
+          return A == S.Context.UnsignedLongLongTy;
+        case BuiltinType::ULongLong:
+          return A == S.Context.LongLongTy;          
+      }
+      return A == B;
+    }
+  }
+  return false;  
+}
+
+bool
+CheckPrintfHandler::HandleAmount(const analyze_printf::OptionalAmount &Amt,
+                                 unsigned MissingArgDiag,
+                                 unsigned BadTypeDiag,
+                                 const char *startSpecifier,
+                                 unsigned specifierLen) {
+
+  if (Amt.hasDataArgument()) {
+    ++NumConversions;
+    if (!HasVAListArg) {
+      if (NumConversions > NumDataArgs) {
+        S.Diag(getLocationOfByte(Amt.getStart()), MissingArgDiag)
+          << getFormatSpecifierRange(startSpecifier, specifierLen);      
+        // Don't do any more checking.  We will just emit
+        // spurious errors.
+        return false;
+      }
+      
+      // Type check the data argument.  It should be an 'int'.
+      // Although not in conformance with C99, we also allow the argument to be
+      // an 'unsigned int' as that is a reasonably safe case.  GCC also
+      // doesn't emit a warning for that case.
+      const Expr *Arg = getDataArg(NumConversions);
+      QualType T = Arg->getType();
+      if (!MatchType(T, S.Context.IntTy, true)) {
+        S.Diag(getLocationOfByte(Amt.getStart()), BadTypeDiag)
+          << S.Context.IntTy << T
+          << getFormatSpecifierRange(startSpecifier, specifierLen)
+          << Arg->getSourceRange();
+        // Don't do any more checking.  We will just emit
+        // spurious errors.
+        return false;
+      }
+    }
+  }
+  return true;
+}
+
+bool
+CheckPrintfHandler::HandleFormatSpecifier(const analyze_printf::FormatSpecifier &FS,
+                                          const char *startSpecifier,
+                                          unsigned specifierLen) {
+
+  using namespace analyze_printf;
+  const ConversionSpecifier &CS = FS.getConversionSpecifier();
+
+  // First check if the field width, precision, and conversion specifier
+  // have matching data arguments.
+  if (!HandleAmount(FS.getFieldWidth(),
+                    diag::warn_printf_asterisk_width_missing_arg,
+                    diag::warn_printf_asterisk_width_wrong_type,
+          startSpecifier, specifierLen)) {
+    return false;
+  }
+    
+  if (!HandleAmount(FS.getPrecision(),
+                    diag::warn_printf_asterisk_precision_missing_arg,
+                    diag::warn_printf_asterisk_precision_wrong_type,
+          startSpecifier, specifierLen)) {
+    return false;
+  }
+
+  // Check for using an Objective-C specific conversion specifier
+  // in a non-ObjC literal.
+  if (!IsObjCLiteral && CS.isObjCArg()) {
+    HandleInvalidConversionSpecifier(FS, startSpecifier, specifierLen);
+    
+    // Continue checking the other format specifiers.
+    return true;
+  }
+
+  if (!CS.consumesDataArgument()) {
+    // FIXME: Technically specifying a precision or field width here
+    // makes no sense.  Worth issuing a warning at some point.
+    return true;
+  }
+  
+  ++NumConversions;  
+  
+  // Are we using '%n'?  Issue a warning about this being
+  // a possible security issue.
+  if (CS.getKind() == ConversionSpecifier::OutIntPtrArg) {
+    S.Diag(getLocationOfByte(CS.getStart()), diag::warn_printf_write_back)
+      << getFormatSpecifierRange(startSpecifier, specifierLen);           
+    // Continue checking the other format specifiers.
+    return true;
+  }
+  
+  
+  // The remaining checks depend on the data arguments.
+  if (HasVAListArg)
+    return true;
+  
+  if (NumConversions > NumDataArgs) {
+    S.Diag(getLocationOfByte(CS.getStart()),
+           diag::warn_printf_insufficient_data_args)
+      << getFormatSpecifierRange(startSpecifier, specifierLen);    
+    // Don't do any more checking.
+    return false;
+  }
+  
+  // Now type check the data expression that matches the
+  // format specifier.
+  const Expr *Ex = getDataArg(NumConversions);
+  const analyze_printf::ArgTypeResult &ATR = FS.getArgType(S.Context);
+  
+  if (const QualType *T = ATR.getSpecificType()) {
+    if (!MatchType(*T, Ex->getType(), true)) {
+      // Check if we didn't match because of an implicit cast from a 'char'
+      // or 'short' to an 'int'.  This is done because printf is a varargs
+      // function.
+      if (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(Ex))
+        if (ICE->getType() == S.Context.IntTy)
+          if (MatchType(*T, ICE->getSubExpr()->getType(), true))
+            return true;
+
+      S.Diag(getLocationOfByte(CS.getStart()),
+             diag::warn_printf_conversion_argument_type_mismatch)
+      << *T << Ex->getType();
+//        << getFormatSpecifierRange(startSpecifier, specifierLen)
+//        << Ex->getSourceRange();
+    }
+    return true;
+  }
+
+  return true;
+}
+
+void CheckPrintfHandler::DoneProcessing() {
+  // Does the number of data arguments exceed the number of
+  // format conversions in the format string?
+  if (!HasVAListArg && NumConversions < NumDataArgs)
+    S.Diag(getDataArg(NumConversions+1)->getLocStart(),
+           diag::warn_printf_too_many_data_args)
+      << getFormatStringRange();
+}
+
+void Sema::CheckPrintfString(const StringLiteral *FExpr,
+                             const Expr *OrigFormatExpr,
+                             const CallExpr *TheCall, bool HasVAListArg,
+                             unsigned format_idx, unsigned firstDataArg) {
+
+  // CHECK: is the format string a wide literal?
+  if (FExpr->isWide()) {
+    Diag(FExpr->getLocStart(),
+         diag::warn_printf_format_string_is_wide_literal)
+    << OrigFormatExpr->getSourceRange();
+    return;
+  }
+  
+  // Str - The format string.  NOTE: this is NOT null-terminated!
+  const char *Str = FExpr->getStrData();
+  
+  // CHECK: empty format string?
+  unsigned StrLen = FExpr->getByteLength();
+  
+  if (StrLen == 0) {
+    Diag(FExpr->getLocStart(), diag::warn_printf_empty_format_string)
+    << OrigFormatExpr->getSourceRange();
+    return;
+  }
+  
+  CheckPrintfHandler H(*this, FExpr, OrigFormatExpr,
+                       TheCall->getNumArgs() - firstDataArg,
+                       isa<ObjCStringLiteral>(OrigFormatExpr), Str,
+                       HasVAListArg, TheCall, format_idx);
+
+  if (!analyze_printf::ParseFormatString(H, Str, Str + StrLen))
+    H.DoneProcessing();
+}
+
+//===--- CHECK: Return Address of Stack Variable --------------------------===//
+
+static DeclRefExpr* EvalVal(Expr *E);
+static DeclRefExpr* EvalAddr(Expr* E);
+
+/// CheckReturnStackAddr - Check if a return statement returns the address
+///   of a stack variable.
+void
+Sema::CheckReturnStackAddr(Expr *RetValExp, QualType lhsType,
+                           SourceLocation ReturnLoc) {
+
+  // Perform checking for returned stack addresses.
+  if (lhsType->isPointerType() || lhsType->isBlockPointerType()) {
+    if (DeclRefExpr *DR = EvalAddr(RetValExp))
+      Diag(DR->getLocStart(), diag::warn_ret_stack_addr)
+       << DR->getDecl()->getDeclName() << RetValExp->getSourceRange();
+
+    // Skip over implicit cast expressions when checking for block expressions.
+    RetValExp = RetValExp->IgnoreParenCasts();
+
+    if (BlockExpr *C = dyn_cast<BlockExpr>(RetValExp))
+      if (C->hasBlockDeclRefExprs())
+        Diag(C->getLocStart(), diag::err_ret_local_block)
+          << C->getSourceRange();
+    
+    if (AddrLabelExpr *ALE = dyn_cast<AddrLabelExpr>(RetValExp))
+      Diag(ALE->getLocStart(), diag::warn_ret_addr_label)
+        << ALE->getSourceRange();
+    
+  } else if (lhsType->isReferenceType()) {
+    // Perform checking for stack values returned by reference.
+    // Check for a reference to the stack
+    if (DeclRefExpr *DR = EvalVal(RetValExp))
+      Diag(DR->getLocStart(), diag::warn_ret_stack_ref)
+        << DR->getDecl()->getDeclName() << RetValExp->getSourceRange();
+  }
+}
+
+/// EvalAddr - EvalAddr and EvalVal are mutually recursive functions that
+///  check if the expression in a return statement evaluates to an address
+///  to a location on the stack.  The recursion is used to traverse the
+///  AST of the return expression, with recursion backtracking when we
+///  encounter a subexpression that (1) clearly does not lead to the address
+///  of a stack variable or (2) is something we cannot determine leads to
+///  the address of a stack variable based on such local checking.
+///
+///  EvalAddr processes expressions that are pointers that are used as
+///  references (and not L-values).  EvalVal handles all other values.
+///  At the base case of the recursion is a check for a DeclRefExpr* in
+///  the refers to a stack variable.
+///
+///  This implementation handles:
+///
+///   * pointer-to-pointer casts
+///   * implicit conversions from array references to pointers
+///   * taking the address of fields
+///   * arbitrary interplay between "&" and "*" operators
+///   * pointer arithmetic from an address of a stack variable
+///   * taking the address of an array element where the array is on the stack
+static DeclRefExpr* EvalAddr(Expr *E) {
+  // We should only be called for evaluating pointer expressions.
+  assert((E->getType()->isAnyPointerType() ||
+          E->getType()->isBlockPointerType() ||
+          E->getType()->isObjCQualifiedIdType()) &&
+         "EvalAddr only works on pointers");
+
+  // Our "symbolic interpreter" is just a dispatch off the currently
+  // viewed AST node.  We then recursively traverse the AST by calling
+  // EvalAddr and EvalVal appropriately.
+  switch (E->getStmtClass()) {
+  case Stmt::ParenExprClass:
+    // Ignore parentheses.
+    return EvalAddr(cast<ParenExpr>(E)->getSubExpr());
+
+  case Stmt::UnaryOperatorClass: {
+    // The only unary operator that make sense to handle here
+    // is AddrOf.  All others don't make sense as pointers.
+    UnaryOperator *U = cast<UnaryOperator>(E);
+
+    if (U->getOpcode() == UnaryOperator::AddrOf)
+      return EvalVal(U->getSubExpr());
+    else
+      return NULL;
+  }
+
+  case Stmt::BinaryOperatorClass: {
+    // Handle pointer arithmetic.  All other binary operators are not valid
+    // in this context.
+    BinaryOperator *B = cast<BinaryOperator>(E);
+    BinaryOperator::Opcode op = B->getOpcode();
+
+    if (op != BinaryOperator::Add && op != BinaryOperator::Sub)
+      return NULL;
+
+    Expr *Base = B->getLHS();
+
+    // Determine which argument is the real pointer base.  It could be
+    // the RHS argument instead of the LHS.
+    if (!Base->getType()->isPointerType()) Base = B->getRHS();
+
+    assert (Base->getType()->isPointerType());
+    return EvalAddr(Base);
+  }
+
+  // For conditional operators we need to see if either the LHS or RHS are
+  // valid DeclRefExpr*s.  If one of them is valid, we return it.
+  case Stmt::ConditionalOperatorClass: {
+    ConditionalOperator *C = cast<ConditionalOperator>(E);
+
+    // Handle the GNU extension for missing LHS.
+    if (Expr *lhsExpr = C->getLHS())
+      if (DeclRefExpr* LHS = EvalAddr(lhsExpr))
+        return LHS;
+
+     return EvalAddr(C->getRHS());
+  }
+
+  // For casts, we need to handle conversions from arrays to
+  // pointer values, and pointer-to-pointer conversions.
+  case Stmt::ImplicitCastExprClass:
+  case Stmt::CStyleCastExprClass:
+  case Stmt::CXXFunctionalCastExprClass: {
+    Expr* SubExpr = cast<CastExpr>(E)->getSubExpr();
+    QualType T = SubExpr->getType();
+
+    if (SubExpr->getType()->isPointerType() ||
+        SubExpr->getType()->isBlockPointerType() ||
+        SubExpr->getType()->isObjCQualifiedIdType())
+      return EvalAddr(SubExpr);
+    else if (T->isArrayType())
+      return EvalVal(SubExpr);
+    else
+      return 0;
+  }
+
+  // C++ casts.  For dynamic casts, static casts, and const casts, we
+  // are always converting from a pointer-to-pointer, so we just blow
+  // through the cast.  In the case the dynamic cast doesn't fail (and
+  // return NULL), we take the conservative route and report cases
+  // where we return the address of a stack variable.  For Reinterpre
+  // FIXME: The comment about is wrong; we're not always converting
+  // from pointer to pointer. I'm guessing that this code should also
+  // handle references to objects.
+  case Stmt::CXXStaticCastExprClass:
+  case Stmt::CXXDynamicCastExprClass:
+  case Stmt::CXXConstCastExprClass:
+  case Stmt::CXXReinterpretCastExprClass: {
+      Expr *S = cast<CXXNamedCastExpr>(E)->getSubExpr();
+      if (S->getType()->isPointerType() || S->getType()->isBlockPointerType())
+        return EvalAddr(S);
+      else
+        return NULL;
+  }
+
+  // Everything else: we simply don't reason about them.
+  default:
+    return NULL;
+  }
+}
+
+
+///  EvalVal - This function is complements EvalAddr in the mutual recursion.
+///   See the comments for EvalAddr for more details.
+static DeclRefExpr* EvalVal(Expr *E) {
+
+  // We should only be called for evaluating non-pointer expressions, or
+  // expressions with a pointer type that are not used as references but instead
+  // are l-values (e.g., DeclRefExpr with a pointer type).
+
+  // Our "symbolic interpreter" is just a dispatch off the currently
+  // viewed AST node.  We then recursively traverse the AST by calling
+  // EvalAddr and EvalVal appropriately.
+  switch (E->getStmtClass()) {
+  case Stmt::DeclRefExprClass: {
+    // DeclRefExpr: the base case.  When we hit a DeclRefExpr we are looking
+    //  at code that refers to a variable's name.  We check if it has local
+    //  storage within the function, and if so, return the expression.
+    DeclRefExpr *DR = cast<DeclRefExpr>(E);
+
+    if (VarDecl *V = dyn_cast<VarDecl>(DR->getDecl()))
+      if (V->hasLocalStorage() && !V->getType()->isReferenceType()) return DR;
+
+    return NULL;
+  }
+
+  case Stmt::ParenExprClass:
+    // Ignore parentheses.
+    return EvalVal(cast<ParenExpr>(E)->getSubExpr());
+
+  case Stmt::UnaryOperatorClass: {
+    // The only unary operator that make sense to handle here
+    // is Deref.  All others don't resolve to a "name."  This includes
+    // handling all sorts of rvalues passed to a unary operator.
+    UnaryOperator *U = cast<UnaryOperator>(E);
+
+    if (U->getOpcode() == UnaryOperator::Deref)
+      return EvalAddr(U->getSubExpr());
+
+    return NULL;
+  }
+
+  case Stmt::ArraySubscriptExprClass: {
+    // Array subscripts are potential references to data on the stack.  We
+    // retrieve the DeclRefExpr* for the array variable if it indeed
+    // has local storage.
+    return EvalAddr(cast<ArraySubscriptExpr>(E)->getBase());
+  }
+
+  case Stmt::ConditionalOperatorClass: {
+    // For conditional operators we need to see if either the LHS or RHS are
+    // non-NULL DeclRefExpr's.  If one is non-NULL, we return it.
+    ConditionalOperator *C = cast<ConditionalOperator>(E);
+
+    // Handle the GNU extension for missing LHS.
+    if (Expr *lhsExpr = C->getLHS())
+      if (DeclRefExpr *LHS = EvalVal(lhsExpr))
+        return LHS;
+
+    return EvalVal(C->getRHS());
+  }
+
+  // Accesses to members are potential references to data on the stack.
+  case Stmt::MemberExprClass: {
+    MemberExpr *M = cast<MemberExpr>(E);
+
+    // Check for indirect access.  We only want direct field accesses.
+    if (!M->isArrow())
+      return EvalVal(M->getBase());
+    else
+      return NULL;
+  }
+
+  // Everything else: we simply don't reason about them.
+  default:
+    return NULL;
+  }
+}
+
+//===--- CHECK: Floating-Point comparisons (-Wfloat-equal) ---------------===//
+
+/// Check for comparisons of floating point operands using != and ==.
+/// Issue a warning if these are no self-comparisons, as they are not likely
+/// to do what the programmer intended.
+void Sema::CheckFloatComparison(SourceLocation loc, Expr* lex, Expr *rex) {
+  bool EmitWarning = true;
+
+  Expr* LeftExprSansParen = lex->IgnoreParens();
+  Expr* RightExprSansParen = rex->IgnoreParens();
+
+  // Special case: check for x == x (which is OK).
+  // Do not emit warnings for such cases.
+  if (DeclRefExpr* DRL = dyn_cast<DeclRefExpr>(LeftExprSansParen))
+    if (DeclRefExpr* DRR = dyn_cast<DeclRefExpr>(RightExprSansParen))
+      if (DRL->getDecl() == DRR->getDecl())
+        EmitWarning = false;
+
+
+  // Special case: check for comparisons against literals that can be exactly
+  //  represented by APFloat.  In such cases, do not emit a warning.  This
+  //  is a heuristic: often comparison against such literals are used to
+  //  detect if a value in a variable has not changed.  This clearly can
+  //  lead to false negatives.
+  if (EmitWarning) {
+    if (FloatingLiteral* FLL = dyn_cast<FloatingLiteral>(LeftExprSansParen)) {
+      if (FLL->isExact())
+        EmitWarning = false;
+    } else
+      if (FloatingLiteral* FLR = dyn_cast<FloatingLiteral>(RightExprSansParen)){
+        if (FLR->isExact())
+          EmitWarning = false;
+    }
+  }
+
+  // Check for comparisons with builtin types.
+  if (EmitWarning)
+    if (CallExpr* CL = dyn_cast<CallExpr>(LeftExprSansParen))
+      if (CL->isBuiltinCall(Context))
+        EmitWarning = false;
+
+  if (EmitWarning)
+    if (CallExpr* CR = dyn_cast<CallExpr>(RightExprSansParen))
+      if (CR->isBuiltinCall(Context))
+        EmitWarning = false;
+
+  // Emit the diagnostic.
+  if (EmitWarning)
+    Diag(loc, diag::warn_floatingpoint_eq)
+      << lex->getSourceRange() << rex->getSourceRange();
+}
+
+//===--- CHECK: Integer mixed-sign comparisons (-Wsign-compare) --------===//
+//===--- CHECK: Lossy implicit conversions (-Wconversion) --------------===//
+
+namespace {
+
+/// Structure recording the 'active' range of an integer-valued
+/// expression.
+struct IntRange {
+  /// The number of bits active in the int.
+  unsigned Width;
+
+  /// True if the int is known not to have negative values.
+  bool NonNegative;
+
+  IntRange() {}
+  IntRange(unsigned Width, bool NonNegative)
+    : Width(Width), NonNegative(NonNegative)
+  {}
+
+  // Returns the range of the bool type.
+  static IntRange forBoolType() {
+    return IntRange(1, true);
+  }
+
+  // Returns the range of an integral type.
+  static IntRange forType(ASTContext &C, QualType T) {
+    return forCanonicalType(C, T->getCanonicalTypeInternal().getTypePtr());
+  }
+
+  // Returns the range of an integeral type based on its canonical
+  // representation.
+  static IntRange forCanonicalType(ASTContext &C, const Type *T) {
+    assert(T->isCanonicalUnqualified());
+
+    if (const VectorType *VT = dyn_cast<VectorType>(T))
+      T = VT->getElementType().getTypePtr();
+    if (const ComplexType *CT = dyn_cast<ComplexType>(T))
+      T = CT->getElementType().getTypePtr();
+    if (const EnumType *ET = dyn_cast<EnumType>(T))
+      T = ET->getDecl()->getIntegerType().getTypePtr();
+
+    const BuiltinType *BT = cast<BuiltinType>(T);
+    assert(BT->isInteger());
+
+    return IntRange(C.getIntWidth(QualType(T, 0)), BT->isUnsignedInteger());
+  }
+
+  // Returns the supremum of two ranges: i.e. their conservative merge.
+  static IntRange join(const IntRange &L, const IntRange &R) {
+    return IntRange(std::max(L.Width, R.Width),
+                    L.NonNegative && R.NonNegative);
+  }
+
+  // Returns the infinum of two ranges: i.e. their aggressive merge.
+  static IntRange meet(const IntRange &L, const IntRange &R) {
+    return IntRange(std::min(L.Width, R.Width),
+                    L.NonNegative || R.NonNegative);
+  }
+};
+
+IntRange GetValueRange(ASTContext &C, llvm::APSInt &value, unsigned MaxWidth) {
+  if (value.isSigned() && value.isNegative())
+    return IntRange(value.getMinSignedBits(), false);
+
+  if (value.getBitWidth() > MaxWidth)
+    value.trunc(MaxWidth);
+
+  // isNonNegative() just checks the sign bit without considering
+  // signedness.
+  return IntRange(value.getActiveBits(), true);
+}
+
+IntRange GetValueRange(ASTContext &C, APValue &result, QualType Ty,
+                       unsigned MaxWidth) {
+  if (result.isInt())
+    return GetValueRange(C, result.getInt(), MaxWidth);
+
+  if (result.isVector()) {
+    IntRange R = GetValueRange(C, result.getVectorElt(0), Ty, MaxWidth);
+    for (unsigned i = 1, e = result.getVectorLength(); i != e; ++i) {
+      IntRange El = GetValueRange(C, result.getVectorElt(i), Ty, MaxWidth);
+      R = IntRange::join(R, El);
+    }
+    return R;
+  }
+
+  if (result.isComplexInt()) {
+    IntRange R = GetValueRange(C, result.getComplexIntReal(), MaxWidth);
+    IntRange I = GetValueRange(C, result.getComplexIntImag(), MaxWidth);
+    return IntRange::join(R, I);
+  }
+
+  // This can happen with lossless casts to intptr_t of "based" lvalues.
+  // Assume it might use arbitrary bits.
+  // FIXME: The only reason we need to pass the type in here is to get
+  // the sign right on this one case.  It would be nice if APValue
+  // preserved this.
+  assert(result.isLValue());
+  return IntRange(MaxWidth, Ty->isUnsignedIntegerType());
+}
+
+/// Pseudo-evaluate the given integer expression, estimating the
+/// range of values it might take.
+///
+/// \param MaxWidth - the width to which the value will be truncated
+IntRange GetExprRange(ASTContext &C, Expr *E, unsigned MaxWidth) {
+  E = E->IgnoreParens();
+
+  // Try a full evaluation first.
+  Expr::EvalResult result;
+  if (E->Evaluate(result, C))
+    return GetValueRange(C, result.Val, E->getType(), MaxWidth);
+
+  // I think we only want to look through implicit casts here; if the
+  // user has an explicit widening cast, we should treat the value as
+  // being of the new, wider type.
+  if (ImplicitCastExpr *CE = dyn_cast<ImplicitCastExpr>(E)) {
+    if (CE->getCastKind() == CastExpr::CK_NoOp)
+      return GetExprRange(C, CE->getSubExpr(), MaxWidth);
+
+    IntRange OutputTypeRange = IntRange::forType(C, CE->getType());
+
+    bool isIntegerCast = (CE->getCastKind() == CastExpr::CK_IntegralCast);
+    if (!isIntegerCast && CE->getCastKind() == CastExpr::CK_Unknown)
+      isIntegerCast = CE->getSubExpr()->getType()->isIntegerType();
+
+    // Assume that non-integer casts can span the full range of the type.
+    if (!isIntegerCast)
+      return OutputTypeRange;
+
+    IntRange SubRange
+      = GetExprRange(C, CE->getSubExpr(),
+                     std::min(MaxWidth, OutputTypeRange.Width));
+
+    // Bail out if the subexpr's range is as wide as the cast type.
+    if (SubRange.Width >= OutputTypeRange.Width)
+      return OutputTypeRange;
+
+    // Otherwise, we take the smaller width, and we're non-negative if
+    // either the output type or the subexpr is.
+    return IntRange(SubRange.Width,
+                    SubRange.NonNegative || OutputTypeRange.NonNegative);
+  }
+
+  if (ConditionalOperator *CO = dyn_cast<ConditionalOperator>(E)) {
+    // If we can fold the condition, just take that operand.
+    bool CondResult;
+    if (CO->getCond()->EvaluateAsBooleanCondition(CondResult, C))
+      return GetExprRange(C, CondResult ? CO->getTrueExpr()
+                                        : CO->getFalseExpr(),
+                          MaxWidth);
+
+    // Otherwise, conservatively merge.
+    IntRange L = GetExprRange(C, CO->getTrueExpr(), MaxWidth);
+    IntRange R = GetExprRange(C, CO->getFalseExpr(), MaxWidth);
+    return IntRange::join(L, R);
+  }
+
+  if (BinaryOperator *BO = dyn_cast<BinaryOperator>(E)) {
+    switch (BO->getOpcode()) {
+
+    // Boolean-valued operations are single-bit and positive.
+    case BinaryOperator::LAnd:
+    case BinaryOperator::LOr:
+    case BinaryOperator::LT:
+    case BinaryOperator::GT:
+    case BinaryOperator::LE:
+    case BinaryOperator::GE:
+    case BinaryOperator::EQ:
+    case BinaryOperator::NE:
+      return IntRange::forBoolType();
+
+    // Operations with opaque sources are black-listed.
+    case BinaryOperator::PtrMemD:
+    case BinaryOperator::PtrMemI:
+      return IntRange::forType(C, E->getType());
+
+    // Bitwise-and uses the *infinum* of the two source ranges.
+    case BinaryOperator::And:
+      return IntRange::meet(GetExprRange(C, BO->getLHS(), MaxWidth),
+                            GetExprRange(C, BO->getRHS(), MaxWidth));
+
+    // Left shift gets black-listed based on a judgement call.
+    case BinaryOperator::Shl:
+      return IntRange::forType(C, E->getType());
+
+    // Right shift by a constant can narrow its left argument.
+    case BinaryOperator::Shr: {
+      IntRange L = GetExprRange(C, BO->getLHS(), MaxWidth);
+
+      // If the shift amount is a positive constant, drop the width by
+      // that much.
+      llvm::APSInt shift;
+      if (BO->getRHS()->isIntegerConstantExpr(shift, C) &&
+          shift.isNonNegative()) {
+        unsigned zext = shift.getZExtValue();
+        if (zext >= L.Width)
+          L.Width = (L.NonNegative ? 0 : 1);
+        else
+          L.Width -= zext;
+      }
+
+      return L;
+    }
+
+    // Comma acts as its right operand.
+    case BinaryOperator::Comma:
+      return GetExprRange(C, BO->getRHS(), MaxWidth);
+
+    // Black-list pointer subtractions.
+    case BinaryOperator::Sub:
+      if (BO->getLHS()->getType()->isPointerType())
+        return IntRange::forType(C, E->getType());
+      // fallthrough
+      
+    default:
+      break;
+    }
+
+    // Treat every other operator as if it were closed on the
+    // narrowest type that encompasses both operands.
+    IntRange L = GetExprRange(C, BO->getLHS(), MaxWidth);
+    IntRange R = GetExprRange(C, BO->getRHS(), MaxWidth);
+    return IntRange::join(L, R);
+  }
+
+  if (UnaryOperator *UO = dyn_cast<UnaryOperator>(E)) {
+    switch (UO->getOpcode()) {
+    // Boolean-valued operations are white-listed.
+    case UnaryOperator::LNot:
+      return IntRange::forBoolType();
+
+    // Operations with opaque sources are black-listed.
+    case UnaryOperator::Deref:
+    case UnaryOperator::AddrOf: // should be impossible
+    case UnaryOperator::OffsetOf:
+      return IntRange::forType(C, E->getType());
+
+    default:
+      return GetExprRange(C, UO->getSubExpr(), MaxWidth);
+    }
+  }
+
+  FieldDecl *BitField = E->getBitField();
+  if (BitField) {
+    llvm::APSInt BitWidthAP = BitField->getBitWidth()->EvaluateAsInt(C);
+    unsigned BitWidth = BitWidthAP.getZExtValue();
+
+    return IntRange(BitWidth, BitField->getType()->isUnsignedIntegerType());
+  }
+
+  return IntRange::forType(C, E->getType());
+}
+
+/// Checks whether the given value, which currently has the given
+/// source semantics, has the same value when coerced through the
+/// target semantics.
+bool IsSameFloatAfterCast(const llvm::APFloat &value,
+                          const llvm::fltSemantics &Src,
+                          const llvm::fltSemantics &Tgt) {
+  llvm::APFloat truncated = value;
+
+  bool ignored;
+  truncated.convert(Src, llvm::APFloat::rmNearestTiesToEven, &ignored);
+  truncated.convert(Tgt, llvm::APFloat::rmNearestTiesToEven, &ignored);
+
+  return truncated.bitwiseIsEqual(value);
+}
+
+/// Checks whether the given value, which currently has the given
+/// source semantics, has the same value when coerced through the
+/// target semantics.
+///
+/// The value might be a vector of floats (or a complex number).
+bool IsSameFloatAfterCast(const APValue &value,
+                          const llvm::fltSemantics &Src,
+                          const llvm::fltSemantics &Tgt) {
+  if (value.isFloat())
+    return IsSameFloatAfterCast(value.getFloat(), Src, Tgt);
+
+  if (value.isVector()) {
+    for (unsigned i = 0, e = value.getVectorLength(); i != e; ++i)
+      if (!IsSameFloatAfterCast(value.getVectorElt(i), Src, Tgt))
+        return false;
+    return true;
+  }
+
+  assert(value.isComplexFloat());
+  return (IsSameFloatAfterCast(value.getComplexFloatReal(), Src, Tgt) &&
+          IsSameFloatAfterCast(value.getComplexFloatImag(), Src, Tgt));
+}
+
+} // end anonymous namespace
+
+/// \brief Implements -Wsign-compare.
+///
+/// \param lex the left-hand expression
+/// \param rex the right-hand expression
+/// \param OpLoc the location of the joining operator
+/// \param Equality whether this is an "equality-like" join, which
+///   suppresses the warning in some cases
+void Sema::CheckSignCompare(Expr *lex, Expr *rex, SourceLocation OpLoc,
+                            const PartialDiagnostic &PD, bool Equality) {
+  // Don't warn if we're in an unevaluated context.
+  if (ExprEvalContexts.back().Context == Unevaluated)
+    return;
+
+  // If either expression is value-dependent, don't warn. We'll get another
+  // chance at instantiation time.
+  if (lex->isValueDependent() || rex->isValueDependent())
+    return;
+
+  QualType lt = lex->getType(), rt = rex->getType();
+
+  // Only warn if both operands are integral.
+  if (!lt->isIntegerType() || !rt->isIntegerType())
+    return;
+
+  // In C, the width of a bitfield determines its type, and the
+  // declared type only contributes the signedness.  This duplicates
+  // the work that will later be done by UsualUnaryConversions.
+  // Eventually, this check will be reorganized in a way that avoids
+  // this duplication.
+  if (!getLangOptions().CPlusPlus) {
+    QualType tmp;
+    tmp = Context.isPromotableBitField(lex);
+    if (!tmp.isNull()) lt = tmp;
+    tmp = Context.isPromotableBitField(rex);
+    if (!tmp.isNull()) rt = tmp;
+  }
+
+  // The rule is that the signed operand becomes unsigned, so isolate the
+  // signed operand.
+  Expr *signedOperand = lex, *unsignedOperand = rex;
+  QualType signedType = lt, unsignedType = rt;
+  if (lt->isSignedIntegerType()) {
+    if (rt->isSignedIntegerType()) return;
+  } else {
+    if (!rt->isSignedIntegerType()) return;
+    std::swap(signedOperand, unsignedOperand);
+    std::swap(signedType, unsignedType);
+  }
+
+  unsigned unsignedWidth = Context.getIntWidth(unsignedType);
+  unsigned signedWidth = Context.getIntWidth(signedType);
+
+  // If the unsigned type is strictly smaller than the signed type,
+  // then (1) the result type will be signed and (2) the unsigned
+  // value will fit fully within the signed type, and thus the result
+  // of the comparison will be exact.
+  if (signedWidth > unsignedWidth)
+    return;
+
+  // Otherwise, calculate the effective ranges.
+  IntRange signedRange = GetExprRange(Context, signedOperand, signedWidth);
+  IntRange unsignedRange = GetExprRange(Context, unsignedOperand, unsignedWidth);
+
+  // We should never be unable to prove that the unsigned operand is
+  // non-negative.
+  assert(unsignedRange.NonNegative && "unsigned range includes negative?");
+
+  // If the signed operand is non-negative, then the signed->unsigned
+  // conversion won't change it.
+  if (signedRange.NonNegative)
+    return;
+
+  // For (in)equality comparisons, if the unsigned operand is a
+  // constant which cannot collide with a overflowed signed operand,
+  // then reinterpreting the signed operand as unsigned will not
+  // change the result of the comparison.
+  if (Equality && unsignedRange.Width < unsignedWidth)
+    return;
+
+  Diag(OpLoc, PD)
+    << lt << rt << lex->getSourceRange() << rex->getSourceRange();
+}
+
+/// Diagnose an implicit cast;  purely a helper for CheckImplicitConversion.
+static void DiagnoseImpCast(Sema &S, Expr *E, QualType T, unsigned diag) {
+  S.Diag(E->getExprLoc(), diag) << E->getType() << T << E->getSourceRange();
+}
+
+/// Implements -Wconversion.
+void Sema::CheckImplicitConversion(Expr *E, QualType T) {
+  // Don't diagnose in unevaluated contexts.
+  if (ExprEvalContexts.back().Context == Sema::Unevaluated)
+    return;
+
+  // Don't diagnose for value-dependent expressions.
+  if (E->isValueDependent())
+    return;
+
+  const Type *Source = Context.getCanonicalType(E->getType()).getTypePtr();
+  const Type *Target = Context.getCanonicalType(T).getTypePtr();
+
+  // Never diagnose implicit casts to bool.
+  if (Target->isSpecificBuiltinType(BuiltinType::Bool))
+    return;
+
+  // Strip vector types.
+  if (isa<VectorType>(Source)) {
+    if (!isa<VectorType>(Target))
+      return DiagnoseImpCast(*this, E, T, diag::warn_impcast_vector_scalar);
+
+    Source = cast<VectorType>(Source)->getElementType().getTypePtr();
+    Target = cast<VectorType>(Target)->getElementType().getTypePtr();
+  }
+
+  // Strip complex types.
+  if (isa<ComplexType>(Source)) {
+    if (!isa<ComplexType>(Target))
+      return DiagnoseImpCast(*this, E, T, diag::warn_impcast_complex_scalar);
+
+    Source = cast<ComplexType>(Source)->getElementType().getTypePtr();
+    Target = cast<ComplexType>(Target)->getElementType().getTypePtr();
+  }
+
+  const BuiltinType *SourceBT = dyn_cast<BuiltinType>(Source);
+  const BuiltinType *TargetBT = dyn_cast<BuiltinType>(Target);
+
+  // If the source is floating point...
+  if (SourceBT && SourceBT->isFloatingPoint()) {
+    // ...and the target is floating point...
+    if (TargetBT && TargetBT->isFloatingPoint()) {
+      // ...then warn if we're dropping FP rank.
+
+      // Builtin FP kinds are ordered by increasing FP rank.
+      if (SourceBT->getKind() > TargetBT->getKind()) {
+        // Don't warn about float constants that are precisely
+        // representable in the target type.
+        Expr::EvalResult result;
+        if (E->Evaluate(result, Context)) {
+          // Value might be a float, a float vector, or a float complex.
+          if (IsSameFloatAfterCast(result.Val,
+                     Context.getFloatTypeSemantics(QualType(TargetBT, 0)),
+                     Context.getFloatTypeSemantics(QualType(SourceBT, 0))))
+            return;
+        }
+
+        DiagnoseImpCast(*this, E, T, diag::warn_impcast_float_precision);
+      }
+      return;
+    }
+
+    // If the target is integral, always warn.
+    if ((TargetBT && TargetBT->isInteger()))
+      // TODO: don't warn for integer values?
+      return DiagnoseImpCast(*this, E, T, diag::warn_impcast_float_integer);
+
+    return;
+  }
+
+  if (!Source->isIntegerType() || !Target->isIntegerType())
+    return;
+
+  IntRange SourceRange = GetExprRange(Context, E, Context.getIntWidth(E->getType()));
+  IntRange TargetRange = IntRange::forCanonicalType(Context, Target);
+
+  // FIXME: also signed<->unsigned?
+
+  if (SourceRange.Width > TargetRange.Width) {
+    // People want to build with -Wshorten-64-to-32 and not -Wconversion
+    // and by god we'll let them.
+    if (SourceRange.Width == 64 && TargetRange.Width == 32)
+      return DiagnoseImpCast(*this, E, T, diag::warn_impcast_integer_64_32);
+    return DiagnoseImpCast(*this, E, T, diag::warn_impcast_integer_precision);
+  }
+
+  return;
+}
+
+// MarkLive - Mark all the blocks reachable from e as live.  Returns the total
+// number of blocks just marked live.
+static unsigned MarkLive(CFGBlock *e, llvm::BitVector &live) {
+  unsigned count = 0;
+  std::queue<CFGBlock*> workq;
+  // Prep work queue
+  live.set(e->getBlockID());
+  ++count;
+  workq.push(e);
+  // Solve
+  while (!workq.empty()) {
+    CFGBlock *item = workq.front();
+    workq.pop();
+    for (CFGBlock::succ_iterator I=item->succ_begin(),
+           E=item->succ_end();
+         I != E;
+         ++I) {
+      if ((*I) && !live[(*I)->getBlockID()]) {
+        live.set((*I)->getBlockID());
+        ++count;
+        workq.push(*I);
+      }
+    }
+  }
+  return count;
+}
+
+static SourceLocation GetUnreachableLoc(CFGBlock &b, SourceRange &R1,
+                                        SourceRange &R2) {
+  Stmt *S;
+  unsigned sn = 0;
+  R1 = R2 = SourceRange();
+
+  top:
+  if (sn < b.size())
+    S = b[sn].getStmt();
+  else if (b.getTerminator())
+    S = b.getTerminator();
+  else
+    return SourceLocation();
+
+  switch (S->getStmtClass()) {
+  case Expr::BinaryOperatorClass: {
+    BinaryOperator *BO = cast<BinaryOperator>(S);
+    if (BO->getOpcode() == BinaryOperator::Comma) {
+      if (sn+1 < b.size())
+        return b[sn+1].getStmt()->getLocStart();
+      CFGBlock *n = &b;
+      while (1) {
+        if (n->getTerminator())
+          return n->getTerminator()->getLocStart();
+        if (n->succ_size() != 1)
+          return SourceLocation();
+        n = n[0].succ_begin()[0];
+        if (n->pred_size() != 1)
+          return SourceLocation();
+        if (!n->empty())
+          return n[0][0].getStmt()->getLocStart();
+      }
+    }
+    R1 = BO->getLHS()->getSourceRange();
+    R2 = BO->getRHS()->getSourceRange();
+    return BO->getOperatorLoc();
+  }
+  case Expr::UnaryOperatorClass: {
+    const UnaryOperator *UO = cast<UnaryOperator>(S);
+    R1 = UO->getSubExpr()->getSourceRange();
+    return UO->getOperatorLoc();
+  }
+  case Expr::CompoundAssignOperatorClass: {
+    const CompoundAssignOperator *CAO = cast<CompoundAssignOperator>(S);
+    R1 = CAO->getLHS()->getSourceRange();
+    R2 = CAO->getRHS()->getSourceRange();
+    return CAO->getOperatorLoc();
+  }
+  case Expr::ConditionalOperatorClass: {
+    const ConditionalOperator *CO = cast<ConditionalOperator>(S);
+    return CO->getQuestionLoc();
+  }
+  case Expr::MemberExprClass: {
+    const MemberExpr *ME = cast<MemberExpr>(S);
+    R1 = ME->getSourceRange();
+    return ME->getMemberLoc();
+  }
+  case Expr::ArraySubscriptExprClass: {
+    const ArraySubscriptExpr *ASE = cast<ArraySubscriptExpr>(S);
+    R1 = ASE->getLHS()->getSourceRange();
+    R2 = ASE->getRHS()->getSourceRange();
+    return ASE->getRBracketLoc();
+  }
+  case Expr::CStyleCastExprClass: {
+    const CStyleCastExpr *CSC = cast<CStyleCastExpr>(S);
+    R1 = CSC->getSubExpr()->getSourceRange();
+    return CSC->getLParenLoc();
+  }
+  case Expr::CXXFunctionalCastExprClass: {
+    const CXXFunctionalCastExpr *CE = cast <CXXFunctionalCastExpr>(S);
+    R1 = CE->getSubExpr()->getSourceRange();
+    return CE->getTypeBeginLoc();
+  }
+  case Expr::ImplicitCastExprClass:
+    ++sn;
+    goto top;
+  case Stmt::CXXTryStmtClass: {
+    return cast<CXXTryStmt>(S)->getHandler(0)->getCatchLoc();
+  }
+  default: ;
+  }
+  R1 = S->getSourceRange();
+  return S->getLocStart();
+}
+
+static SourceLocation MarkLiveTop(CFGBlock *e, llvm::BitVector &live,
+                               SourceManager &SM) {
+  std::queue<CFGBlock*> workq;
+  // Prep work queue
+  workq.push(e);
+  SourceRange R1, R2;
+  SourceLocation top = GetUnreachableLoc(*e, R1, R2);
+  bool FromMainFile = false;
+  bool FromSystemHeader = false;
+  bool TopValid = false;
+  if (top.isValid()) {
+    FromMainFile = SM.isFromMainFile(top);
+    FromSystemHeader = SM.isInSystemHeader(top);
+    TopValid = true;
+  }
+  // Solve
+  while (!workq.empty()) {
+    CFGBlock *item = workq.front();
+    workq.pop();
+    SourceLocation c = GetUnreachableLoc(*item, R1, R2);
+    if (c.isValid()
+        && (!TopValid
+            || (SM.isFromMainFile(c) && !FromMainFile)
+            || (FromSystemHeader && !SM.isInSystemHeader(c))
+            || SM.isBeforeInTranslationUnit(c, top))) {
+      top = c;
+      FromMainFile = SM.isFromMainFile(top);
+      FromSystemHeader = SM.isInSystemHeader(top);
+    }
+    live.set(item->getBlockID());
+    for (CFGBlock::succ_iterator I=item->succ_begin(),
+           E=item->succ_end();
+         I != E;
+         ++I) {
+      if ((*I) && !live[(*I)->getBlockID()]) {
+        live.set((*I)->getBlockID());
+        workq.push(*I);
+      }
+    }
+  }
+  return top;
+}
+
+static int LineCmp(const void *p1, const void *p2) {
+  SourceLocation *Line1 = (SourceLocation *)p1;
+  SourceLocation *Line2 = (SourceLocation *)p2;
+  return !(*Line1 < *Line2);
+}
+
+namespace {
+  struct ErrLoc {
+    SourceLocation Loc;
+    SourceRange R1;
+    SourceRange R2;
+    ErrLoc(SourceLocation l, SourceRange r1, SourceRange r2)
+      : Loc(l), R1(r1), R2(r2) { }
+  };
+}
+
+/// CheckUnreachable - Check for unreachable code.
+void Sema::CheckUnreachable(AnalysisContext &AC) {
+  unsigned count;
+  // We avoid checking when there are errors, as the CFG won't faithfully match
+  // the user's code.
+  if (getDiagnostics().hasErrorOccurred())
+    return;
+  if (Diags.getDiagnosticLevel(diag::warn_unreachable) == Diagnostic::Ignored)
+    return;
+
+  CFG *cfg = AC.getCFG();
+  if (cfg == 0)
+    return;
+  
+  llvm::BitVector live(cfg->getNumBlockIDs());
+  // Mark all live things first.
+  count = MarkLive(&cfg->getEntry(), live);
+
+  if (count == cfg->getNumBlockIDs())
+    // If there are no dead blocks, we're done.
+    return;
+
+  SourceRange R1, R2;
+
+  llvm::SmallVector<ErrLoc, 24> lines;
+  bool AddEHEdges = AC.getAddEHEdges();
+  // First, give warnings for blocks with no predecessors, as they
+  // can't be part of a loop.
+  for (CFG::iterator I = cfg->begin(), E = cfg->end(); I != E; ++I) {
+    CFGBlock &b = **I;
+    if (!live[b.getBlockID()]) {
+      if (b.pred_begin() == b.pred_end()) {
+        if (!AddEHEdges && b.getTerminator()
+            && isa<CXXTryStmt>(b.getTerminator())) {
+          // When not adding EH edges from calls, catch clauses
+          // can otherwise seem dead.  Avoid noting them as dead.
+          count += MarkLive(&b, live);
+          continue;
+        }
+        SourceLocation c = GetUnreachableLoc(b, R1, R2);
+        if (!c.isValid()) {
+          // Blocks without a location can't produce a warning, so don't mark
+          // reachable blocks from here as live.
+          live.set(b.getBlockID());
+          ++count;
+          continue;
+        }
+        lines.push_back(ErrLoc(c, R1, R2));
+        // Avoid excessive errors by marking everything reachable from here
+        count += MarkLive(&b, live);
+      }
+    }
+  }
+
+  if (count < cfg->getNumBlockIDs()) {
+    // And then give warnings for the tops of loops.
+    for (CFG::iterator I = cfg->begin(), E = cfg->end(); I != E; ++I) {
+      CFGBlock &b = **I;
+      if (!live[b.getBlockID()])
+        // Avoid excessive errors by marking everything reachable from here
+        lines.push_back(ErrLoc(MarkLiveTop(&b, live,
+                                           Context.getSourceManager()),
+                               SourceRange(), SourceRange()));
+    }
+  }
+
+  llvm::array_pod_sort(lines.begin(), lines.end(), LineCmp);
+  for (llvm::SmallVector<ErrLoc, 24>::iterator I = lines.begin(),
+         E = lines.end();
+       I != E;
+       ++I)
+    if (I->Loc.isValid())
+      Diag(I->Loc, diag::warn_unreachable) << I->R1 << I->R2;
+}
+
+/// CheckFallThrough - Check that we don't fall off the end of a
+/// Statement that should return a value.
+///
+/// \returns AlwaysFallThrough iff we always fall off the end of the statement,
+/// MaybeFallThrough iff we might or might not fall off the end,
+/// NeverFallThroughOrReturn iff we never fall off the end of the statement or
+/// return.  We assume NeverFallThrough iff we never fall off the end of the
+/// statement but we may return.  We assume that functions not marked noreturn
+/// will return.
+Sema::ControlFlowKind Sema::CheckFallThrough(AnalysisContext &AC) {
+  CFG *cfg = AC.getCFG();
+  if (cfg == 0)
+    // FIXME: This should be NeverFallThrough
+    return NeverFallThroughOrReturn;
+
+  // The CFG leaves in dead things, and we don't want the dead code paths to
+  // confuse us, so we mark all live things first.
+  std::queue<CFGBlock*> workq;
+  llvm::BitVector live(cfg->getNumBlockIDs());
+  unsigned count = MarkLive(&cfg->getEntry(), live);
+
+  bool AddEHEdges = AC.getAddEHEdges();
+  if (!AddEHEdges && count != cfg->getNumBlockIDs())
+    // When there are things remaining dead, and we didn't add EH edges
+    // from CallExprs to the catch clauses, we have to go back and
+    // mark them as live.
+    for (CFG::iterator I = cfg->begin(), E = cfg->end(); I != E; ++I) {
+      CFGBlock &b = **I;
+      if (!live[b.getBlockID()]) {
+        if (b.pred_begin() == b.pred_end()) {
+          if (b.getTerminator() && isa<CXXTryStmt>(b.getTerminator()))
+            // When not adding EH edges from calls, catch clauses
+            // can otherwise seem dead.  Avoid noting them as dead.
+            count += MarkLive(&b, live);
+          continue;
+        }
+      }
+    }
+
+  // Now we know what is live, we check the live precessors of the exit block
+  // and look for fall through paths, being careful to ignore normal returns,
+  // and exceptional paths.
+  bool HasLiveReturn = false;
+  bool HasFakeEdge = false;
+  bool HasPlainEdge = false;
+  bool HasAbnormalEdge = false;
+  for (CFGBlock::pred_iterator I=cfg->getExit().pred_begin(),
+         E = cfg->getExit().pred_end();
+       I != E;
+       ++I) {
+    CFGBlock& B = **I;
+    if (!live[B.getBlockID()])
+      continue;
+    if (B.size() == 0) {
+      if (B.getTerminator() && isa<CXXTryStmt>(B.getTerminator())) {
+        HasAbnormalEdge = true;
+        continue;
+      }
+
+      // A labeled empty statement, or the entry block...
+      HasPlainEdge = true;
+      continue;
+    }
+    Stmt *S = B[B.size()-1];
+    if (isa<ReturnStmt>(S)) {
+      HasLiveReturn = true;
+      continue;
+    }
+    if (isa<ObjCAtThrowStmt>(S)) {
+      HasFakeEdge = true;
+      continue;
+    }
+    if (isa<CXXThrowExpr>(S)) {
+      HasFakeEdge = true;
+      continue;
+    }
+    if (const AsmStmt *AS = dyn_cast<AsmStmt>(S)) {
+      if (AS->isMSAsm()) {
+        HasFakeEdge = true;
+        HasLiveReturn = true;
+        continue;
+      }
+    }
+    if (isa<CXXTryStmt>(S)) {
+      HasAbnormalEdge = true;
+      continue;
+    }
+
+    bool NoReturnEdge = false;
+    if (CallExpr *C = dyn_cast<CallExpr>(S)) {
+      if (B.succ_begin()[0] != &cfg->getExit()) {
+        HasAbnormalEdge = true;
+        continue;
+      }
+      Expr *CEE = C->getCallee()->IgnoreParenCasts();
+      if (CEE->getType().getNoReturnAttr()) {
+        NoReturnEdge = true;
+        HasFakeEdge = true;
+      } else if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(CEE)) {
+        ValueDecl *VD = DRE->getDecl();
+        if (VD->hasAttr<NoReturnAttr>()) {
+          NoReturnEdge = true;
+          HasFakeEdge = true;
+        }
+      }
+    }
+    // FIXME: Add noreturn message sends.
+    if (NoReturnEdge == false)
+      HasPlainEdge = true;
+  }
+  if (!HasPlainEdge) {
+    if (HasLiveReturn)
+      return NeverFallThrough;
+    return NeverFallThroughOrReturn;
+  }
+  if (HasAbnormalEdge || HasFakeEdge || HasLiveReturn)
+    return MaybeFallThrough;
+  // This says AlwaysFallThrough for calls to functions that are not marked
+  // noreturn, that don't return.  If people would like this warning to be more
+  // accurate, such functions should be marked as noreturn.
+  return AlwaysFallThrough;
+}
+
+/// CheckFallThroughForFunctionDef - Check that we don't fall off the end of a
+/// function that should return a value.  Check that we don't fall off the end
+/// of a noreturn function.  We assume that functions and blocks not marked
+/// noreturn will return.
+void Sema::CheckFallThroughForFunctionDef(Decl *D, Stmt *Body,
+                                          AnalysisContext &AC) {
+  // FIXME: Would be nice if we had a better way to control cascading errors,
+  // but for now, avoid them.  The problem is that when Parse sees:
+  //   int foo() { return a; }
+  // The return is eaten and the Sema code sees just:
+  //   int foo() { }
+  // which this code would then warn about.
+  if (getDiagnostics().hasErrorOccurred())
+    return;
+  
+  bool ReturnsVoid = false;
+  bool HasNoReturn = false;
+  if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
+    // For function templates, class templates and member function templates
+    // we'll do the analysis at instantiation time.
+    if (FD->isDependentContext())
+      return;
+
+    if (FD->getResultType()->isVoidType())
+      ReturnsVoid = true;
+    if (FD->hasAttr<NoReturnAttr>() ||
+        FD->getType()->getAs<FunctionType>()->getNoReturnAttr())
+      HasNoReturn = true;
+  } else if (ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) {
+    if (MD->getResultType()->isVoidType())
+      ReturnsVoid = true;
+    if (MD->hasAttr<NoReturnAttr>())
+      HasNoReturn = true;
+  }
+
+  // Short circuit for compilation speed.
+  if ((Diags.getDiagnosticLevel(diag::warn_maybe_falloff_nonvoid_function)
+       == Diagnostic::Ignored || ReturnsVoid)
+      && (Diags.getDiagnosticLevel(diag::warn_noreturn_function_has_return_expr)
+          == Diagnostic::Ignored || !HasNoReturn)
+      && (Diags.getDiagnosticLevel(diag::warn_suggest_noreturn_block)
+          == Diagnostic::Ignored || !ReturnsVoid))
+    return;
+  // FIXME: Function try block
+  if (CompoundStmt *Compound = dyn_cast<CompoundStmt>(Body)) {
+    switch (CheckFallThrough(AC)) {
+    case MaybeFallThrough:
+      if (HasNoReturn)
+        Diag(Compound->getRBracLoc(), diag::warn_falloff_noreturn_function);
+      else if (!ReturnsVoid)
+        Diag(Compound->getRBracLoc(),diag::warn_maybe_falloff_nonvoid_function);
+      break;
+    case AlwaysFallThrough:
+      if (HasNoReturn)
+        Diag(Compound->getRBracLoc(), diag::warn_falloff_noreturn_function);
+      else if (!ReturnsVoid)
+        Diag(Compound->getRBracLoc(), diag::warn_falloff_nonvoid_function);
+      break;
+    case NeverFallThroughOrReturn:
+      if (ReturnsVoid && !HasNoReturn)
+        Diag(Compound->getLBracLoc(), diag::warn_suggest_noreturn_function);
+      break;
+    case NeverFallThrough:
+      break;
+    }
+  }
+}
+
+/// CheckFallThroughForBlock - Check that we don't fall off the end of a block
+/// that should return a value.  Check that we don't fall off the end of a
+/// noreturn block.  We assume that functions and blocks not marked noreturn
+/// will return.
+void Sema::CheckFallThroughForBlock(QualType BlockTy, Stmt *Body,
+                                    AnalysisContext &AC) {
+  // FIXME: Would be nice if we had a better way to control cascading errors,
+  // but for now, avoid them.  The problem is that when Parse sees:
+  //   int foo() { return a; }
+  // The return is eaten and the Sema code sees just:
+  //   int foo() { }
+  // which this code would then warn about.
+  if (getDiagnostics().hasErrorOccurred())
+    return;
+  bool ReturnsVoid = false;
+  bool HasNoReturn = false;
+  if (const FunctionType *FT =BlockTy->getPointeeType()->getAs<FunctionType>()){
+    if (FT->getResultType()->isVoidType())
+      ReturnsVoid = true;
+    if (FT->getNoReturnAttr())
+      HasNoReturn = true;
+  }
+
+  // Short circuit for compilation speed.
+  if (ReturnsVoid
+      && !HasNoReturn
+      && (Diags.getDiagnosticLevel(diag::warn_suggest_noreturn_block)
+          == Diagnostic::Ignored || !ReturnsVoid))
+    return;
+  // FIXME: Funtion try block
+  if (CompoundStmt *Compound = dyn_cast<CompoundStmt>(Body)) {
+    switch (CheckFallThrough(AC)) {
+    case MaybeFallThrough:
+      if (HasNoReturn)
+        Diag(Compound->getRBracLoc(), diag::err_noreturn_block_has_return_expr);
+      else if (!ReturnsVoid)
+        Diag(Compound->getRBracLoc(), diag::err_maybe_falloff_nonvoid_block);
+      break;
+    case AlwaysFallThrough:
+      if (HasNoReturn)
+        Diag(Compound->getRBracLoc(), diag::err_noreturn_block_has_return_expr);
+      else if (!ReturnsVoid)
+        Diag(Compound->getRBracLoc(), diag::err_falloff_nonvoid_block);
+      break;
+    case NeverFallThroughOrReturn:
+      if (ReturnsVoid)
+        Diag(Compound->getLBracLoc(), diag::warn_suggest_noreturn_block);
+      break;
+    case NeverFallThrough:
+      break;
+    }
+  }
+}
+
+/// CheckParmsForFunctionDef - Check that the parameters of the given
+/// function are appropriate for the definition of a function. This
+/// takes care of any checks that cannot be performed on the
+/// declaration itself, e.g., that the types of each of the function
+/// parameters are complete.
+bool Sema::CheckParmsForFunctionDef(FunctionDecl *FD) {
+  bool HasInvalidParm = false;
+  for (unsigned p = 0, NumParams = FD->getNumParams(); p < NumParams; ++p) {
+    ParmVarDecl *Param = FD->getParamDecl(p);
+
+    // C99 6.7.5.3p4: the parameters in a parameter type list in a
+    // function declarator that is part of a function definition of
+    // that function shall not have incomplete type.
+    //
+    // This is also C++ [dcl.fct]p6.
+    if (!Param->isInvalidDecl() &&
+        RequireCompleteType(Param->getLocation(), Param->getType(),
+                               diag::err_typecheck_decl_incomplete_type)) {
+      Param->setInvalidDecl();
+      HasInvalidParm = true;
+    }
+
+    // C99 6.9.1p5: If the declarator includes a parameter type list, the
+    // declaration of each parameter shall include an identifier.
+    if (Param->getIdentifier() == 0 &&
+        !Param->isImplicit() &&
+        !getLangOptions().CPlusPlus)
+      Diag(Param->getLocation(), diag::err_parameter_name_omitted);
+
+    // C99 6.7.5.3p12:
+    //   If the function declarator is not part of a definition of that
+    //   function, parameters may have incomplete type and may use the [*]
+    //   notation in their sequences of declarator specifiers to specify
+    //   variable length array types.
+    QualType PType = Param->getOriginalType();
+    if (const ArrayType *AT = Context.getAsArrayType(PType)) {
+      if (AT->getSizeModifier() == ArrayType::Star) {
+        // FIXME: This diagnosic should point the the '[*]' if source-location
+        // information is added for it.
+        Diag(Param->getLocation(), diag::err_array_star_in_function_definition);
+      }
+    }
+
+    if (getLangOptions().CPlusPlus)
+      if (const RecordType *RT = Param->getType()->getAs<RecordType>())
+        FinalizeVarWithDestructor(Param, RT);
+  }
+
+  return HasInvalidParm;
+}
diff --git a/lib/Sema/SemaCodeComplete.cpp b/lib/Sema/SemaCodeComplete.cpp
new file mode 100644
index 0000000..a862949
--- /dev/null
+++ b/lib/Sema/SemaCodeComplete.cpp
@@ -0,0 +1,3302 @@
+//===---------------- SemaCodeComplete.cpp - Code Completion ----*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+//  This file defines the code-completion semantic actions.
+//
+//===----------------------------------------------------------------------===//
+#include "Sema.h"
+#include "Lookup.h"
+#include "clang/Sema/CodeCompleteConsumer.h"
+#include "clang/AST/ExprCXX.h"
+#include "clang/AST/ExprObjC.h"
+#include "clang/Lex/MacroInfo.h"
+#include "clang/Lex/Preprocessor.h"
+#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/StringExtras.h"
+#include <list>
+#include <map>
+#include <vector>
+
+using namespace clang;
+
+namespace {
+  /// \brief A container of code-completion results.
+  class ResultBuilder {
+  public:
+    /// \brief The type of a name-lookup filter, which can be provided to the
+    /// name-lookup routines to specify which declarations should be included in
+    /// the result set (when it returns true) and which declarations should be
+    /// filtered out (returns false).
+    typedef bool (ResultBuilder::*LookupFilter)(NamedDecl *) const;
+    
+    typedef CodeCompleteConsumer::Result Result;
+    
+  private:
+    /// \brief The actual results we have found.
+    std::vector<Result> Results;
+    
+    /// \brief A record of all of the declarations we have found and placed
+    /// into the result set, used to ensure that no declaration ever gets into
+    /// the result set twice.
+    llvm::SmallPtrSet<Decl*, 16> AllDeclsFound;
+    
+    typedef std::pair<NamedDecl *, unsigned> DeclIndexPair;
+
+    /// \brief An entry in the shadow map, which is optimized to store
+    /// a single (declaration, index) mapping (the common case) but
+    /// can also store a list of (declaration, index) mappings.
+    class ShadowMapEntry {
+      typedef llvm::SmallVector<DeclIndexPair, 4> DeclIndexPairVector;
+
+      /// \brief Contains either the solitary NamedDecl * or a vector
+      /// of (declaration, index) pairs.
+      llvm::PointerUnion<NamedDecl *, DeclIndexPairVector*> DeclOrVector;
+
+      /// \brief When the entry contains a single declaration, this is
+      /// the index associated with that entry.
+      unsigned SingleDeclIndex;
+
+    public:
+      ShadowMapEntry() : DeclOrVector(), SingleDeclIndex(0) { }
+
+      void Add(NamedDecl *ND, unsigned Index) {
+        if (DeclOrVector.isNull()) {
+          // 0 - > 1 elements: just set the single element information.
+          DeclOrVector = ND;
+          SingleDeclIndex = Index;
+          return;
+        }
+
+        if (NamedDecl *PrevND = DeclOrVector.dyn_cast<NamedDecl *>()) {
+          // 1 -> 2 elements: create the vector of results and push in the
+          // existing declaration.
+          DeclIndexPairVector *Vec = new DeclIndexPairVector;
+          Vec->push_back(DeclIndexPair(PrevND, SingleDeclIndex));
+          DeclOrVector = Vec;
+        }
+
+        // Add the new element to the end of the vector.
+        DeclOrVector.get<DeclIndexPairVector*>()->push_back(
+                                                    DeclIndexPair(ND, Index));
+      }
+
+      void Destroy() {
+        if (DeclIndexPairVector *Vec
+              = DeclOrVector.dyn_cast<DeclIndexPairVector *>()) {
+          delete Vec;
+          DeclOrVector = ((NamedDecl *)0);
+        }
+      }
+
+      // Iteration.
+      class iterator;
+      iterator begin() const;
+      iterator end() const;
+    };
+
+    /// \brief A mapping from declaration names to the declarations that have
+    /// this name within a particular scope and their index within the list of
+    /// results.
+    typedef llvm::DenseMap<DeclarationName, ShadowMapEntry> ShadowMap;
+    
+    /// \brief The semantic analysis object for which results are being 
+    /// produced.
+    Sema &SemaRef;
+    
+    /// \brief If non-NULL, a filter function used to remove any code-completion
+    /// results that are not desirable.
+    LookupFilter Filter;
+
+    /// \brief Whether we should allow declarations as
+    /// nested-name-specifiers that would otherwise be filtered out.
+    bool AllowNestedNameSpecifiers;
+
+    /// \brief A list of shadow maps, which is used to model name hiding at
+    /// different levels of, e.g., the inheritance hierarchy.
+    std::list<ShadowMap> ShadowMaps;
+    
+  public:
+    explicit ResultBuilder(Sema &SemaRef, LookupFilter Filter = 0)
+      : SemaRef(SemaRef), Filter(Filter), AllowNestedNameSpecifiers(false) { }
+    
+    /// \brief Set the filter used for code-completion results.
+    void setFilter(LookupFilter Filter) {
+      this->Filter = Filter;
+    }
+    
+    typedef std::vector<Result>::iterator iterator;
+    iterator begin() { return Results.begin(); }
+    iterator end() { return Results.end(); }
+    
+    Result *data() { return Results.empty()? 0 : &Results.front(); }
+    unsigned size() const { return Results.size(); }
+    bool empty() const { return Results.empty(); }
+    
+    /// \brief Specify whether nested-name-specifiers are allowed.
+    void allowNestedNameSpecifiers(bool Allow = true) {
+      AllowNestedNameSpecifiers = Allow;
+    }
+
+    /// \brief Determine whether the given declaration is at all interesting
+    /// as a code-completion result.
+    ///
+    /// \param ND the declaration that we are inspecting.
+    ///
+    /// \param AsNestedNameSpecifier will be set true if this declaration is
+    /// only interesting when it is a nested-name-specifier.
+    bool isInterestingDecl(NamedDecl *ND, bool &AsNestedNameSpecifier) const;
+    
+    /// \brief Check whether the result is hidden by the Hiding declaration.
+    ///
+    /// \returns true if the result is hidden and cannot be found, false if
+    /// the hidden result could still be found. When false, \p R may be
+    /// modified to describe how the result can be found (e.g., via extra
+    /// qualification).
+    bool CheckHiddenResult(Result &R, DeclContext *CurContext,
+                           NamedDecl *Hiding);
+    
+    /// \brief Add a new result to this result set (if it isn't already in one
+    /// of the shadow maps), or replace an existing result (for, e.g., a 
+    /// redeclaration).
+    ///
+    /// \param CurContext the result to add (if it is unique).
+    ///
+    /// \param R the context in which this result will be named.
+    void MaybeAddResult(Result R, DeclContext *CurContext = 0);
+    
+    /// \brief Add a new result to this result set, where we already know
+    /// the hiding declation (if any).
+    ///
+    /// \param R the result to add (if it is unique).
+    ///
+    /// \param CurContext the context in which this result will be named.
+    ///
+    /// \param Hiding the declaration that hides the result.
+    ///
+    /// \param InBaseClass whether the result was found in a base
+    /// class of the searched context.
+    void AddResult(Result R, DeclContext *CurContext, NamedDecl *Hiding,
+                   bool InBaseClass);
+    
+    /// \brief Add a new non-declaration result to this result set.
+    void AddResult(Result R);
+
+    /// \brief Enter into a new scope.
+    void EnterNewScope();
+    
+    /// \brief Exit from the current scope.
+    void ExitScope();
+    
+    /// \brief Ignore this declaration, if it is seen again.
+    void Ignore(Decl *D) { AllDeclsFound.insert(D->getCanonicalDecl()); }
+
+    /// \name Name lookup predicates
+    ///
+    /// These predicates can be passed to the name lookup functions to filter the
+    /// results of name lookup. All of the predicates have the same type, so that
+    /// 
+    //@{
+    bool IsOrdinaryName(NamedDecl *ND) const;
+    bool IsOrdinaryNonValueName(NamedDecl *ND) const;
+    bool IsNestedNameSpecifier(NamedDecl *ND) const;
+    bool IsEnum(NamedDecl *ND) const;
+    bool IsClassOrStruct(NamedDecl *ND) const;
+    bool IsUnion(NamedDecl *ND) const;
+    bool IsNamespace(NamedDecl *ND) const;
+    bool IsNamespaceOrAlias(NamedDecl *ND) const;
+    bool IsType(NamedDecl *ND) const;
+    bool IsMember(NamedDecl *ND) const;
+    bool IsObjCIvar(NamedDecl *ND) const;
+    //@}    
+  };  
+}
+
+class ResultBuilder::ShadowMapEntry::iterator {
+  llvm::PointerUnion<NamedDecl*, const DeclIndexPair*> DeclOrIterator;
+  unsigned SingleDeclIndex;
+
+public:
+  typedef DeclIndexPair value_type;
+  typedef value_type reference;
+  typedef std::ptrdiff_t difference_type;
+  typedef std::input_iterator_tag iterator_category;
+        
+  class pointer {
+    DeclIndexPair Value;
+
+  public:
+    pointer(const DeclIndexPair &Value) : Value(Value) { }
+
+    const DeclIndexPair *operator->() const {
+      return &Value;
+    }
+  };
+        
+  iterator() : DeclOrIterator((NamedDecl *)0), SingleDeclIndex(0) { }
+
+  iterator(NamedDecl *SingleDecl, unsigned Index)
+    : DeclOrIterator(SingleDecl), SingleDeclIndex(Index) { }
+
+  iterator(const DeclIndexPair *Iterator)
+    : DeclOrIterator(Iterator), SingleDeclIndex(0) { }
+
+  iterator &operator++() {
+    if (DeclOrIterator.is<NamedDecl *>()) {
+      DeclOrIterator = (NamedDecl *)0;
+      SingleDeclIndex = 0;
+      return *this;
+    }
+
+    const DeclIndexPair *I = DeclOrIterator.get<const DeclIndexPair*>();
+    ++I;
+    DeclOrIterator = I;
+    return *this;
+  }
+
+  iterator operator++(int) {
+    iterator tmp(*this);
+    ++(*this);
+    return tmp;
+  }
+
+  reference operator*() const {
+    if (NamedDecl *ND = DeclOrIterator.dyn_cast<NamedDecl *>())
+      return reference(ND, SingleDeclIndex);
+
+    return *DeclOrIterator.get<const DeclIndexPair*>();
+  }
+
+  pointer operator->() const {
+    return pointer(**this);
+  }
+
+  friend bool operator==(const iterator &X, const iterator &Y) {
+    return X.DeclOrIterator.getOpaqueValue()
+                                  == Y.DeclOrIterator.getOpaqueValue() &&
+      X.SingleDeclIndex == Y.SingleDeclIndex;
+  }
+
+  friend bool operator!=(const iterator &X, const iterator &Y) {
+    return !(X == Y);
+  }
+};
+
+ResultBuilder::ShadowMapEntry::iterator 
+ResultBuilder::ShadowMapEntry::begin() const {
+  if (DeclOrVector.isNull())
+    return iterator();
+
+  if (NamedDecl *ND = DeclOrVector.dyn_cast<NamedDecl *>())
+    return iterator(ND, SingleDeclIndex);
+
+  return iterator(DeclOrVector.get<DeclIndexPairVector *>()->begin());
+}
+
+ResultBuilder::ShadowMapEntry::iterator 
+ResultBuilder::ShadowMapEntry::end() const {
+  if (DeclOrVector.is<NamedDecl *>() || DeclOrVector.isNull())
+    return iterator();
+
+  return iterator(DeclOrVector.get<DeclIndexPairVector *>()->end());
+}
+
+/// \brief Compute the qualification required to get from the current context
+/// (\p CurContext) to the target context (\p TargetContext).
+///
+/// \param Context the AST context in which the qualification will be used.
+///
+/// \param CurContext the context where an entity is being named, which is
+/// typically based on the current scope.
+///
+/// \param TargetContext the context in which the named entity actually 
+/// resides.
+///
+/// \returns a nested name specifier that refers into the target context, or
+/// NULL if no qualification is needed.
+static NestedNameSpecifier *
+getRequiredQualification(ASTContext &Context,
+                         DeclContext *CurContext,
+                         DeclContext *TargetContext) {
+  llvm::SmallVector<DeclContext *, 4> TargetParents;
+  
+  for (DeclContext *CommonAncestor = TargetContext;
+       CommonAncestor && !CommonAncestor->Encloses(CurContext);
+       CommonAncestor = CommonAncestor->getLookupParent()) {
+    if (CommonAncestor->isTransparentContext() ||
+        CommonAncestor->isFunctionOrMethod())
+      continue;
+    
+    TargetParents.push_back(CommonAncestor);
+  }
+  
+  NestedNameSpecifier *Result = 0;
+  while (!TargetParents.empty()) {
+    DeclContext *Parent = TargetParents.back();
+    TargetParents.pop_back();
+    
+    if (NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(Parent))
+      Result = NestedNameSpecifier::Create(Context, Result, Namespace);
+    else if (TagDecl *TD = dyn_cast<TagDecl>(Parent))
+      Result = NestedNameSpecifier::Create(Context, Result,
+                                           false,
+                                     Context.getTypeDeclType(TD).getTypePtr());
+    else
+      assert(Parent->isTranslationUnit());
+  }  
+  return Result;
+}
+
+bool ResultBuilder::isInterestingDecl(NamedDecl *ND, 
+                                      bool &AsNestedNameSpecifier) const {
+  AsNestedNameSpecifier = false;
+
+  ND = ND->getUnderlyingDecl();
+  unsigned IDNS = ND->getIdentifierNamespace();
+
+  // Skip unnamed entities.
+  if (!ND->getDeclName())
+    return false;
+  
+  // Friend declarations and declarations introduced due to friends are never
+  // added as results.
+  if (isa<FriendDecl>(ND) || 
+      (IDNS & (Decl::IDNS_OrdinaryFriend | Decl::IDNS_TagFriend)))
+    return false;
+  
+  // Class template (partial) specializations are never added as results.
+  if (isa<ClassTemplateSpecializationDecl>(ND) ||
+      isa<ClassTemplatePartialSpecializationDecl>(ND))
+    return false;
+  
+  // Using declarations themselves are never added as results.
+  if (isa<UsingDecl>(ND))
+    return false;
+  
+  // Some declarations have reserved names that we don't want to ever show.
+  if (const IdentifierInfo *Id = ND->getIdentifier()) {
+    // __va_list_tag is a freak of nature. Find it and skip it.
+    if (Id->isStr("__va_list_tag") || Id->isStr("__builtin_va_list"))
+      return false;
+    
+    // Filter out names reserved for the implementation (C99 7.1.3, 
+    // C++ [lib.global.names]). Users don't need to see those.
+    //
+    // FIXME: Add predicate for this.
+    if (Id->getLength() >= 2) {
+      const char *Name = Id->getNameStart();
+      if (Name[0] == '_' &&
+          (Name[1] == '_' || (Name[1] >= 'A' && Name[1] <= 'Z')))
+        return false;
+    }
+  }
+ 
+  // C++ constructors are never found by name lookup.
+  if (isa<CXXConstructorDecl>(ND))
+    return false;
+  
+  // Filter out any unwanted results.
+  if (Filter && !(this->*Filter)(ND)) {
+    // Check whether it is interesting as a nested-name-specifier.
+    if (AllowNestedNameSpecifiers && SemaRef.getLangOptions().CPlusPlus && 
+        IsNestedNameSpecifier(ND) &&
+        (Filter != &ResultBuilder::IsMember ||
+         (isa<CXXRecordDecl>(ND) && 
+          cast<CXXRecordDecl>(ND)->isInjectedClassName()))) {
+      AsNestedNameSpecifier = true;
+      return true;
+    }
+
+    return false;
+  }
+  
+  // ... then it must be interesting!
+  return true;
+}
+
+bool ResultBuilder::CheckHiddenResult(Result &R, DeclContext *CurContext,
+                                      NamedDecl *Hiding) {
+  // In C, there is no way to refer to a hidden name.
+  // FIXME: This isn't true; we can find a tag name hidden by an ordinary
+  // name if we introduce the tag type.
+  if (!SemaRef.getLangOptions().CPlusPlus)
+    return true;
+  
+  DeclContext *HiddenCtx = R.Declaration->getDeclContext()->getLookupContext();
+  
+  // There is no way to qualify a name declared in a function or method.
+  if (HiddenCtx->isFunctionOrMethod())
+    return true;
+  
+  if (HiddenCtx == Hiding->getDeclContext()->getLookupContext())
+    return true;
+  
+  // We can refer to the result with the appropriate qualification. Do it.
+  R.Hidden = true;
+  R.QualifierIsInformative = false;
+  
+  if (!R.Qualifier)
+    R.Qualifier = getRequiredQualification(SemaRef.Context, 
+                                           CurContext, 
+                                           R.Declaration->getDeclContext());
+  return false;
+}
+
+void ResultBuilder::MaybeAddResult(Result R, DeclContext *CurContext) {
+  assert(!ShadowMaps.empty() && "Must enter into a results scope");
+  
+  if (R.Kind != Result::RK_Declaration) {
+    // For non-declaration results, just add the result.
+    Results.push_back(R);
+    return;
+  }
+
+  // Look through using declarations.
+  if (UsingShadowDecl *Using = dyn_cast<UsingShadowDecl>(R.Declaration)) {
+    MaybeAddResult(Result(Using->getTargetDecl(), R.Qualifier), CurContext);
+    return;
+  }
+  
+  Decl *CanonDecl = R.Declaration->getCanonicalDecl();
+  unsigned IDNS = CanonDecl->getIdentifierNamespace();
+
+  bool AsNestedNameSpecifier = false;
+  if (!isInterestingDecl(R.Declaration, AsNestedNameSpecifier))
+    return;
+      
+  ShadowMap &SMap = ShadowMaps.back();
+  ShadowMapEntry::iterator I, IEnd;
+  ShadowMap::iterator NamePos = SMap.find(R.Declaration->getDeclName());
+  if (NamePos != SMap.end()) {
+    I = NamePos->second.begin();
+    IEnd = NamePos->second.end();
+  }
+
+  for (; I != IEnd; ++I) {
+    NamedDecl *ND = I->first;
+    unsigned Index = I->second;
+    if (ND->getCanonicalDecl() == CanonDecl) {
+      // This is a redeclaration. Always pick the newer declaration.
+      Results[Index].Declaration = R.Declaration;
+      
+      // We're done.
+      return;
+    }
+  }
+  
+  // This is a new declaration in this scope. However, check whether this
+  // declaration name is hidden by a similarly-named declaration in an outer
+  // scope.
+  std::list<ShadowMap>::iterator SM, SMEnd = ShadowMaps.end();
+  --SMEnd;
+  for (SM = ShadowMaps.begin(); SM != SMEnd; ++SM) {
+    ShadowMapEntry::iterator I, IEnd;
+    ShadowMap::iterator NamePos = SM->find(R.Declaration->getDeclName());
+    if (NamePos != SM->end()) {
+      I = NamePos->second.begin();
+      IEnd = NamePos->second.end();
+    }
+    for (; I != IEnd; ++I) {
+      // A tag declaration does not hide a non-tag declaration.
+      if (I->first->getIdentifierNamespace() == Decl::IDNS_Tag &&
+          (IDNS & (Decl::IDNS_Member | Decl::IDNS_Ordinary | 
+                   Decl::IDNS_ObjCProtocol)))
+        continue;
+      
+      // Protocols are in distinct namespaces from everything else.
+      if (((I->first->getIdentifierNamespace() & Decl::IDNS_ObjCProtocol)
+           || (IDNS & Decl::IDNS_ObjCProtocol)) &&
+          I->first->getIdentifierNamespace() != IDNS)
+        continue;
+      
+      // The newly-added result is hidden by an entry in the shadow map.
+      if (CheckHiddenResult(R, CurContext, I->first))
+        return;
+      
+      break;
+    }
+  }
+  
+  // Make sure that any given declaration only shows up in the result set once.
+  if (!AllDeclsFound.insert(CanonDecl))
+    return;
+  
+  // If the filter is for nested-name-specifiers, then this result starts a
+  // nested-name-specifier.
+  if (AsNestedNameSpecifier)
+    R.StartsNestedNameSpecifier = true;
+  
+  // If this result is supposed to have an informative qualifier, add one.
+  if (R.QualifierIsInformative && !R.Qualifier &&
+      !R.StartsNestedNameSpecifier) {
+    DeclContext *Ctx = R.Declaration->getDeclContext();
+    if (NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(Ctx))
+      R.Qualifier = NestedNameSpecifier::Create(SemaRef.Context, 0, Namespace);
+    else if (TagDecl *Tag = dyn_cast<TagDecl>(Ctx))
+      R.Qualifier = NestedNameSpecifier::Create(SemaRef.Context, 0, false, 
+                             SemaRef.Context.getTypeDeclType(Tag).getTypePtr());
+    else
+      R.QualifierIsInformative = false;
+  }
+    
+  // Insert this result into the set of results and into the current shadow
+  // map.
+  SMap[R.Declaration->getDeclName()].Add(R.Declaration, Results.size());
+  Results.push_back(R);
+}
+
+void ResultBuilder::AddResult(Result R, DeclContext *CurContext, 
+                              NamedDecl *Hiding, bool InBaseClass = false) {
+  if (R.Kind != Result::RK_Declaration) {
+    // For non-declaration results, just add the result.
+    Results.push_back(R);
+    return;
+  }
+
+  // Look through using declarations.
+  if (UsingShadowDecl *Using = dyn_cast<UsingShadowDecl>(R.Declaration)) {
+    AddResult(Result(Using->getTargetDecl(), R.Qualifier), CurContext, Hiding);
+    return;
+  }
+  
+  bool AsNestedNameSpecifier = false;
+  if (!isInterestingDecl(R.Declaration, AsNestedNameSpecifier))
+    return;
+  
+  if (Hiding && CheckHiddenResult(R, CurContext, Hiding))
+    return;
+      
+  // Make sure that any given declaration only shows up in the result set once.
+  if (!AllDeclsFound.insert(R.Declaration->getCanonicalDecl()))
+    return;
+  
+  // If the filter is for nested-name-specifiers, then this result starts a
+  // nested-name-specifier.
+  if (AsNestedNameSpecifier)
+    R.StartsNestedNameSpecifier = true;
+  else if (Filter == &ResultBuilder::IsMember && !R.Qualifier && InBaseClass &&
+           isa<CXXRecordDecl>(R.Declaration->getDeclContext()
+                                                  ->getLookupContext()))
+    R.QualifierIsInformative = true;
+
+  // If this result is supposed to have an informative qualifier, add one.
+  if (R.QualifierIsInformative && !R.Qualifier &&
+      !R.StartsNestedNameSpecifier) {
+    DeclContext *Ctx = R.Declaration->getDeclContext();
+    if (NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(Ctx))
+      R.Qualifier = NestedNameSpecifier::Create(SemaRef.Context, 0, Namespace);
+    else if (TagDecl *Tag = dyn_cast<TagDecl>(Ctx))
+      R.Qualifier = NestedNameSpecifier::Create(SemaRef.Context, 0, false, 
+                            SemaRef.Context.getTypeDeclType(Tag).getTypePtr());
+    else
+      R.QualifierIsInformative = false;
+  }
+  
+  // Insert this result into the set of results.
+  Results.push_back(R);
+}
+
+void ResultBuilder::AddResult(Result R) {
+  assert(R.Kind != Result::RK_Declaration && 
+          "Declaration results need more context");
+  Results.push_back(R);
+}
+
+/// \brief Enter into a new scope.
+void ResultBuilder::EnterNewScope() {
+  ShadowMaps.push_back(ShadowMap());
+}
+
+/// \brief Exit from the current scope.
+void ResultBuilder::ExitScope() {
+  for (ShadowMap::iterator E = ShadowMaps.back().begin(),
+                        EEnd = ShadowMaps.back().end();
+       E != EEnd;
+       ++E)
+    E->second.Destroy();
+         
+  ShadowMaps.pop_back();
+}
+
+/// \brief Determines whether this given declaration will be found by
+/// ordinary name lookup.
+bool ResultBuilder::IsOrdinaryName(NamedDecl *ND) const {
+  unsigned IDNS = Decl::IDNS_Ordinary;
+  if (SemaRef.getLangOptions().CPlusPlus)
+    IDNS |= Decl::IDNS_Tag;
+  else if (SemaRef.getLangOptions().ObjC1 && isa<ObjCIvarDecl>(ND))
+    return true;
+
+  return ND->getIdentifierNamespace() & IDNS;
+}
+
+/// \brief Determines whether this given declaration will be found by
+/// ordinary name lookup.
+bool ResultBuilder::IsOrdinaryNonValueName(NamedDecl *ND) const {
+  unsigned IDNS = Decl::IDNS_Ordinary;
+  if (SemaRef.getLangOptions().CPlusPlus)
+    IDNS |= Decl::IDNS_Tag;
+  
+  return (ND->getIdentifierNamespace() & IDNS) && 
+    !isa<ValueDecl>(ND) && !isa<FunctionTemplateDecl>(ND);
+}
+
+/// \brief Determines whether the given declaration is suitable as the 
+/// start of a C++ nested-name-specifier, e.g., a class or namespace.
+bool ResultBuilder::IsNestedNameSpecifier(NamedDecl *ND) const {
+  // Allow us to find class templates, too.
+  if (ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(ND))
+    ND = ClassTemplate->getTemplatedDecl();
+  
+  return SemaRef.isAcceptableNestedNameSpecifier(ND);
+}
+
+/// \brief Determines whether the given declaration is an enumeration.
+bool ResultBuilder::IsEnum(NamedDecl *ND) const {
+  return isa<EnumDecl>(ND);
+}
+
+/// \brief Determines whether the given declaration is a class or struct.
+bool ResultBuilder::IsClassOrStruct(NamedDecl *ND) const {
+  // Allow us to find class templates, too.
+  if (ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(ND))
+    ND = ClassTemplate->getTemplatedDecl();
+  
+  if (RecordDecl *RD = dyn_cast<RecordDecl>(ND))
+    return RD->getTagKind() == TagDecl::TK_class ||
+    RD->getTagKind() == TagDecl::TK_struct;
+  
+  return false;
+}
+
+/// \brief Determines whether the given declaration is a union.
+bool ResultBuilder::IsUnion(NamedDecl *ND) const {
+  // Allow us to find class templates, too.
+  if (ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(ND))
+    ND = ClassTemplate->getTemplatedDecl();
+  
+  if (RecordDecl *RD = dyn_cast<RecordDecl>(ND))
+    return RD->getTagKind() == TagDecl::TK_union;
+  
+  return false;
+}
+
+/// \brief Determines whether the given declaration is a namespace.
+bool ResultBuilder::IsNamespace(NamedDecl *ND) const {
+  return isa<NamespaceDecl>(ND);
+}
+
+/// \brief Determines whether the given declaration is a namespace or 
+/// namespace alias.
+bool ResultBuilder::IsNamespaceOrAlias(NamedDecl *ND) const {
+  return isa<NamespaceDecl>(ND) || isa<NamespaceAliasDecl>(ND);
+}
+
+/// \brief Determines whether the given declaration is a type.
+bool ResultBuilder::IsType(NamedDecl *ND) const {
+  return isa<TypeDecl>(ND);
+}
+
+/// \brief Determines which members of a class should be visible via
+/// "." or "->".  Only value declarations, nested name specifiers, and
+/// using declarations thereof should show up.
+bool ResultBuilder::IsMember(NamedDecl *ND) const {
+  if (UsingShadowDecl *Using = dyn_cast<UsingShadowDecl>(ND))
+    ND = Using->getTargetDecl();
+
+  return isa<ValueDecl>(ND) || isa<FunctionTemplateDecl>(ND) ||
+    isa<ObjCPropertyDecl>(ND);
+}
+
+/// \rief Determines whether the given declaration is an Objective-C
+/// instance variable.
+bool ResultBuilder::IsObjCIvar(NamedDecl *ND) const {
+  return isa<ObjCIvarDecl>(ND);
+}
+
+namespace {
+  /// \brief Visible declaration consumer that adds a code-completion result
+  /// for each visible declaration.
+  class CodeCompletionDeclConsumer : public VisibleDeclConsumer {
+    ResultBuilder &Results;
+    DeclContext *CurContext;
+    
+  public:
+    CodeCompletionDeclConsumer(ResultBuilder &Results, DeclContext *CurContext)
+      : Results(Results), CurContext(CurContext) { }
+    
+    virtual void FoundDecl(NamedDecl *ND, NamedDecl *Hiding, bool InBaseClass) {
+      Results.AddResult(ND, CurContext, Hiding, InBaseClass);
+    }
+  };
+}
+
+/// \brief Add type specifiers for the current language as keyword results.
+static void AddTypeSpecifierResults(const LangOptions &LangOpts,
+                                    ResultBuilder &Results) {
+  typedef CodeCompleteConsumer::Result Result;
+  Results.AddResult(Result("short"));
+  Results.AddResult(Result("long"));
+  Results.AddResult(Result("signed"));
+  Results.AddResult(Result("unsigned"));
+  Results.AddResult(Result("void"));
+  Results.AddResult(Result("char"));
+  Results.AddResult(Result("int"));
+  Results.AddResult(Result("float"));
+  Results.AddResult(Result("double"));
+  Results.AddResult(Result("enum"));
+  Results.AddResult(Result("struct"));
+  Results.AddResult(Result("union"));
+  Results.AddResult(Result("const"));
+  Results.AddResult(Result("volatile"));
+
+  if (LangOpts.C99) {
+    // C99-specific
+    Results.AddResult(Result("_Complex"));
+    Results.AddResult(Result("_Imaginary"));
+    Results.AddResult(Result("_Bool"));
+    Results.AddResult(Result("restrict"));
+  }
+  
+  if (LangOpts.CPlusPlus) {
+    // C++-specific
+    Results.AddResult(Result("bool"));
+    Results.AddResult(Result("class"));
+    Results.AddResult(Result("wchar_t"));
+    
+    // typename qualified-id
+    CodeCompletionString *Pattern = new CodeCompletionString;
+    Pattern->AddTypedTextChunk("typename");
+    Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace);
+    Pattern->AddPlaceholderChunk("qualified-id");
+    Results.AddResult(Result(Pattern));
+
+    if (LangOpts.CPlusPlus0x) {
+      Results.AddResult(Result("auto"));
+      Results.AddResult(Result("char16_t"));
+      Results.AddResult(Result("char32_t"));
+      Results.AddResult(Result("decltype"));
+    }
+  }
+  
+  // GNU extensions
+  if (LangOpts.GNUMode) {
+    // FIXME: Enable when we actually support decimal floating point.
+    //    Results.AddResult(Result("_Decimal32"));
+    //    Results.AddResult(Result("_Decimal64"));
+    //    Results.AddResult(Result("_Decimal128"));
+    
+    CodeCompletionString *Pattern = new CodeCompletionString;
+    Pattern->AddTypedTextChunk("typeof");
+    Pattern->AddChunk(CodeCompletionString::CK_LeftParen);
+    Pattern->AddPlaceholderChunk("expression-or-type");
+    Pattern->AddChunk(CodeCompletionString::CK_RightParen);
+    Results.AddResult(Result(Pattern));
+  }
+}
+
+static void AddStorageSpecifiers(Action::CodeCompletionContext CCC,
+                                 const LangOptions &LangOpts, 
+                                 ResultBuilder &Results) {
+  typedef CodeCompleteConsumer::Result Result;
+  // Note: we don't suggest either "auto" or "register", because both
+  // are pointless as storage specifiers. Elsewhere, we suggest "auto"
+  // in C++0x as a type specifier.
+  Results.AddResult(Result("extern"));
+  Results.AddResult(Result("static"));
+}
+
+static void AddFunctionSpecifiers(Action::CodeCompletionContext CCC,
+                                  const LangOptions &LangOpts, 
+                                  ResultBuilder &Results) {
+  typedef CodeCompleteConsumer::Result Result;
+  switch (CCC) {
+  case Action::CCC_Class:
+  case Action::CCC_MemberTemplate:
+    if (LangOpts.CPlusPlus) {
+      Results.AddResult(Result("explicit"));
+      Results.AddResult(Result("friend"));
+      Results.AddResult(Result("mutable"));
+      Results.AddResult(Result("virtual"));
+    }    
+    // Fall through
+
+  case Action::CCC_ObjCInterface:
+  case Action::CCC_ObjCImplementation:
+  case Action::CCC_Namespace:
+  case Action::CCC_Template:
+    if (LangOpts.CPlusPlus || LangOpts.C99)
+      Results.AddResult(Result("inline"));
+    break;
+
+  case Action::CCC_ObjCInstanceVariableList:
+  case Action::CCC_Expression:
+  case Action::CCC_Statement:
+  case Action::CCC_ForInit:
+  case Action::CCC_Condition:
+    break;
+  }
+}
+
+static void AddObjCExpressionResults(ResultBuilder &Results, bool NeedAt);
+static void AddObjCStatementResults(ResultBuilder &Results, bool NeedAt);
+static void AddObjCVisibilityResults(const LangOptions &LangOpts,
+                                     ResultBuilder &Results,
+                                     bool NeedAt);  
+static void AddObjCImplementationResults(const LangOptions &LangOpts,
+                                         ResultBuilder &Results,
+                                         bool NeedAt);
+static void AddObjCInterfaceResults(const LangOptions &LangOpts,
+                                    ResultBuilder &Results,
+                                    bool NeedAt);
+static void AddObjCTopLevelResults(ResultBuilder &Results, bool NeedAt);
+
+/// \brief Add language constructs that show up for "ordinary" names.
+static void AddOrdinaryNameResults(Action::CodeCompletionContext CCC,
+                                   Scope *S,
+                                   Sema &SemaRef,
+                                   ResultBuilder &Results) {
+  typedef CodeCompleteConsumer::Result Result;
+  switch (CCC) {
+  case Action::CCC_Namespace:
+    if (SemaRef.getLangOptions().CPlusPlus) {
+      // namespace <identifier> { }
+      CodeCompletionString *Pattern = new CodeCompletionString;
+      Pattern->AddTypedTextChunk("namespace");
+      Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace);
+      Pattern->AddPlaceholderChunk("identifier");
+      Pattern->AddChunk(CodeCompletionString::CK_LeftBrace);
+      Pattern->AddPlaceholderChunk("declarations");
+      Pattern->AddChunk(CodeCompletionString::CK_VerticalSpace);
+      Pattern->AddChunk(CodeCompletionString::CK_RightBrace);
+      Results.AddResult(Result(Pattern));
+
+      // namespace identifier = identifier ;
+      Pattern = new CodeCompletionString;
+      Pattern->AddTypedTextChunk("namespace");
+      Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace);
+      Pattern->AddPlaceholderChunk("identifier");
+      Pattern->AddChunk(CodeCompletionString::CK_Equal);
+      Pattern->AddPlaceholderChunk("identifier");
+      Pattern->AddChunk(CodeCompletionString::CK_SemiColon);
+      Results.AddResult(Result(Pattern));
+
+      // Using directives
+      Pattern = new CodeCompletionString;
+      Pattern->AddTypedTextChunk("using");
+      Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace);
+      Pattern->AddTextChunk("namespace");
+      Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace);
+      Pattern->AddPlaceholderChunk("identifier");
+      Pattern->AddChunk(CodeCompletionString::CK_SemiColon);
+      Results.AddResult(Result(Pattern));
+
+      // asm(string-literal)      
+      Pattern = new CodeCompletionString;
+      Pattern->AddTypedTextChunk("asm");
+      Pattern->AddChunk(CodeCompletionString::CK_LeftParen);
+      Pattern->AddPlaceholderChunk("string-literal");
+      Pattern->AddChunk(CodeCompletionString::CK_RightParen);
+      Pattern->AddChunk(CodeCompletionString::CK_SemiColon);
+      Results.AddResult(Result(Pattern));
+
+      // Explicit template instantiation
+      Pattern = new CodeCompletionString;
+      Pattern->AddTypedTextChunk("template");
+      Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace);
+      Pattern->AddPlaceholderChunk("declaration");
+      Pattern->AddChunk(CodeCompletionString::CK_SemiColon);
+      Results.AddResult(Result(Pattern));
+    }
+      
+    if (SemaRef.getLangOptions().ObjC1)
+      AddObjCTopLevelResults(Results, true);
+      
+    // Fall through
+
+  case Action::CCC_Class:
+    Results.AddResult(Result("typedef"));
+    if (SemaRef.getLangOptions().CPlusPlus) {
+      // Using declaration
+      CodeCompletionString *Pattern = new CodeCompletionString;
+      Pattern->AddTypedTextChunk("using");
+      Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace);
+      Pattern->AddPlaceholderChunk("qualified-id");
+      Pattern->AddChunk(CodeCompletionString::CK_SemiColon);
+      Results.AddResult(Result(Pattern));
+      
+      // using typename qualified-id; (only in a dependent context)
+      if (SemaRef.CurContext->isDependentContext()) {
+        Pattern = new CodeCompletionString;
+        Pattern->AddTypedTextChunk("using");
+        Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace);
+        Pattern->AddTextChunk("typename");
+        Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace);
+        Pattern->AddPlaceholderChunk("qualified-id");
+        Pattern->AddChunk(CodeCompletionString::CK_SemiColon);
+        Results.AddResult(Result(Pattern));
+      }
+
+      if (CCC == Action::CCC_Class) {
+        // public:
+        Pattern = new CodeCompletionString;
+        Pattern->AddTypedTextChunk("public");
+        Pattern->AddChunk(CodeCompletionString::CK_Colon);
+        Results.AddResult(Result(Pattern));
+
+        // protected:
+        Pattern = new CodeCompletionString;
+        Pattern->AddTypedTextChunk("protected");
+        Pattern->AddChunk(CodeCompletionString::CK_Colon);
+        Results.AddResult(Result(Pattern));
+
+        // private:
+        Pattern = new CodeCompletionString;
+        Pattern->AddTypedTextChunk("private");
+        Pattern->AddChunk(CodeCompletionString::CK_Colon);
+        Results.AddResult(Result(Pattern));
+      }
+    }
+    // Fall through
+
+  case Action::CCC_Template:
+  case Action::CCC_MemberTemplate:
+    if (SemaRef.getLangOptions().CPlusPlus) {
+      // template < parameters >
+      CodeCompletionString *Pattern = new CodeCompletionString;
+      Pattern->AddTypedTextChunk("template");
+      Pattern->AddChunk(CodeCompletionString::CK_LeftAngle);
+      Pattern->AddPlaceholderChunk("parameters");
+      Pattern->AddChunk(CodeCompletionString::CK_RightAngle);
+      Results.AddResult(Result(Pattern));
+    }
+
+    AddStorageSpecifiers(CCC, SemaRef.getLangOptions(), Results);
+    AddFunctionSpecifiers(CCC, SemaRef.getLangOptions(), Results);
+    break;
+
+  case Action::CCC_ObjCInterface:
+    AddObjCInterfaceResults(SemaRef.getLangOptions(), Results, true);
+    AddStorageSpecifiers(CCC, SemaRef.getLangOptions(), Results);
+    AddFunctionSpecifiers(CCC, SemaRef.getLangOptions(), Results);
+    break;
+      
+  case Action::CCC_ObjCImplementation:
+    AddObjCImplementationResults(SemaRef.getLangOptions(), Results, true);
+    AddStorageSpecifiers(CCC, SemaRef.getLangOptions(), Results);
+    AddFunctionSpecifiers(CCC, SemaRef.getLangOptions(), Results);
+    break;
+      
+  case Action::CCC_ObjCInstanceVariableList:
+    AddObjCVisibilityResults(SemaRef.getLangOptions(), Results, true);
+    break;
+      
+  case Action::CCC_Statement: {
+    Results.AddResult(Result("typedef"));
+
+    CodeCompletionString *Pattern = 0;
+    if (SemaRef.getLangOptions().CPlusPlus) {
+      Pattern = new CodeCompletionString;
+      Pattern->AddTypedTextChunk("try");
+      Pattern->AddChunk(CodeCompletionString::CK_LeftBrace);
+      Pattern->AddPlaceholderChunk("statements");
+      Pattern->AddChunk(CodeCompletionString::CK_VerticalSpace);
+      Pattern->AddChunk(CodeCompletionString::CK_RightBrace);
+      Pattern->AddTextChunk("catch");
+      Pattern->AddChunk(CodeCompletionString::CK_LeftParen);
+      Pattern->AddPlaceholderChunk("declaration");
+      Pattern->AddChunk(CodeCompletionString::CK_RightParen);
+      Pattern->AddChunk(CodeCompletionString::CK_LeftBrace);
+      Pattern->AddPlaceholderChunk("statements");
+      Pattern->AddChunk(CodeCompletionString::CK_VerticalSpace);
+      Pattern->AddChunk(CodeCompletionString::CK_RightBrace);
+      Results.AddResult(Result(Pattern));
+    }
+    if (SemaRef.getLangOptions().ObjC1)
+      AddObjCStatementResults(Results, true);
+    
+    // if (condition) { statements }
+    Pattern = new CodeCompletionString;
+    Pattern->AddTypedTextChunk("if");
+    Pattern->AddChunk(CodeCompletionString::CK_LeftParen);
+    if (SemaRef.getLangOptions().CPlusPlus)
+      Pattern->AddPlaceholderChunk("condition");
+    else
+      Pattern->AddPlaceholderChunk("expression");
+    Pattern->AddChunk(CodeCompletionString::CK_RightParen);
+    Pattern->AddChunk(CodeCompletionString::CK_LeftBrace);
+    Pattern->AddPlaceholderChunk("statements");
+    Pattern->AddChunk(CodeCompletionString::CK_VerticalSpace);
+    Pattern->AddChunk(CodeCompletionString::CK_RightBrace);
+    Results.AddResult(Result(Pattern));
+
+    // switch (condition) { }
+    Pattern = new CodeCompletionString;
+    Pattern->AddTypedTextChunk("switch");
+    Pattern->AddChunk(CodeCompletionString::CK_LeftParen);
+    if (SemaRef.getLangOptions().CPlusPlus)
+      Pattern->AddPlaceholderChunk("condition");
+    else
+      Pattern->AddPlaceholderChunk("expression");
+    Pattern->AddChunk(CodeCompletionString::CK_RightParen);
+    Pattern->AddChunk(CodeCompletionString::CK_LeftBrace);
+    Pattern->AddChunk(CodeCompletionString::CK_VerticalSpace);
+    Pattern->AddChunk(CodeCompletionString::CK_RightBrace);
+    Results.AddResult(Result(Pattern));
+
+    // Switch-specific statements.
+    if (!SemaRef.getSwitchStack().empty()) {
+      // case expression:
+      Pattern = new CodeCompletionString;
+      Pattern->AddTypedTextChunk("case");
+      Pattern->AddPlaceholderChunk("expression");
+      Pattern->AddChunk(CodeCompletionString::CK_Colon);
+      Results.AddResult(Result(Pattern));
+
+      // default:
+      Pattern = new CodeCompletionString;
+      Pattern->AddTypedTextChunk("default");
+      Pattern->AddChunk(CodeCompletionString::CK_Colon);
+      Results.AddResult(Result(Pattern));
+    }
+
+    /// while (condition) { statements }
+    Pattern = new CodeCompletionString;
+    Pattern->AddTypedTextChunk("while");
+    Pattern->AddChunk(CodeCompletionString::CK_LeftParen);
+    if (SemaRef.getLangOptions().CPlusPlus)
+      Pattern->AddPlaceholderChunk("condition");
+    else
+      Pattern->AddPlaceholderChunk("expression");
+    Pattern->AddChunk(CodeCompletionString::CK_RightParen);
+    Pattern->AddChunk(CodeCompletionString::CK_LeftBrace);
+    Pattern->AddPlaceholderChunk("statements");
+    Pattern->AddChunk(CodeCompletionString::CK_VerticalSpace);
+    Pattern->AddChunk(CodeCompletionString::CK_RightBrace);
+    Results.AddResult(Result(Pattern));
+
+    // do { statements } while ( expression );
+    Pattern = new CodeCompletionString;
+    Pattern->AddTypedTextChunk("do");
+    Pattern->AddChunk(CodeCompletionString::CK_LeftBrace);
+    Pattern->AddPlaceholderChunk("statements");
+    Pattern->AddChunk(CodeCompletionString::CK_VerticalSpace);
+    Pattern->AddChunk(CodeCompletionString::CK_RightBrace);
+    Pattern->AddTextChunk("while");
+    Pattern->AddChunk(CodeCompletionString::CK_LeftParen);
+    Pattern->AddPlaceholderChunk("expression");
+    Pattern->AddChunk(CodeCompletionString::CK_RightParen);
+    Pattern->AddChunk(CodeCompletionString::CK_SemiColon);
+    Results.AddResult(Result(Pattern));
+
+    // for ( for-init-statement ; condition ; expression ) { statements }
+    Pattern = new CodeCompletionString;
+    Pattern->AddTypedTextChunk("for");
+    Pattern->AddChunk(CodeCompletionString::CK_LeftParen);
+    if (SemaRef.getLangOptions().CPlusPlus || SemaRef.getLangOptions().C99)
+      Pattern->AddPlaceholderChunk("init-statement");
+    else
+      Pattern->AddPlaceholderChunk("init-expression");
+    Pattern->AddChunk(CodeCompletionString::CK_SemiColon);
+    Pattern->AddPlaceholderChunk("condition");
+    Pattern->AddChunk(CodeCompletionString::CK_SemiColon);
+    Pattern->AddPlaceholderChunk("inc-expression");
+    Pattern->AddChunk(CodeCompletionString::CK_RightParen);
+    Pattern->AddChunk(CodeCompletionString::CK_LeftBrace);
+    Pattern->AddPlaceholderChunk("statements");
+    Pattern->AddChunk(CodeCompletionString::CK_VerticalSpace);
+    Pattern->AddChunk(CodeCompletionString::CK_RightBrace);
+    Results.AddResult(Result(Pattern));
+    
+    if (S->getContinueParent()) {
+      // continue ;
+      Pattern = new CodeCompletionString;
+      Pattern->AddTypedTextChunk("continue");
+      Pattern->AddChunk(CodeCompletionString::CK_SemiColon);
+      Results.AddResult(Result(Pattern));
+    }
+
+    if (S->getBreakParent()) {
+      // break ;
+      Pattern = new CodeCompletionString;
+      Pattern->AddTypedTextChunk("break");
+      Pattern->AddChunk(CodeCompletionString::CK_SemiColon);
+      Results.AddResult(Result(Pattern));
+    }
+
+    // "return expression ;" or "return ;", depending on whether we
+    // know the function is void or not.
+    bool isVoid = false;
+    if (FunctionDecl *Function = dyn_cast<FunctionDecl>(SemaRef.CurContext))
+      isVoid = Function->getResultType()->isVoidType();
+    else if (ObjCMethodDecl *Method
+                                 = dyn_cast<ObjCMethodDecl>(SemaRef.CurContext))
+      isVoid = Method->getResultType()->isVoidType();
+    else if (SemaRef.CurBlock && !SemaRef.CurBlock->ReturnType.isNull())
+      isVoid = SemaRef.CurBlock->ReturnType->isVoidType();
+    Pattern = new CodeCompletionString;
+    Pattern->AddTypedTextChunk("return");
+    if (!isVoid)
+      Pattern->AddPlaceholderChunk("expression");
+    Pattern->AddChunk(CodeCompletionString::CK_SemiColon);
+    Results.AddResult(Result(Pattern));
+
+    // goto identifier ;
+    Pattern = new CodeCompletionString;
+    Pattern->AddTypedTextChunk("goto");
+    Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace);
+    Pattern->AddPlaceholderChunk("identifier");
+    Pattern->AddChunk(CodeCompletionString::CK_SemiColon);
+    Results.AddResult(Result(Pattern));    
+
+    // Using directives
+    Pattern = new CodeCompletionString;
+    Pattern->AddTypedTextChunk("using");
+    Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace);
+    Pattern->AddTextChunk("namespace");
+    Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace);
+    Pattern->AddPlaceholderChunk("identifier");
+    Pattern->AddChunk(CodeCompletionString::CK_SemiColon);
+    Results.AddResult(Result(Pattern));
+  }
+
+  // Fall through (for statement expressions).
+  case Action::CCC_ForInit:
+  case Action::CCC_Condition:
+    AddStorageSpecifiers(CCC, SemaRef.getLangOptions(), Results);
+    // Fall through: conditions and statements can have expressions.
+
+  case Action::CCC_Expression: {
+    CodeCompletionString *Pattern = 0;
+    if (SemaRef.getLangOptions().CPlusPlus) {
+      // 'this', if we're in a non-static member function.
+      if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(SemaRef.CurContext))
+        if (!Method->isStatic())
+          Results.AddResult(Result("this"));
+      
+      // true, false
+      Results.AddResult(Result("true"));
+      Results.AddResult(Result("false"));
+
+      // dynamic_cast < type-id > ( expression )
+      Pattern = new CodeCompletionString;
+      Pattern->AddTypedTextChunk("dynamic_cast");
+      Pattern->AddChunk(CodeCompletionString::CK_LeftAngle);
+      Pattern->AddPlaceholderChunk("type-id");
+      Pattern->AddChunk(CodeCompletionString::CK_RightAngle);
+      Pattern->AddChunk(CodeCompletionString::CK_LeftParen);
+      Pattern->AddPlaceholderChunk("expression");
+      Pattern->AddChunk(CodeCompletionString::CK_RightParen);
+      Results.AddResult(Result(Pattern));      
+      
+      // static_cast < type-id > ( expression )
+      Pattern = new CodeCompletionString;
+      Pattern->AddTypedTextChunk("static_cast");
+      Pattern->AddChunk(CodeCompletionString::CK_LeftAngle);
+      Pattern->AddPlaceholderChunk("type-id");
+      Pattern->AddChunk(CodeCompletionString::CK_RightAngle);
+      Pattern->AddChunk(CodeCompletionString::CK_LeftParen);
+      Pattern->AddPlaceholderChunk("expression");
+      Pattern->AddChunk(CodeCompletionString::CK_RightParen);
+      Results.AddResult(Result(Pattern));      
+
+      // reinterpret_cast < type-id > ( expression )
+      Pattern = new CodeCompletionString;
+      Pattern->AddTypedTextChunk("reinterpret_cast");
+      Pattern->AddChunk(CodeCompletionString::CK_LeftAngle);
+      Pattern->AddPlaceholderChunk("type-id");
+      Pattern->AddChunk(CodeCompletionString::CK_RightAngle);
+      Pattern->AddChunk(CodeCompletionString::CK_LeftParen);
+      Pattern->AddPlaceholderChunk("expression");
+      Pattern->AddChunk(CodeCompletionString::CK_RightParen);
+      Results.AddResult(Result(Pattern));      
+
+      // const_cast < type-id > ( expression )
+      Pattern = new CodeCompletionString;
+      Pattern->AddTypedTextChunk("const_cast");
+      Pattern->AddChunk(CodeCompletionString::CK_LeftAngle);
+      Pattern->AddPlaceholderChunk("type-id");
+      Pattern->AddChunk(CodeCompletionString::CK_RightAngle);
+      Pattern->AddChunk(CodeCompletionString::CK_LeftParen);
+      Pattern->AddPlaceholderChunk("expression");
+      Pattern->AddChunk(CodeCompletionString::CK_RightParen);
+      Results.AddResult(Result(Pattern));      
+
+      // typeid ( expression-or-type )
+      Pattern = new CodeCompletionString;
+      Pattern->AddTypedTextChunk("typeid");
+      Pattern->AddChunk(CodeCompletionString::CK_LeftParen);
+      Pattern->AddPlaceholderChunk("expression-or-type");
+      Pattern->AddChunk(CodeCompletionString::CK_RightParen);
+      Results.AddResult(Result(Pattern));      
+
+      // new T ( ... )
+      Pattern = new CodeCompletionString;
+      Pattern->AddTypedTextChunk("new");
+      Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace);
+      Pattern->AddPlaceholderChunk("type-id");
+      Pattern->AddChunk(CodeCompletionString::CK_LeftParen);
+      Pattern->AddPlaceholderChunk("expressions");
+      Pattern->AddChunk(CodeCompletionString::CK_RightParen);
+      Results.AddResult(Result(Pattern));      
+
+      // new T [ ] ( ... )
+      Pattern = new CodeCompletionString;
+      Pattern->AddTypedTextChunk("new");
+      Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace);
+      Pattern->AddPlaceholderChunk("type-id");
+      Pattern->AddChunk(CodeCompletionString::CK_LeftBracket);
+      Pattern->AddPlaceholderChunk("size");
+      Pattern->AddChunk(CodeCompletionString::CK_RightBracket);
+      Pattern->AddChunk(CodeCompletionString::CK_LeftParen);
+      Pattern->AddPlaceholderChunk("expressions");
+      Pattern->AddChunk(CodeCompletionString::CK_RightParen);
+      Results.AddResult(Result(Pattern));      
+
+      // delete expression
+      Pattern = new CodeCompletionString;
+      Pattern->AddTypedTextChunk("delete");
+      Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace);
+      Pattern->AddPlaceholderChunk("expression");
+      Results.AddResult(Result(Pattern));      
+
+      // delete [] expression
+      Pattern = new CodeCompletionString;
+      Pattern->AddTypedTextChunk("delete");
+      Pattern->AddChunk(CodeCompletionString::CK_LeftBracket);
+      Pattern->AddChunk(CodeCompletionString::CK_RightBracket);
+      Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace);
+      Pattern->AddPlaceholderChunk("expression");
+      Results.AddResult(Result(Pattern));
+
+      // throw expression
+      Pattern = new CodeCompletionString;
+      Pattern->AddTypedTextChunk("throw");
+      Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace);
+      Pattern->AddPlaceholderChunk("expression");
+      Results.AddResult(Result(Pattern));
+    }
+
+    if (SemaRef.getLangOptions().ObjC1) {
+      // Add "super", if we're in an Objective-C class with a superclass.
+      if (ObjCMethodDecl *Method = SemaRef.getCurMethodDecl())
+        if (Method->getClassInterface()->getSuperClass())
+          Results.AddResult(Result("super"));
+      
+      AddObjCExpressionResults(Results, true);
+    }
+
+    // sizeof expression
+    Pattern = new CodeCompletionString;
+    Pattern->AddTypedTextChunk("sizeof");
+    Pattern->AddChunk(CodeCompletionString::CK_LeftParen);
+    Pattern->AddPlaceholderChunk("expression-or-type");
+    Pattern->AddChunk(CodeCompletionString::CK_RightParen);
+    Results.AddResult(Result(Pattern));
+    break;
+  }
+  }
+
+  AddTypeSpecifierResults(SemaRef.getLangOptions(), Results);
+
+  if (SemaRef.getLangOptions().CPlusPlus)
+    Results.AddResult(Result("operator"));
+}
+
+/// \brief If the given declaration has an associated type, add it as a result 
+/// type chunk.
+static void AddResultTypeChunk(ASTContext &Context,
+                               NamedDecl *ND,
+                               CodeCompletionString *Result) {
+  if (!ND)
+    return;
+  
+  // Determine the type of the declaration (if it has a type).
+  QualType T;
+  if (FunctionDecl *Function = dyn_cast<FunctionDecl>(ND))
+    T = Function->getResultType();
+  else if (ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(ND))
+    T = Method->getResultType();
+  else if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(ND))
+    T = FunTmpl->getTemplatedDecl()->getResultType();
+  else if (EnumConstantDecl *Enumerator = dyn_cast<EnumConstantDecl>(ND))
+    T = Context.getTypeDeclType(cast<TypeDecl>(Enumerator->getDeclContext()));
+  else if (isa<UnresolvedUsingValueDecl>(ND)) {
+    /* Do nothing: ignore unresolved using declarations*/
+  } else if (ValueDecl *Value = dyn_cast<ValueDecl>(ND))
+    T = Value->getType();
+  else if (ObjCPropertyDecl *Property = dyn_cast<ObjCPropertyDecl>(ND))
+    T = Property->getType();
+  
+  if (T.isNull() || Context.hasSameType(T, Context.DependentTy))
+    return;
+  
+  std::string TypeStr;
+  T.getAsStringInternal(TypeStr, Context.PrintingPolicy);
+  Result->AddResultTypeChunk(TypeStr);
+}
+
+/// \brief Add function parameter chunks to the given code completion string.
+static void AddFunctionParameterChunks(ASTContext &Context,
+                                       FunctionDecl *Function,
+                                       CodeCompletionString *Result) {
+  typedef CodeCompletionString::Chunk Chunk;
+  
+  CodeCompletionString *CCStr = Result;
+  
+  for (unsigned P = 0, N = Function->getNumParams(); P != N; ++P) {
+    ParmVarDecl *Param = Function->getParamDecl(P);
+    
+    if (Param->hasDefaultArg()) {
+      // When we see an optional default argument, put that argument and
+      // the remaining default arguments into a new, optional string.
+      CodeCompletionString *Opt = new CodeCompletionString;
+      CCStr->AddOptionalChunk(std::auto_ptr<CodeCompletionString>(Opt));
+      CCStr = Opt;
+    }
+    
+    if (P != 0)
+      CCStr->AddChunk(Chunk(CodeCompletionString::CK_Comma));
+    
+    // Format the placeholder string.
+    std::string PlaceholderStr;
+    if (Param->getIdentifier())
+      PlaceholderStr = Param->getIdentifier()->getName();
+    
+    Param->getType().getAsStringInternal(PlaceholderStr, 
+                                         Context.PrintingPolicy);
+    
+    // Add the placeholder string.
+    CCStr->AddPlaceholderChunk(PlaceholderStr);
+  }
+  
+  if (const FunctionProtoType *Proto 
+        = Function->getType()->getAs<FunctionProtoType>())
+    if (Proto->isVariadic())
+      CCStr->AddPlaceholderChunk(", ...");
+}
+
+/// \brief Add template parameter chunks to the given code completion string.
+static void AddTemplateParameterChunks(ASTContext &Context,
+                                       TemplateDecl *Template,
+                                       CodeCompletionString *Result,
+                                       unsigned MaxParameters = 0) {
+  typedef CodeCompletionString::Chunk Chunk;
+  
+  CodeCompletionString *CCStr = Result;
+  bool FirstParameter = true;
+  
+  TemplateParameterList *Params = Template->getTemplateParameters();
+  TemplateParameterList::iterator PEnd = Params->end();
+  if (MaxParameters)
+    PEnd = Params->begin() + MaxParameters;
+  for (TemplateParameterList::iterator P = Params->begin(); P != PEnd; ++P) {
+    bool HasDefaultArg = false;
+    std::string PlaceholderStr;
+    if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(*P)) {
+      if (TTP->wasDeclaredWithTypename())
+        PlaceholderStr = "typename";
+      else
+        PlaceholderStr = "class";
+      
+      if (TTP->getIdentifier()) {
+        PlaceholderStr += ' ';
+        PlaceholderStr += TTP->getIdentifier()->getName();
+      }
+      
+      HasDefaultArg = TTP->hasDefaultArgument();
+    } else if (NonTypeTemplateParmDecl *NTTP 
+               = dyn_cast<NonTypeTemplateParmDecl>(*P)) {
+      if (NTTP->getIdentifier())
+        PlaceholderStr = NTTP->getIdentifier()->getName();
+      NTTP->getType().getAsStringInternal(PlaceholderStr, 
+                                          Context.PrintingPolicy);
+      HasDefaultArg = NTTP->hasDefaultArgument();
+    } else {
+      assert(isa<TemplateTemplateParmDecl>(*P));
+      TemplateTemplateParmDecl *TTP = cast<TemplateTemplateParmDecl>(*P);
+      
+      // Since putting the template argument list into the placeholder would
+      // be very, very long, we just use an abbreviation.
+      PlaceholderStr = "template<...> class";
+      if (TTP->getIdentifier()) {
+        PlaceholderStr += ' ';
+        PlaceholderStr += TTP->getIdentifier()->getName();
+      }
+      
+      HasDefaultArg = TTP->hasDefaultArgument();
+    }
+    
+    if (HasDefaultArg) {
+      // When we see an optional default argument, put that argument and
+      // the remaining default arguments into a new, optional string.
+      CodeCompletionString *Opt = new CodeCompletionString;
+      CCStr->AddOptionalChunk(std::auto_ptr<CodeCompletionString>(Opt));
+      CCStr = Opt;
+    }
+    
+    if (FirstParameter)
+      FirstParameter = false;
+    else
+      CCStr->AddChunk(Chunk(CodeCompletionString::CK_Comma));
+    
+    // Add the placeholder string.
+    CCStr->AddPlaceholderChunk(PlaceholderStr);
+  }    
+}
+
+/// \brief Add a qualifier to the given code-completion string, if the
+/// provided nested-name-specifier is non-NULL.
+static void 
+AddQualifierToCompletionString(CodeCompletionString *Result, 
+                               NestedNameSpecifier *Qualifier, 
+                               bool QualifierIsInformative,
+                               ASTContext &Context) {
+  if (!Qualifier)
+    return;
+  
+  std::string PrintedNNS;
+  {
+    llvm::raw_string_ostream OS(PrintedNNS);
+    Qualifier->print(OS, Context.PrintingPolicy);
+  }
+  if (QualifierIsInformative)
+    Result->AddInformativeChunk(PrintedNNS);
+  else
+    Result->AddTextChunk(PrintedNNS);
+}
+
+static void AddFunctionTypeQualsToCompletionString(CodeCompletionString *Result,
+                                                   FunctionDecl *Function) {
+  const FunctionProtoType *Proto
+    = Function->getType()->getAs<FunctionProtoType>();
+  if (!Proto || !Proto->getTypeQuals())
+    return;
+
+  std::string QualsStr;
+  if (Proto->getTypeQuals() & Qualifiers::Const)
+    QualsStr += " const";
+  if (Proto->getTypeQuals() & Qualifiers::Volatile)
+    QualsStr += " volatile";
+  if (Proto->getTypeQuals() & Qualifiers::Restrict)
+    QualsStr += " restrict";
+  Result->AddInformativeChunk(QualsStr);
+}
+
+/// \brief If possible, create a new code completion string for the given
+/// result.
+///
+/// \returns Either a new, heap-allocated code completion string describing
+/// how to use this result, or NULL to indicate that the string or name of the
+/// result is all that is needed.
+CodeCompletionString *
+CodeCompleteConsumer::Result::CreateCodeCompletionString(Sema &S) {
+  typedef CodeCompletionString::Chunk Chunk;
+  
+  if (Kind == RK_Pattern)
+    return Pattern->Clone();
+  
+  CodeCompletionString *Result = new CodeCompletionString;
+
+  if (Kind == RK_Keyword) {
+    Result->AddTypedTextChunk(Keyword);
+    return Result;
+  }
+  
+  if (Kind == RK_Macro) {
+    MacroInfo *MI = S.PP.getMacroInfo(Macro);
+    assert(MI && "Not a macro?");
+
+    Result->AddTypedTextChunk(Macro->getName());
+
+    if (!MI->isFunctionLike())
+      return Result;
+    
+    // Format a function-like macro with placeholders for the arguments.
+    Result->AddChunk(Chunk(CodeCompletionString::CK_LeftParen));
+    for (MacroInfo::arg_iterator A = MI->arg_begin(), AEnd = MI->arg_end();
+         A != AEnd; ++A) {
+      if (A != MI->arg_begin())
+        Result->AddChunk(Chunk(CodeCompletionString::CK_Comma));
+      
+      if (!MI->isVariadic() || A != AEnd - 1) {
+        // Non-variadic argument.
+        Result->AddPlaceholderChunk((*A)->getName());
+        continue;
+      }
+      
+      // Variadic argument; cope with the different between GNU and C99
+      // variadic macros, providing a single placeholder for the rest of the
+      // arguments.
+      if ((*A)->isStr("__VA_ARGS__"))
+        Result->AddPlaceholderChunk("...");
+      else {
+        std::string Arg = (*A)->getName();
+        Arg += "...";
+        Result->AddPlaceholderChunk(Arg);
+      }
+    }
+    Result->AddChunk(Chunk(CodeCompletionString::CK_RightParen));
+    return Result;
+  }
+  
+  assert(Kind == RK_Declaration && "Missed a macro kind?");
+  NamedDecl *ND = Declaration;
+  
+  if (StartsNestedNameSpecifier) {
+    Result->AddTypedTextChunk(ND->getNameAsString());
+    Result->AddTextChunk("::");
+    return Result;
+  }
+  
+  AddResultTypeChunk(S.Context, ND, Result);
+  
+  if (FunctionDecl *Function = dyn_cast<FunctionDecl>(ND)) {
+    AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative, 
+                                   S.Context);
+    Result->AddTypedTextChunk(Function->getNameAsString());
+    Result->AddChunk(Chunk(CodeCompletionString::CK_LeftParen));
+    AddFunctionParameterChunks(S.Context, Function, Result);
+    Result->AddChunk(Chunk(CodeCompletionString::CK_RightParen));
+    AddFunctionTypeQualsToCompletionString(Result, Function);
+    return Result;
+  }
+  
+  if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(ND)) {
+    AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative, 
+                                   S.Context);
+    FunctionDecl *Function = FunTmpl->getTemplatedDecl();
+    Result->AddTypedTextChunk(Function->getNameAsString());
+    
+    // Figure out which template parameters are deduced (or have default
+    // arguments).
+    llvm::SmallVector<bool, 16> Deduced;
+    S.MarkDeducedTemplateParameters(FunTmpl, Deduced);
+    unsigned LastDeducibleArgument;
+    for (LastDeducibleArgument = Deduced.size(); LastDeducibleArgument > 0;
+         --LastDeducibleArgument) {
+      if (!Deduced[LastDeducibleArgument - 1]) {
+        // C++0x: Figure out if the template argument has a default. If so,
+        // the user doesn't need to type this argument.
+        // FIXME: We need to abstract template parameters better!
+        bool HasDefaultArg = false;
+        NamedDecl *Param = FunTmpl->getTemplateParameters()->getParam(
+                                                                      LastDeducibleArgument - 1);
+        if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(Param))
+          HasDefaultArg = TTP->hasDefaultArgument();
+        else if (NonTypeTemplateParmDecl *NTTP 
+                 = dyn_cast<NonTypeTemplateParmDecl>(Param))
+          HasDefaultArg = NTTP->hasDefaultArgument();
+        else {
+          assert(isa<TemplateTemplateParmDecl>(Param));
+          HasDefaultArg 
+            = cast<TemplateTemplateParmDecl>(Param)->hasDefaultArgument();
+        }
+        
+        if (!HasDefaultArg)
+          break;
+      }
+    }
+    
+    if (LastDeducibleArgument) {
+      // Some of the function template arguments cannot be deduced from a
+      // function call, so we introduce an explicit template argument list
+      // containing all of the arguments up to the first deducible argument.
+      Result->AddChunk(Chunk(CodeCompletionString::CK_LeftAngle));
+      AddTemplateParameterChunks(S.Context, FunTmpl, Result, 
+                                 LastDeducibleArgument);
+      Result->AddChunk(Chunk(CodeCompletionString::CK_RightAngle));
+    }
+    
+    // Add the function parameters
+    Result->AddChunk(Chunk(CodeCompletionString::CK_LeftParen));
+    AddFunctionParameterChunks(S.Context, Function, Result);
+    Result->AddChunk(Chunk(CodeCompletionString::CK_RightParen));
+    AddFunctionTypeQualsToCompletionString(Result, Function);
+    return Result;
+  }
+  
+  if (TemplateDecl *Template = dyn_cast<TemplateDecl>(ND)) {
+    AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative, 
+                                   S.Context);
+    Result->AddTypedTextChunk(Template->getNameAsString());
+    Result->AddChunk(Chunk(CodeCompletionString::CK_LeftAngle));
+    AddTemplateParameterChunks(S.Context, Template, Result);
+    Result->AddChunk(Chunk(CodeCompletionString::CK_RightAngle));
+    return Result;
+  }
+  
+  if (ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(ND)) {
+    Selector Sel = Method->getSelector();
+    if (Sel.isUnarySelector()) {
+      Result->AddTypedTextChunk(Sel.getIdentifierInfoForSlot(0)->getName());
+      return Result;
+    }
+
+    std::string SelName = Sel.getIdentifierInfoForSlot(0)->getName().str();
+    SelName += ':';
+    if (StartParameter == 0)
+      Result->AddTypedTextChunk(SelName);
+    else {
+      Result->AddInformativeChunk(SelName);
+      
+      // If there is only one parameter, and we're past it, add an empty
+      // typed-text chunk since there is nothing to type.
+      if (Method->param_size() == 1)
+        Result->AddTypedTextChunk("");
+    }
+    unsigned Idx = 0;
+    for (ObjCMethodDecl::param_iterator P = Method->param_begin(),
+                                     PEnd = Method->param_end();
+         P != PEnd; (void)++P, ++Idx) {
+      if (Idx > 0) {
+        std::string Keyword;
+        if (Idx > StartParameter)
+          Result->AddChunk(CodeCompletionString::CK_HorizontalSpace);
+        if (IdentifierInfo *II = Sel.getIdentifierInfoForSlot(Idx))
+          Keyword += II->getName().str();
+        Keyword += ":";
+        if (Idx < StartParameter || AllParametersAreInformative) {
+          Result->AddInformativeChunk(Keyword);
+        } else if (Idx == StartParameter)
+          Result->AddTypedTextChunk(Keyword);
+        else
+          Result->AddTextChunk(Keyword);
+      }
+      
+      // If we're before the starting parameter, skip the placeholder.
+      if (Idx < StartParameter)
+        continue;
+
+      std::string Arg;
+      (*P)->getType().getAsStringInternal(Arg, S.Context.PrintingPolicy);
+      Arg = "(" + Arg + ")";
+      if (IdentifierInfo *II = (*P)->getIdentifier())
+        Arg += II->getName().str();
+      if (AllParametersAreInformative)
+        Result->AddInformativeChunk(Arg);
+      else
+        Result->AddPlaceholderChunk(Arg);
+    }
+
+    if (Method->isVariadic()) {
+      if (AllParametersAreInformative)
+        Result->AddInformativeChunk(", ...");
+      else
+        Result->AddPlaceholderChunk(", ...");
+    }
+    
+    return Result;
+  }
+
+  if (Qualifier)
+    AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative, 
+                                   S.Context);
+
+  Result->AddTypedTextChunk(ND->getNameAsString());
+  return Result;
+}
+
+CodeCompletionString *
+CodeCompleteConsumer::OverloadCandidate::CreateSignatureString(
+                                                          unsigned CurrentArg,
+                                                               Sema &S) const {
+  typedef CodeCompletionString::Chunk Chunk;
+  
+  CodeCompletionString *Result = new CodeCompletionString;
+  FunctionDecl *FDecl = getFunction();
+  AddResultTypeChunk(S.Context, FDecl, Result);
+  const FunctionProtoType *Proto 
+    = dyn_cast<FunctionProtoType>(getFunctionType());
+  if (!FDecl && !Proto) {
+    // Function without a prototype. Just give the return type and a 
+    // highlighted ellipsis.
+    const FunctionType *FT = getFunctionType();
+    Result->AddTextChunk(
+            FT->getResultType().getAsString(S.Context.PrintingPolicy));
+    Result->AddChunk(Chunk(CodeCompletionString::CK_LeftParen));
+    Result->AddChunk(Chunk(CodeCompletionString::CK_CurrentParameter, "..."));
+    Result->AddChunk(Chunk(CodeCompletionString::CK_RightParen));
+    return Result;
+  }
+  
+  if (FDecl)
+    Result->AddTextChunk(FDecl->getNameAsString());
+  else
+    Result->AddTextChunk(
+         Proto->getResultType().getAsString(S.Context.PrintingPolicy));
+  
+  Result->AddChunk(Chunk(CodeCompletionString::CK_LeftParen));
+  unsigned NumParams = FDecl? FDecl->getNumParams() : Proto->getNumArgs();
+  for (unsigned I = 0; I != NumParams; ++I) {
+    if (I)
+      Result->AddChunk(Chunk(CodeCompletionString::CK_Comma));
+    
+    std::string ArgString;
+    QualType ArgType;
+    
+    if (FDecl) {
+      ArgString = FDecl->getParamDecl(I)->getNameAsString();
+      ArgType = FDecl->getParamDecl(I)->getOriginalType();
+    } else {
+      ArgType = Proto->getArgType(I);
+    }
+    
+    ArgType.getAsStringInternal(ArgString, S.Context.PrintingPolicy);
+    
+    if (I == CurrentArg)
+      Result->AddChunk(Chunk(CodeCompletionString::CK_CurrentParameter, 
+                             ArgString));
+    else
+      Result->AddTextChunk(ArgString);
+  }
+  
+  if (Proto && Proto->isVariadic()) {
+    Result->AddChunk(Chunk(CodeCompletionString::CK_Comma));
+    if (CurrentArg < NumParams)
+      Result->AddTextChunk("...");
+    else
+      Result->AddChunk(Chunk(CodeCompletionString::CK_CurrentParameter, "..."));
+  }
+  Result->AddChunk(Chunk(CodeCompletionString::CK_RightParen));
+  
+  return Result;
+}
+
+namespace {
+  struct SortCodeCompleteResult {
+    typedef CodeCompleteConsumer::Result Result;
+    
+    bool isEarlierDeclarationName(DeclarationName X, DeclarationName Y) const {
+      Selector XSel = X.getObjCSelector();
+      Selector YSel = Y.getObjCSelector();
+      if (!XSel.isNull() && !YSel.isNull()) {
+        // We are comparing two selectors.
+        unsigned N = std::min(XSel.getNumArgs(), YSel.getNumArgs());
+        if (N == 0)
+          ++N;
+        for (unsigned I = 0; I != N; ++I) {
+          IdentifierInfo *XId = XSel.getIdentifierInfoForSlot(I);
+          IdentifierInfo *YId = YSel.getIdentifierInfoForSlot(I);
+          if (!XId || !YId)
+            return XId && !YId;
+          
+          switch (XId->getName().compare_lower(YId->getName())) {
+          case -1: return true;
+          case 1: return false;
+          default: break;
+          }
+        }
+    
+        return XSel.getNumArgs() < YSel.getNumArgs();
+      }
+
+      // For non-selectors, order by kind.
+      if (X.getNameKind() != Y.getNameKind())
+        return X.getNameKind() < Y.getNameKind();
+      
+      // Order identifiers by comparison of their lowercased names.
+      if (IdentifierInfo *XId = X.getAsIdentifierInfo())
+        return XId->getName().compare_lower(
+                                     Y.getAsIdentifierInfo()->getName()) < 0;
+
+      // Order overloaded operators by the order in which they appear
+      // in our list of operators.
+      if (OverloadedOperatorKind XOp = X.getCXXOverloadedOperator())
+        return XOp < Y.getCXXOverloadedOperator();
+
+      // Order C++0x user-defined literal operators lexically by their
+      // lowercased suffixes.
+      if (IdentifierInfo *XLit = X.getCXXLiteralIdentifier())
+        return XLit->getName().compare_lower(
+                                  Y.getCXXLiteralIdentifier()->getName()) < 0;
+
+      // The only stable ordering we have is to turn the name into a
+      // string and then compare the lower-case strings. This is
+      // inefficient, but thankfully does not happen too often.
+      return llvm::StringRef(X.getAsString()).compare_lower(
+                                                 Y.getAsString()) < 0;
+    }
+    
+    /// \brief Retrieve the name that should be used to order a result.
+    ///
+    /// If the name needs to be constructed as a string, that string will be
+    /// saved into Saved and the returned StringRef will refer to it.
+    static llvm::StringRef getOrderedName(const Result &R,
+                                          std::string &Saved) {
+      switch (R.Kind) {
+      case Result::RK_Keyword:
+        return R.Keyword;
+          
+      case Result::RK_Pattern:
+        return R.Pattern->getTypedText();
+          
+      case Result::RK_Macro:
+        return R.Macro->getName();
+          
+      case Result::RK_Declaration:
+        // Handle declarations below.
+        break;
+      }
+            
+      DeclarationName Name = R.Declaration->getDeclName();
+      
+      // If the name is a simple identifier (by far the common case), or a
+      // zero-argument selector, just return a reference to that identifier.
+      if (IdentifierInfo *Id = Name.getAsIdentifierInfo())
+        return Id->getName();
+      if (Name.isObjCZeroArgSelector())
+        if (IdentifierInfo *Id
+                          = Name.getObjCSelector().getIdentifierInfoForSlot(0))
+          return Id->getName();
+      
+      Saved = Name.getAsString();
+      return Saved;
+    }
+    
+    bool operator()(const Result &X, const Result &Y) const {
+      std::string XSaved, YSaved;
+      llvm::StringRef XStr = getOrderedName(X, XSaved);
+      llvm::StringRef YStr = getOrderedName(Y, YSaved);
+      int cmp = XStr.compare_lower(YStr);
+      if (cmp)
+        return cmp < 0;
+      
+      // Non-hidden names precede hidden names.
+      if (X.Hidden != Y.Hidden)
+        return !X.Hidden;
+      
+      // Non-nested-name-specifiers precede nested-name-specifiers.
+      if (X.StartsNestedNameSpecifier != Y.StartsNestedNameSpecifier)
+        return !X.StartsNestedNameSpecifier;
+      
+      return false;
+    }
+  };
+}
+
+static void AddMacroResults(Preprocessor &PP, ResultBuilder &Results) {
+  Results.EnterNewScope();
+  for (Preprocessor::macro_iterator M = PP.macro_begin(), 
+                                 MEnd = PP.macro_end();
+       M != MEnd; ++M)
+    Results.AddResult(M->first);
+  Results.ExitScope();
+}
+
+static void HandleCodeCompleteResults(Sema *S,
+                                      CodeCompleteConsumer *CodeCompleter,
+                                     CodeCompleteConsumer::Result *Results,
+                                     unsigned NumResults) {
+  std::stable_sort(Results, Results + NumResults, SortCodeCompleteResult());
+
+  if (CodeCompleter)
+    CodeCompleter->ProcessCodeCompleteResults(*S, Results, NumResults);
+  
+  for (unsigned I = 0; I != NumResults; ++I)
+    Results[I].Destroy();
+}
+
+void Sema::CodeCompleteOrdinaryName(Scope *S, 
+                                    CodeCompletionContext CompletionContext) {
+  typedef CodeCompleteConsumer::Result Result;
+  ResultBuilder Results(*this);
+
+  // Determine how to filter results, e.g., so that the names of
+  // values (functions, enumerators, function templates, etc.) are
+  // only allowed where we can have an expression.
+  switch (CompletionContext) {
+  case CCC_Namespace:
+  case CCC_Class:
+  case CCC_ObjCInterface:
+  case CCC_ObjCImplementation:
+  case CCC_ObjCInstanceVariableList:
+  case CCC_Template:
+  case CCC_MemberTemplate:
+    Results.setFilter(&ResultBuilder::IsOrdinaryNonValueName);
+    break;
+
+  case CCC_Expression:
+  case CCC_Statement:
+  case CCC_ForInit:
+  case CCC_Condition:
+    Results.setFilter(&ResultBuilder::IsOrdinaryName);
+    break;
+  }
+
+  CodeCompletionDeclConsumer Consumer(Results, CurContext);
+  LookupVisibleDecls(S, LookupOrdinaryName, Consumer);
+
+  Results.EnterNewScope();
+  AddOrdinaryNameResults(CompletionContext, S, *this, Results);
+  Results.ExitScope();
+
+  if (CodeCompleter->includeMacros())
+    AddMacroResults(PP, Results);
+  HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size());
+}
+
+static void AddObjCProperties(ObjCContainerDecl *Container, 
+                              bool AllowCategories,
+                              DeclContext *CurContext,
+                              ResultBuilder &Results) {
+  typedef CodeCompleteConsumer::Result Result;
+
+  // Add properties in this container.
+  for (ObjCContainerDecl::prop_iterator P = Container->prop_begin(),
+                                     PEnd = Container->prop_end();
+       P != PEnd;
+       ++P)
+    Results.MaybeAddResult(Result(*P, 0), CurContext);
+  
+  // Add properties in referenced protocols.
+  if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
+    for (ObjCProtocolDecl::protocol_iterator P = Protocol->protocol_begin(),
+                                          PEnd = Protocol->protocol_end();
+         P != PEnd; ++P)
+      AddObjCProperties(*P, AllowCategories, CurContext, Results);
+  } else if (ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container)){
+    if (AllowCategories) {
+      // Look through categories.
+      for (ObjCCategoryDecl *Category = IFace->getCategoryList();
+           Category; Category = Category->getNextClassCategory())
+        AddObjCProperties(Category, AllowCategories, CurContext, Results);
+    }
+    
+    // Look through protocols.
+    for (ObjCInterfaceDecl::protocol_iterator I = IFace->protocol_begin(),
+                                              E = IFace->protocol_end(); 
+         I != E; ++I)
+      AddObjCProperties(*I, AllowCategories, CurContext, Results);
+    
+    // Look in the superclass.
+    if (IFace->getSuperClass())
+      AddObjCProperties(IFace->getSuperClass(), AllowCategories, CurContext, 
+                        Results);
+  } else if (const ObjCCategoryDecl *Category
+                                    = dyn_cast<ObjCCategoryDecl>(Container)) {
+    // Look through protocols.
+    for (ObjCInterfaceDecl::protocol_iterator P = Category->protocol_begin(),
+                                           PEnd = Category->protocol_end(); 
+         P != PEnd; ++P)
+      AddObjCProperties(*P, AllowCategories, CurContext, Results);
+  }
+}
+
+void Sema::CodeCompleteMemberReferenceExpr(Scope *S, ExprTy *BaseE,
+                                           SourceLocation OpLoc,
+                                           bool IsArrow) {
+  if (!BaseE || !CodeCompleter)
+    return;
+  
+  typedef CodeCompleteConsumer::Result Result;
+  
+  Expr *Base = static_cast<Expr *>(BaseE);
+  QualType BaseType = Base->getType();
+
+  if (IsArrow) {
+    if (const PointerType *Ptr = BaseType->getAs<PointerType>())
+      BaseType = Ptr->getPointeeType();
+    else if (BaseType->isObjCObjectPointerType())
+    /*Do nothing*/ ;
+    else
+      return;
+  }
+  
+  ResultBuilder Results(*this, &ResultBuilder::IsMember);
+  Results.EnterNewScope();
+  if (const RecordType *Record = BaseType->getAs<RecordType>()) {
+    // Access to a C/C++ class, struct, or union.
+    Results.allowNestedNameSpecifiers();
+    CodeCompletionDeclConsumer Consumer(Results, CurContext);
+    LookupVisibleDecls(Record->getDecl(), LookupMemberName, Consumer);
+
+    if (getLangOptions().CPlusPlus) {
+      if (!Results.empty()) {
+        // The "template" keyword can follow "->" or "." in the grammar.
+        // However, we only want to suggest the template keyword if something
+        // is dependent.
+        bool IsDependent = BaseType->isDependentType();
+        if (!IsDependent) {
+          for (Scope *DepScope = S; DepScope; DepScope = DepScope->getParent())
+            if (DeclContext *Ctx = (DeclContext *)DepScope->getEntity()) {
+              IsDependent = Ctx->isDependentContext();
+              break;
+            }
+        }
+
+        if (IsDependent)
+          Results.AddResult(Result("template"));
+      }
+    }
+  } else if (!IsArrow && BaseType->getAsObjCInterfacePointerType()) {
+    // Objective-C property reference.
+    
+    // Add property results based on our interface.
+    const ObjCObjectPointerType *ObjCPtr
+      = BaseType->getAsObjCInterfacePointerType();
+    assert(ObjCPtr && "Non-NULL pointer guaranteed above!");
+    AddObjCProperties(ObjCPtr->getInterfaceDecl(), true, CurContext, Results);
+    
+    // Add properties from the protocols in a qualified interface.
+    for (ObjCObjectPointerType::qual_iterator I = ObjCPtr->qual_begin(),
+                                              E = ObjCPtr->qual_end();
+         I != E; ++I)
+      AddObjCProperties(*I, true, CurContext, Results);
+  } else if ((IsArrow && BaseType->isObjCObjectPointerType()) ||
+             (!IsArrow && BaseType->isObjCInterfaceType())) {
+    // Objective-C instance variable access.
+    ObjCInterfaceDecl *Class = 0;
+    if (const ObjCObjectPointerType *ObjCPtr
+                                    = BaseType->getAs<ObjCObjectPointerType>())
+      Class = ObjCPtr->getInterfaceDecl();
+    else
+      Class = BaseType->getAs<ObjCInterfaceType>()->getDecl();
+    
+    // Add all ivars from this class and its superclasses.
+    if (Class) {
+      CodeCompletionDeclConsumer Consumer(Results, CurContext);
+      Results.setFilter(&ResultBuilder::IsObjCIvar);
+      LookupVisibleDecls(Class, LookupMemberName, Consumer);
+    }
+  }
+  
+  // FIXME: How do we cope with isa?
+  
+  Results.ExitScope();
+
+  // Add macros
+  if (CodeCompleter->includeMacros())
+    AddMacroResults(PP, Results);
+
+  // Hand off the results found for code completion.
+  HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size());
+}
+
+void Sema::CodeCompleteTag(Scope *S, unsigned TagSpec) {
+  if (!CodeCompleter)
+    return;
+  
+  typedef CodeCompleteConsumer::Result Result;
+  ResultBuilder::LookupFilter Filter = 0;
+  switch ((DeclSpec::TST)TagSpec) {
+  case DeclSpec::TST_enum:
+    Filter = &ResultBuilder::IsEnum;
+    break;
+    
+  case DeclSpec::TST_union:
+    Filter = &ResultBuilder::IsUnion;
+    break;
+    
+  case DeclSpec::TST_struct:
+  case DeclSpec::TST_class:
+    Filter = &ResultBuilder::IsClassOrStruct;
+    break;
+    
+  default:
+    assert(false && "Unknown type specifier kind in CodeCompleteTag");
+    return;
+  }
+  
+  ResultBuilder Results(*this, Filter);
+  Results.allowNestedNameSpecifiers();
+  CodeCompletionDeclConsumer Consumer(Results, CurContext);
+  LookupVisibleDecls(S, LookupTagName, Consumer);
+  
+  if (CodeCompleter->includeMacros())
+    AddMacroResults(PP, Results);
+  HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size());
+}
+
+void Sema::CodeCompleteCase(Scope *S) {
+  if (getSwitchStack().empty() || !CodeCompleter)
+    return;
+  
+  SwitchStmt *Switch = getSwitchStack().back();
+  if (!Switch->getCond()->getType()->isEnumeralType())
+    return;
+  
+  // Code-complete the cases of a switch statement over an enumeration type
+  // by providing the list of 
+  EnumDecl *Enum = Switch->getCond()->getType()->getAs<EnumType>()->getDecl();
+  
+  // Determine which enumerators we have already seen in the switch statement.
+  // FIXME: Ideally, we would also be able to look *past* the code-completion
+  // token, in case we are code-completing in the middle of the switch and not
+  // at the end. However, we aren't able to do so at the moment.
+  llvm::SmallPtrSet<EnumConstantDecl *, 8> EnumeratorsSeen;
+  NestedNameSpecifier *Qualifier = 0;
+  for (SwitchCase *SC = Switch->getSwitchCaseList(); SC; 
+       SC = SC->getNextSwitchCase()) {
+    CaseStmt *Case = dyn_cast<CaseStmt>(SC);
+    if (!Case)
+      continue;
+
+    Expr *CaseVal = Case->getLHS()->IgnoreParenCasts();
+    if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(CaseVal))
+      if (EnumConstantDecl *Enumerator 
+            = dyn_cast<EnumConstantDecl>(DRE->getDecl())) {
+        // We look into the AST of the case statement to determine which 
+        // enumerator was named. Alternatively, we could compute the value of 
+        // the integral constant expression, then compare it against the
+        // values of each enumerator. However, value-based approach would not 
+        // work as well with C++ templates where enumerators declared within a 
+        // template are type- and value-dependent.
+        EnumeratorsSeen.insert(Enumerator);
+        
+        // If this is a qualified-id, keep track of the nested-name-specifier
+        // so that we can reproduce it as part of code completion, e.g.,
+        //
+        //   switch (TagD.getKind()) {
+        //     case TagDecl::TK_enum:
+        //       break;
+        //     case XXX
+        //
+        // At the XXX, our completions are TagDecl::TK_union,
+        // TagDecl::TK_struct, and TagDecl::TK_class, rather than TK_union,
+        // TK_struct, and TK_class.
+        Qualifier = DRE->getQualifier();
+      }
+  }
+  
+  if (getLangOptions().CPlusPlus && !Qualifier && EnumeratorsSeen.empty()) {
+    // If there are no prior enumerators in C++, check whether we have to 
+    // qualify the names of the enumerators that we suggest, because they
+    // may not be visible in this scope.
+    Qualifier = getRequiredQualification(Context, CurContext,
+                                         Enum->getDeclContext());
+    
+    // FIXME: Scoped enums need to start with "EnumDecl" as the context!
+  }
+  
+  // Add any enumerators that have not yet been mentioned.
+  ResultBuilder Results(*this);
+  Results.EnterNewScope();
+  for (EnumDecl::enumerator_iterator E = Enum->enumerator_begin(),
+                                  EEnd = Enum->enumerator_end();
+       E != EEnd; ++E) {
+    if (EnumeratorsSeen.count(*E))
+      continue;
+    
+    Results.AddResult(CodeCompleteConsumer::Result(*E, Qualifier),
+                      CurContext, 0, false);
+  }
+  Results.ExitScope();
+  
+  if (CodeCompleter->includeMacros())
+    AddMacroResults(PP, Results);
+  HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size());
+}
+
+namespace {
+  struct IsBetterOverloadCandidate {
+    Sema &S;
+    SourceLocation Loc;
+    
+  public:
+    explicit IsBetterOverloadCandidate(Sema &S, SourceLocation Loc)
+      : S(S), Loc(Loc) { }
+    
+    bool 
+    operator()(const OverloadCandidate &X, const OverloadCandidate &Y) const {
+      return S.isBetterOverloadCandidate(X, Y, Loc);
+    }
+  };
+}
+
+void Sema::CodeCompleteCall(Scope *S, ExprTy *FnIn,
+                            ExprTy **ArgsIn, unsigned NumArgs) {
+  if (!CodeCompleter)
+    return;
+
+  // When we're code-completing for a call, we fall back to ordinary
+  // name code-completion whenever we can't produce specific
+  // results. We may want to revisit this strategy in the future,
+  // e.g., by merging the two kinds of results.
+
+  Expr *Fn = (Expr *)FnIn;
+  Expr **Args = (Expr **)ArgsIn;
+
+  // Ignore type-dependent call expressions entirely.
+  if (Fn->isTypeDependent() || 
+      Expr::hasAnyTypeDependentArguments(Args, NumArgs)) {
+    CodeCompleteOrdinaryName(S, CCC_Expression);
+    return;
+  }
+
+  // Build an overload candidate set based on the functions we find.
+  SourceLocation Loc = Fn->getExprLoc();
+  OverloadCandidateSet CandidateSet(Loc);
+
+  // FIXME: What if we're calling something that isn't a function declaration?
+  // FIXME: What if we're calling a pseudo-destructor?
+  // FIXME: What if we're calling a member function?
+  
+  typedef CodeCompleteConsumer::OverloadCandidate ResultCandidate;
+  llvm::SmallVector<ResultCandidate, 8> Results;
+
+  Expr *NakedFn = Fn->IgnoreParenCasts();
+  if (UnresolvedLookupExpr *ULE = dyn_cast<UnresolvedLookupExpr>(NakedFn))
+    AddOverloadedCallCandidates(ULE, Args, NumArgs, CandidateSet,
+                                /*PartialOverloading=*/ true);
+  else if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(NakedFn)) {
+    FunctionDecl *FDecl = dyn_cast<FunctionDecl>(DRE->getDecl());
+    if (FDecl) {
+      if (!FDecl->getType()->getAs<FunctionProtoType>())
+        Results.push_back(ResultCandidate(FDecl));
+      else
+        // FIXME: access?
+        AddOverloadCandidate(FDecl, AS_none, Args, NumArgs, CandidateSet,
+                             false, false, /*PartialOverloading*/ true);
+    }
+  }
+  
+  if (!CandidateSet.empty()) {
+    // Sort the overload candidate set by placing the best overloads first.
+    std::stable_sort(CandidateSet.begin(), CandidateSet.end(),
+                     IsBetterOverloadCandidate(*this, Loc));
+  
+    // Add the remaining viable overload candidates as code-completion reslults.
+    for (OverloadCandidateSet::iterator Cand = CandidateSet.begin(),
+                                     CandEnd = CandidateSet.end();
+         Cand != CandEnd; ++Cand) {
+      if (Cand->Viable)
+        Results.push_back(ResultCandidate(Cand->Function));
+    }
+  }
+
+  if (Results.empty())
+    CodeCompleteOrdinaryName(S, CCC_Expression);
+  else
+    CodeCompleter->ProcessOverloadCandidates(*this, NumArgs, Results.data(), 
+                                             Results.size());
+}
+
+void Sema::CodeCompleteQualifiedId(Scope *S, const CXXScopeSpec &SS,
+                                   bool EnteringContext) {
+  if (!SS.getScopeRep() || !CodeCompleter)
+    return;
+  
+  DeclContext *Ctx = computeDeclContext(SS, EnteringContext);
+  if (!Ctx)
+    return;
+
+  // Try to instantiate any non-dependent declaration contexts before
+  // we look in them.
+  if (!isDependentScopeSpecifier(SS) && RequireCompleteDeclContext(SS))
+    return;
+
+  ResultBuilder Results(*this);
+  CodeCompletionDeclConsumer Consumer(Results, CurContext);
+  LookupVisibleDecls(Ctx, LookupOrdinaryName, Consumer);
+  
+  // The "template" keyword can follow "::" in the grammar, but only
+  // put it into the grammar if the nested-name-specifier is dependent.
+  NestedNameSpecifier *NNS = (NestedNameSpecifier *)SS.getScopeRep();
+  if (!Results.empty() && NNS->isDependent())
+    Results.AddResult("template");
+  
+  if (CodeCompleter->includeMacros())
+    AddMacroResults(PP, Results);
+  HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size());
+}
+
+void Sema::CodeCompleteUsing(Scope *S) {
+  if (!CodeCompleter)
+    return;
+  
+  ResultBuilder Results(*this, &ResultBuilder::IsNestedNameSpecifier);
+  Results.EnterNewScope();
+  
+  // If we aren't in class scope, we could see the "namespace" keyword.
+  if (!S->isClassScope())
+    Results.AddResult(CodeCompleteConsumer::Result("namespace"));
+  
+  // After "using", we can see anything that would start a 
+  // nested-name-specifier.
+  CodeCompletionDeclConsumer Consumer(Results, CurContext);
+  LookupVisibleDecls(S, LookupOrdinaryName, Consumer);
+  Results.ExitScope();
+  
+  if (CodeCompleter->includeMacros())
+    AddMacroResults(PP, Results);
+  HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size());
+}
+
+void Sema::CodeCompleteUsingDirective(Scope *S) {
+  if (!CodeCompleter)
+    return;
+  
+  // After "using namespace", we expect to see a namespace name or namespace
+  // alias.
+  ResultBuilder Results(*this, &ResultBuilder::IsNamespaceOrAlias);
+  Results.EnterNewScope();
+  CodeCompletionDeclConsumer Consumer(Results, CurContext);
+  LookupVisibleDecls(S, LookupOrdinaryName, Consumer);
+  Results.ExitScope();
+  if (CodeCompleter->includeMacros())
+    AddMacroResults(PP, Results);
+  HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size());
+}
+
+void Sema::CodeCompleteNamespaceDecl(Scope *S)  {
+  if (!CodeCompleter)
+    return;
+  
+  ResultBuilder Results(*this, &ResultBuilder::IsNamespace);
+  DeclContext *Ctx = (DeclContext *)S->getEntity();
+  if (!S->getParent())
+    Ctx = Context.getTranslationUnitDecl();
+  
+  if (Ctx && Ctx->isFileContext()) {
+    // We only want to see those namespaces that have already been defined
+    // within this scope, because its likely that the user is creating an
+    // extended namespace declaration. Keep track of the most recent 
+    // definition of each namespace.
+    std::map<NamespaceDecl *, NamespaceDecl *> OrigToLatest;
+    for (DeclContext::specific_decl_iterator<NamespaceDecl> 
+         NS(Ctx->decls_begin()), NSEnd(Ctx->decls_end());
+         NS != NSEnd; ++NS)
+      OrigToLatest[NS->getOriginalNamespace()] = *NS;
+    
+    // Add the most recent definition (or extended definition) of each 
+    // namespace to the list of results.
+    Results.EnterNewScope();
+    for (std::map<NamespaceDecl *, NamespaceDecl *>::iterator 
+         NS = OrigToLatest.begin(), NSEnd = OrigToLatest.end();
+         NS != NSEnd; ++NS)
+      Results.AddResult(CodeCompleteConsumer::Result(NS->second, 0),
+                        CurContext, 0, false);
+    Results.ExitScope();
+  }
+  
+  if (CodeCompleter->includeMacros())
+    AddMacroResults(PP, Results);
+  HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size());
+}
+
+void Sema::CodeCompleteNamespaceAliasDecl(Scope *S)  {
+  if (!CodeCompleter)
+    return;
+  
+  // After "namespace", we expect to see a namespace or alias.
+  ResultBuilder Results(*this, &ResultBuilder::IsNamespaceOrAlias);
+  CodeCompletionDeclConsumer Consumer(Results, CurContext);
+  LookupVisibleDecls(S, LookupOrdinaryName, Consumer);
+  if (CodeCompleter->includeMacros())
+    AddMacroResults(PP, Results);
+  HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size());
+}
+
+void Sema::CodeCompleteOperatorName(Scope *S) {
+  if (!CodeCompleter)
+    return;
+
+  typedef CodeCompleteConsumer::Result Result;
+  ResultBuilder Results(*this, &ResultBuilder::IsType);
+  Results.EnterNewScope();
+  
+  // Add the names of overloadable operators.
+#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly)      \
+  if (std::strcmp(Spelling, "?"))                                                  \
+    Results.AddResult(Result(Spelling));
+#include "clang/Basic/OperatorKinds.def"
+  
+  // Add any type names visible from the current scope
+  Results.allowNestedNameSpecifiers();
+  CodeCompletionDeclConsumer Consumer(Results, CurContext);
+  LookupVisibleDecls(S, LookupOrdinaryName, Consumer);
+  
+  // Add any type specifiers
+  AddTypeSpecifierResults(getLangOptions(), Results);
+  Results.ExitScope();
+  
+  if (CodeCompleter->includeMacros())
+    AddMacroResults(PP, Results);
+  HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size());
+}
+
+// Macro that expands to @Keyword or Keyword, depending on whether NeedAt is
+// true or false.
+#define OBJC_AT_KEYWORD_NAME(NeedAt,Keyword) NeedAt? "@" #Keyword : #Keyword
+static void AddObjCImplementationResults(const LangOptions &LangOpts,
+                                         ResultBuilder &Results,
+                                         bool NeedAt) {
+  typedef CodeCompleteConsumer::Result Result;
+  // Since we have an implementation, we can end it.
+  Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,end)));
+  
+  CodeCompletionString *Pattern = 0;
+  if (LangOpts.ObjC2) {
+    // @dynamic
+    Pattern = new CodeCompletionString;
+    Pattern->AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,dynamic));
+    Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace);
+    Pattern->AddPlaceholderChunk("property");
+    Results.AddResult(Result(Pattern));
+    
+    // @synthesize
+    Pattern = new CodeCompletionString;
+    Pattern->AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,synthesize));
+    Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace);
+    Pattern->AddPlaceholderChunk("property");
+    Results.AddResult(Result(Pattern));
+  }  
+}
+
+static void AddObjCInterfaceResults(const LangOptions &LangOpts,
+                                    ResultBuilder &Results,
+                                    bool NeedAt) {
+  typedef CodeCompleteConsumer::Result Result;
+  
+  // Since we have an interface or protocol, we can end it.
+  Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,end)));
+  
+  if (LangOpts.ObjC2) {
+    // @property
+    Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,property)));
+  
+    // @required
+    Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,required)));
+  
+    // @optional
+    Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,optional)));
+  }
+}
+
+static void AddObjCTopLevelResults(ResultBuilder &Results, bool NeedAt) {
+  typedef CodeCompleteConsumer::Result Result;
+  CodeCompletionString *Pattern = 0;
+  
+  // @class name ;
+  Pattern = new CodeCompletionString;
+  Pattern->AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,class));
+  Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace);
+  Pattern->AddPlaceholderChunk("identifier");
+  Pattern->AddChunk(CodeCompletionString::CK_SemiColon);
+  Results.AddResult(Result(Pattern));
+  
+  // @interface name 
+  // FIXME: Could introduce the whole pattern, including superclasses and 
+  // such.
+  Pattern = new CodeCompletionString;
+  Pattern->AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,interface));
+  Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace);
+  Pattern->AddPlaceholderChunk("class");
+  Results.AddResult(Result(Pattern));
+  
+  // @protocol name
+  Pattern = new CodeCompletionString;
+  Pattern->AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,protocol));
+  Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace);
+  Pattern->AddPlaceholderChunk("protocol");
+  Results.AddResult(Result(Pattern));
+  
+  // @implementation name
+  Pattern = new CodeCompletionString;
+  Pattern->AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,implementation));
+  Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace);
+  Pattern->AddPlaceholderChunk("class");
+  Results.AddResult(Result(Pattern));
+  
+  // @compatibility_alias name
+  Pattern = new CodeCompletionString;
+  Pattern->AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,compatibility_alias));
+  Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace);
+  Pattern->AddPlaceholderChunk("alias");
+  Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace);
+  Pattern->AddPlaceholderChunk("class");
+  Results.AddResult(Result(Pattern));
+}
+
+void Sema::CodeCompleteObjCAtDirective(Scope *S, DeclPtrTy ObjCImpDecl,
+                                       bool InInterface) {
+  typedef CodeCompleteConsumer::Result Result;
+  ResultBuilder Results(*this);
+  Results.EnterNewScope();
+  if (ObjCImpDecl)
+    AddObjCImplementationResults(getLangOptions(), Results, false);
+  else if (InInterface)
+    AddObjCInterfaceResults(getLangOptions(), Results, false);
+  else
+    AddObjCTopLevelResults(Results, false);
+  Results.ExitScope();
+  HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size());
+}
+
+static void AddObjCExpressionResults(ResultBuilder &Results, bool NeedAt) {
+  typedef CodeCompleteConsumer::Result Result;
+  CodeCompletionString *Pattern = 0;
+
+  // @encode ( type-name )
+  Pattern = new CodeCompletionString;
+  Pattern->AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,encode));
+  Pattern->AddChunk(CodeCompletionString::CK_LeftParen);
+  Pattern->AddPlaceholderChunk("type-name");
+  Pattern->AddChunk(CodeCompletionString::CK_RightParen);
+  Results.AddResult(Result(Pattern));
+  
+  // @protocol ( protocol-name )
+  Pattern = new CodeCompletionString;
+  Pattern->AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,protocol));
+  Pattern->AddChunk(CodeCompletionString::CK_LeftParen);
+  Pattern->AddPlaceholderChunk("protocol-name");
+  Pattern->AddChunk(CodeCompletionString::CK_RightParen);
+  Results.AddResult(Result(Pattern));
+
+  // @selector ( selector )
+  Pattern = new CodeCompletionString;
+  Pattern->AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,selector));
+  Pattern->AddChunk(CodeCompletionString::CK_LeftParen);
+  Pattern->AddPlaceholderChunk("selector");
+  Pattern->AddChunk(CodeCompletionString::CK_RightParen);
+  Results.AddResult(Result(Pattern));
+}
+
+static void AddObjCStatementResults(ResultBuilder &Results, bool NeedAt) {
+  typedef CodeCompleteConsumer::Result Result;
+  CodeCompletionString *Pattern = 0;
+  
+  // @try { statements } @catch ( declaration ) { statements } @finally
+  //   { statements }
+  Pattern = new CodeCompletionString;
+  Pattern->AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,try));
+  Pattern->AddChunk(CodeCompletionString::CK_LeftBrace);
+  Pattern->AddPlaceholderChunk("statements");
+  Pattern->AddChunk(CodeCompletionString::CK_RightBrace);
+  Pattern->AddTextChunk("@catch");
+  Pattern->AddChunk(CodeCompletionString::CK_LeftParen);
+  Pattern->AddPlaceholderChunk("parameter");
+  Pattern->AddChunk(CodeCompletionString::CK_RightParen);
+  Pattern->AddChunk(CodeCompletionString::CK_LeftBrace);
+  Pattern->AddPlaceholderChunk("statements");
+  Pattern->AddChunk(CodeCompletionString::CK_RightBrace);
+  Pattern->AddTextChunk("@finally");
+  Pattern->AddChunk(CodeCompletionString::CK_LeftBrace);
+  Pattern->AddPlaceholderChunk("statements");
+  Pattern->AddChunk(CodeCompletionString::CK_RightBrace);
+  Results.AddResult(Result(Pattern));
+  
+  // @throw
+  Pattern = new CodeCompletionString;
+  Pattern->AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,throw));
+  Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace);
+  Pattern->AddPlaceholderChunk("expression");
+  Pattern->AddChunk(CodeCompletionString::CK_SemiColon);
+  Results.AddResult(Result(Pattern));
+  
+  // @synchronized ( expression ) { statements }
+  Pattern = new CodeCompletionString;
+  Pattern->AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,synchronized));
+  Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace);
+  Pattern->AddChunk(CodeCompletionString::CK_LeftParen);
+  Pattern->AddPlaceholderChunk("expression");
+  Pattern->AddChunk(CodeCompletionString::CK_RightParen);
+  Pattern->AddChunk(CodeCompletionString::CK_LeftBrace);
+  Pattern->AddPlaceholderChunk("statements");
+  Pattern->AddChunk(CodeCompletionString::CK_RightBrace);
+  Results.AddResult(Result(Pattern));
+}
+
+static void AddObjCVisibilityResults(const LangOptions &LangOpts,
+                                     ResultBuilder &Results,
+                                     bool NeedAt) {
+  typedef CodeCompleteConsumer::Result Result;
+  Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,private)));
+  Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,protected)));
+  Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,public)));
+  if (LangOpts.ObjC2)
+    Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,package)));    
+}
+
+void Sema::CodeCompleteObjCAtVisibility(Scope *S) {
+  ResultBuilder Results(*this);
+  Results.EnterNewScope();
+  AddObjCVisibilityResults(getLangOptions(), Results, false);
+  Results.ExitScope();
+  HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size());
+}
+
+void Sema::CodeCompleteObjCAtStatement(Scope *S) {
+  ResultBuilder Results(*this);
+  Results.EnterNewScope();
+  AddObjCStatementResults(Results, false);
+  AddObjCExpressionResults(Results, false);
+  Results.ExitScope();
+  HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size());
+}
+
+void Sema::CodeCompleteObjCAtExpression(Scope *S) {
+  ResultBuilder Results(*this);
+  Results.EnterNewScope();
+  AddObjCExpressionResults(Results, false);
+  Results.ExitScope();
+  HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size());
+}
+
+/// \brief Determine whether the addition of the given flag to an Objective-C
+/// property's attributes will cause a conflict.
+static bool ObjCPropertyFlagConflicts(unsigned Attributes, unsigned NewFlag) {
+  // Check if we've already added this flag.
+  if (Attributes & NewFlag)
+    return true;
+  
+  Attributes |= NewFlag;
+  
+  // Check for collisions with "readonly".
+  if ((Attributes & ObjCDeclSpec::DQ_PR_readonly) &&
+      (Attributes & (ObjCDeclSpec::DQ_PR_readwrite |
+                     ObjCDeclSpec::DQ_PR_assign |
+                     ObjCDeclSpec::DQ_PR_copy |
+                     ObjCDeclSpec::DQ_PR_retain)))
+    return true;
+  
+  // Check for more than one of { assign, copy, retain }.
+  unsigned AssignCopyRetMask = Attributes & (ObjCDeclSpec::DQ_PR_assign |
+                                             ObjCDeclSpec::DQ_PR_copy |
+                                             ObjCDeclSpec::DQ_PR_retain);
+  if (AssignCopyRetMask &&
+      AssignCopyRetMask != ObjCDeclSpec::DQ_PR_assign &&
+      AssignCopyRetMask != ObjCDeclSpec::DQ_PR_copy &&
+      AssignCopyRetMask != ObjCDeclSpec::DQ_PR_retain)
+    return true;
+  
+  return false;
+}
+
+void Sema::CodeCompleteObjCPropertyFlags(Scope *S, ObjCDeclSpec &ODS) { 
+  if (!CodeCompleter)
+    return;
+  
+  unsigned Attributes = ODS.getPropertyAttributes();
+  
+  typedef CodeCompleteConsumer::Result Result;
+  ResultBuilder Results(*this);
+  Results.EnterNewScope();
+  if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_readonly))
+    Results.AddResult(CodeCompleteConsumer::Result("readonly"));
+  if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_assign))
+    Results.AddResult(CodeCompleteConsumer::Result("assign"));
+  if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_readwrite))
+    Results.AddResult(CodeCompleteConsumer::Result("readwrite"));
+  if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_retain))
+    Results.AddResult(CodeCompleteConsumer::Result("retain"));
+  if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_copy))
+    Results.AddResult(CodeCompleteConsumer::Result("copy"));
+  if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_nonatomic))
+    Results.AddResult(CodeCompleteConsumer::Result("nonatomic"));
+  if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_setter)) {
+    CodeCompletionString *Setter = new CodeCompletionString;
+    Setter->AddTypedTextChunk("setter");
+    Setter->AddTextChunk(" = ");
+    Setter->AddPlaceholderChunk("method");
+    Results.AddResult(CodeCompleteConsumer::Result(Setter));
+  }
+  if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_getter)) {
+    CodeCompletionString *Getter = new CodeCompletionString;
+    Getter->AddTypedTextChunk("getter");
+    Getter->AddTextChunk(" = ");
+    Getter->AddPlaceholderChunk("method");
+    Results.AddResult(CodeCompleteConsumer::Result(Getter));
+  }
+  Results.ExitScope();
+  HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size());
+}
+
+/// \brief Descripts the kind of Objective-C method that we want to find
+/// via code completion.
+enum ObjCMethodKind {
+  MK_Any, //< Any kind of method, provided it means other specified criteria.
+  MK_ZeroArgSelector, //< Zero-argument (unary) selector.
+  MK_OneArgSelector //< One-argument selector.
+};
+
+static bool isAcceptableObjCMethod(ObjCMethodDecl *Method,
+                                   ObjCMethodKind WantKind,
+                                   IdentifierInfo **SelIdents,
+                                   unsigned NumSelIdents) {
+  Selector Sel = Method->getSelector();
+  if (NumSelIdents > Sel.getNumArgs())
+    return false;
+      
+  switch (WantKind) {
+  case MK_Any:             break;
+  case MK_ZeroArgSelector: return Sel.isUnarySelector();
+  case MK_OneArgSelector:  return Sel.getNumArgs() == 1;
+  }
+
+  for (unsigned I = 0; I != NumSelIdents; ++I)
+    if (SelIdents[I] != Sel.getIdentifierInfoForSlot(I))
+      return false;
+
+  return true;
+}
+                                   
+/// \brief Add all of the Objective-C methods in the given Objective-C 
+/// container to the set of results.
+///
+/// The container will be a class, protocol, category, or implementation of 
+/// any of the above. This mether will recurse to include methods from 
+/// the superclasses of classes along with their categories, protocols, and
+/// implementations.
+///
+/// \param Container the container in which we'll look to find methods.
+///
+/// \param WantInstance whether to add instance methods (only); if false, this
+/// routine will add factory methods (only).
+///
+/// \param CurContext the context in which we're performing the lookup that
+/// finds methods.
+///
+/// \param Results the structure into which we'll add results.
+static void AddObjCMethods(ObjCContainerDecl *Container, 
+                           bool WantInstanceMethods,
+                           ObjCMethodKind WantKind,
+                           IdentifierInfo **SelIdents,
+                           unsigned NumSelIdents,
+                           DeclContext *CurContext,
+                           ResultBuilder &Results) {
+  typedef CodeCompleteConsumer::Result Result;
+  for (ObjCContainerDecl::method_iterator M = Container->meth_begin(),
+                                       MEnd = Container->meth_end();
+       M != MEnd; ++M) {
+    if ((*M)->isInstanceMethod() == WantInstanceMethods) {
+      // Check whether the selector identifiers we've been given are a 
+      // subset of the identifiers for this particular method.
+      if (!isAcceptableObjCMethod(*M, WantKind, SelIdents, NumSelIdents))
+        continue;
+
+      Result R = Result(*M, 0);
+      R.StartParameter = NumSelIdents;
+      R.AllParametersAreInformative = (WantKind != MK_Any);
+      Results.MaybeAddResult(R, CurContext);
+    }
+  }
+  
+  ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container);
+  if (!IFace)
+    return;
+  
+  // Add methods in protocols.
+  const ObjCList<ObjCProtocolDecl> &Protocols= IFace->getReferencedProtocols();
+  for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
+                                            E = Protocols.end(); 
+       I != E; ++I)
+    AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents, NumSelIdents, 
+                   CurContext, Results);
+  
+  // Add methods in categories.
+  for (ObjCCategoryDecl *CatDecl = IFace->getCategoryList(); CatDecl;
+       CatDecl = CatDecl->getNextClassCategory()) {
+    AddObjCMethods(CatDecl, WantInstanceMethods, WantKind, SelIdents, 
+                   NumSelIdents, CurContext, Results);
+    
+    // Add a categories protocol methods.
+    const ObjCList<ObjCProtocolDecl> &Protocols 
+      = CatDecl->getReferencedProtocols();
+    for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
+                                              E = Protocols.end();
+         I != E; ++I)
+      AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents, 
+                     NumSelIdents, CurContext, Results);
+    
+    // Add methods in category implementations.
+    if (ObjCCategoryImplDecl *Impl = CatDecl->getImplementation())
+      AddObjCMethods(Impl, WantInstanceMethods, WantKind, SelIdents, 
+                     NumSelIdents, CurContext, Results);
+  }
+  
+  // Add methods in superclass.
+  if (IFace->getSuperClass())
+    AddObjCMethods(IFace->getSuperClass(), WantInstanceMethods, WantKind, 
+                   SelIdents, NumSelIdents, CurContext, Results);
+
+  // Add methods in our implementation, if any.
+  if (ObjCImplementationDecl *Impl = IFace->getImplementation())
+    AddObjCMethods(Impl, WantInstanceMethods, WantKind, SelIdents,
+                   NumSelIdents, CurContext, Results);
+}
+
+
+void Sema::CodeCompleteObjCPropertyGetter(Scope *S, DeclPtrTy ClassDecl,
+                                          DeclPtrTy *Methods,
+                                          unsigned NumMethods) {
+  typedef CodeCompleteConsumer::Result Result;
+
+  // Try to find the interface where getters might live.
+  ObjCInterfaceDecl *Class
+    = dyn_cast_or_null<ObjCInterfaceDecl>(ClassDecl.getAs<Decl>());
+  if (!Class) {
+    if (ObjCCategoryDecl *Category
+          = dyn_cast_or_null<ObjCCategoryDecl>(ClassDecl.getAs<Decl>()))
+      Class = Category->getClassInterface();
+
+    if (!Class)
+      return;
+  }
+
+  // Find all of the potential getters.
+  ResultBuilder Results(*this);
+  Results.EnterNewScope();
+
+  // FIXME: We need to do this because Objective-C methods don't get
+  // pushed into DeclContexts early enough. Argh!
+  for (unsigned I = 0; I != NumMethods; ++I) { 
+    if (ObjCMethodDecl *Method
+            = dyn_cast_or_null<ObjCMethodDecl>(Methods[I].getAs<Decl>()))
+      if (Method->isInstanceMethod() &&
+          isAcceptableObjCMethod(Method, MK_ZeroArgSelector, 0, 0)) {
+        Result R = Result(Method, 0);
+        R.AllParametersAreInformative = true;
+        Results.MaybeAddResult(R, CurContext);
+      }
+  }
+
+  AddObjCMethods(Class, true, MK_ZeroArgSelector, 0, 0, CurContext, Results);
+  Results.ExitScope();
+  HandleCodeCompleteResults(this, CodeCompleter,Results.data(),Results.size());
+}
+
+void Sema::CodeCompleteObjCPropertySetter(Scope *S, DeclPtrTy ObjCImplDecl,
+                                          DeclPtrTy *Methods,
+                                          unsigned NumMethods) {
+  typedef CodeCompleteConsumer::Result Result;
+
+  // Try to find the interface where setters might live.
+  ObjCInterfaceDecl *Class
+    = dyn_cast_or_null<ObjCInterfaceDecl>(ObjCImplDecl.getAs<Decl>());
+  if (!Class) {
+    if (ObjCCategoryDecl *Category
+          = dyn_cast_or_null<ObjCCategoryDecl>(ObjCImplDecl.getAs<Decl>()))
+      Class = Category->getClassInterface();
+
+    if (!Class)
+      return;
+  }
+
+  // Find all of the potential getters.
+  ResultBuilder Results(*this);
+  Results.EnterNewScope();
+
+  // FIXME: We need to do this because Objective-C methods don't get
+  // pushed into DeclContexts early enough. Argh!
+  for (unsigned I = 0; I != NumMethods; ++I) { 
+    if (ObjCMethodDecl *Method
+            = dyn_cast_or_null<ObjCMethodDecl>(Methods[I].getAs<Decl>()))
+      if (Method->isInstanceMethod() &&
+          isAcceptableObjCMethod(Method, MK_OneArgSelector, 0, 0)) {
+        Result R = Result(Method, 0);
+        R.AllParametersAreInformative = true;
+        Results.MaybeAddResult(R, CurContext);
+      }
+  }
+
+  AddObjCMethods(Class, true, MK_OneArgSelector, 0, 0, CurContext, Results);
+
+  Results.ExitScope();
+  HandleCodeCompleteResults(this, CodeCompleter,Results.data(),Results.size());
+}
+
+void Sema::CodeCompleteObjCClassMessage(Scope *S, IdentifierInfo *FName,
+                                        SourceLocation FNameLoc,
+                                        IdentifierInfo **SelIdents,
+                                        unsigned NumSelIdents) {
+  typedef CodeCompleteConsumer::Result Result;
+  ObjCInterfaceDecl *CDecl = 0;
+
+  if (FName->isStr("super")) {
+    // We're sending a message to "super".
+    if (ObjCMethodDecl *CurMethod = getCurMethodDecl()) {
+      // Figure out which interface we're in.
+      CDecl = CurMethod->getClassInterface();
+      if (!CDecl)
+        return;
+
+      // Find the superclass of this class.
+      CDecl = CDecl->getSuperClass();
+      if (!CDecl)
+        return;
+
+      if (CurMethod->isInstanceMethod()) {
+        // We are inside an instance method, which means that the message
+        // send [super ...] is actually calling an instance method on the
+        // current object. Build the super expression and handle this like
+        // an instance method.
+        QualType SuperTy = Context.getObjCInterfaceType(CDecl);
+        SuperTy = Context.getObjCObjectPointerType(SuperTy);
+        OwningExprResult Super
+          = Owned(new (Context) ObjCSuperExpr(FNameLoc, SuperTy));
+        return CodeCompleteObjCInstanceMessage(S, (Expr *)Super.get(),
+                                               SelIdents, NumSelIdents);
+      }
+
+      // Okay, we're calling a factory method in our superclass.
+    } 
+  }
+
+  // If the given name refers to an interface type, retrieve the
+  // corresponding declaration.
+  if (!CDecl)
+    if (TypeTy *Ty = getTypeName(*FName, FNameLoc, S, 0, false)) {
+      QualType T = GetTypeFromParser(Ty, 0);
+      if (!T.isNull()) 
+        if (const ObjCInterfaceType *Interface = T->getAs<ObjCInterfaceType>())
+          CDecl = Interface->getDecl();
+    }
+
+  if (!CDecl && FName->isStr("super")) {
+    // "super" may be the name of a variable, in which case we are
+    // probably calling an instance method.
+    CXXScopeSpec SS;
+    UnqualifiedId id;
+    id.setIdentifier(FName, FNameLoc);
+    OwningExprResult Super = ActOnIdExpression(S, SS, id, false, false);
+    return CodeCompleteObjCInstanceMessage(S, (Expr *)Super.get(),
+                                           SelIdents, NumSelIdents);
+  }
+
+  // Add all of the factory methods in this Objective-C class, its protocols,
+  // superclasses, categories, implementation, etc.
+  ResultBuilder Results(*this);
+  Results.EnterNewScope();
+  AddObjCMethods(CDecl, false, MK_Any, SelIdents, NumSelIdents, CurContext, 
+                 Results);  
+  Results.ExitScope();
+  
+  // This also suppresses remaining diagnostics.
+  HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size());
+}
+
+void Sema::CodeCompleteObjCInstanceMessage(Scope *S, ExprTy *Receiver,
+                                           IdentifierInfo **SelIdents,
+                                           unsigned NumSelIdents) {
+  typedef CodeCompleteConsumer::Result Result;
+  
+  Expr *RecExpr = static_cast<Expr *>(Receiver);
+  
+  // If necessary, apply function/array conversion to the receiver.
+  // C99 6.7.5.3p[7,8].
+  DefaultFunctionArrayLvalueConversion(RecExpr);
+  QualType ReceiverType = RecExpr->getType();
+  
+  if (ReceiverType->isObjCIdType() || ReceiverType->isBlockPointerType()) {
+    // FIXME: We're messaging 'id'. Do we actually want to look up every method
+    // in the universe?
+    return;
+  }
+  
+  // Build the set of methods we can see.
+  ResultBuilder Results(*this);
+  Results.EnterNewScope();
+  
+  // Handle messages to Class. This really isn't a message to an instance
+  // method, so we treat it the same way we would treat a message send to a
+  // class method.
+  if (ReceiverType->isObjCClassType() || 
+      ReceiverType->isObjCQualifiedClassType()) {
+    if (ObjCMethodDecl *CurMethod = getCurMethodDecl()) {
+      if (ObjCInterfaceDecl *ClassDecl = CurMethod->getClassInterface())
+        AddObjCMethods(ClassDecl, false, MK_Any, SelIdents, NumSelIdents, 
+                       CurContext, Results);
+    }
+  } 
+  // Handle messages to a qualified ID ("id<foo>").
+  else if (const ObjCObjectPointerType *QualID
+             = ReceiverType->getAsObjCQualifiedIdType()) {
+    // Search protocols for instance methods.
+    for (ObjCObjectPointerType::qual_iterator I = QualID->qual_begin(),
+                                              E = QualID->qual_end(); 
+         I != E; ++I)
+      AddObjCMethods(*I, true, MK_Any, SelIdents, NumSelIdents, CurContext, 
+                     Results);
+  }
+  // Handle messages to a pointer to interface type.
+  else if (const ObjCObjectPointerType *IFacePtr
+                              = ReceiverType->getAsObjCInterfacePointerType()) {
+    // Search the class, its superclasses, etc., for instance methods.
+    AddObjCMethods(IFacePtr->getInterfaceDecl(), true, MK_Any, SelIdents,
+                   NumSelIdents, CurContext, Results);
+    
+    // Search protocols for instance methods.
+    for (ObjCObjectPointerType::qual_iterator I = IFacePtr->qual_begin(),
+         E = IFacePtr->qual_end(); 
+         I != E; ++I)
+      AddObjCMethods(*I, true, MK_Any, SelIdents, NumSelIdents, CurContext, 
+                     Results);
+  }
+  
+  Results.ExitScope();
+  HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size());
+}
+
+/// \brief Add all of the protocol declarations that we find in the given
+/// (translation unit) context.
+static void AddProtocolResults(DeclContext *Ctx, DeclContext *CurContext,
+                               bool OnlyForwardDeclarations,
+                               ResultBuilder &Results) {
+  typedef CodeCompleteConsumer::Result Result;
+  
+  for (DeclContext::decl_iterator D = Ctx->decls_begin(), 
+                               DEnd = Ctx->decls_end();
+       D != DEnd; ++D) {
+    // Record any protocols we find.
+    if (ObjCProtocolDecl *Proto = dyn_cast<ObjCProtocolDecl>(*D))
+      if (!OnlyForwardDeclarations || Proto->isForwardDecl())
+        Results.AddResult(Result(Proto, 0), CurContext, 0, false);
+
+    // Record any forward-declared protocols we find.
+    if (ObjCForwardProtocolDecl *Forward
+          = dyn_cast<ObjCForwardProtocolDecl>(*D)) {
+      for (ObjCForwardProtocolDecl::protocol_iterator 
+             P = Forward->protocol_begin(),
+             PEnd = Forward->protocol_end();
+           P != PEnd; ++P)
+        if (!OnlyForwardDeclarations || (*P)->isForwardDecl())
+          Results.AddResult(Result(*P, 0), CurContext, 0, false);
+    }
+  }
+}
+
+void Sema::CodeCompleteObjCProtocolReferences(IdentifierLocPair *Protocols,
+                                              unsigned NumProtocols) {
+  ResultBuilder Results(*this);
+  Results.EnterNewScope();
+  
+  // Tell the result set to ignore all of the protocols we have
+  // already seen.
+  for (unsigned I = 0; I != NumProtocols; ++I)
+    if (ObjCProtocolDecl *Protocol = LookupProtocol(Protocols[I].first))
+      Results.Ignore(Protocol);
+
+  // Add all protocols.
+  AddProtocolResults(Context.getTranslationUnitDecl(), CurContext, false,
+                     Results);
+
+  Results.ExitScope();
+  HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size());
+}
+
+void Sema::CodeCompleteObjCProtocolDecl(Scope *) {
+  ResultBuilder Results(*this);
+  Results.EnterNewScope();
+  
+  // Add all protocols.
+  AddProtocolResults(Context.getTranslationUnitDecl(), CurContext, true,
+                     Results);
+
+  Results.ExitScope();
+  HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size());
+}
+
+/// \brief Add all of the Objective-C interface declarations that we find in
+/// the given (translation unit) context.
+static void AddInterfaceResults(DeclContext *Ctx, DeclContext *CurContext,
+                                bool OnlyForwardDeclarations,
+                                bool OnlyUnimplemented,
+                                ResultBuilder &Results) {
+  typedef CodeCompleteConsumer::Result Result;
+  
+  for (DeclContext::decl_iterator D = Ctx->decls_begin(), 
+                               DEnd = Ctx->decls_end();
+       D != DEnd; ++D) {
+    // Record any interfaces we find.
+    if (ObjCInterfaceDecl *Class = dyn_cast<ObjCInterfaceDecl>(*D))
+      if ((!OnlyForwardDeclarations || Class->isForwardDecl()) &&
+          (!OnlyUnimplemented || !Class->getImplementation()))
+        Results.AddResult(Result(Class, 0), CurContext, 0, false);
+
+    // Record any forward-declared interfaces we find.
+    if (ObjCClassDecl *Forward = dyn_cast<ObjCClassDecl>(*D)) {
+      for (ObjCClassDecl::iterator C = Forward->begin(), CEnd = Forward->end();
+           C != CEnd; ++C)
+        if ((!OnlyForwardDeclarations || C->getInterface()->isForwardDecl()) &&
+            (!OnlyUnimplemented || !C->getInterface()->getImplementation()))
+          Results.AddResult(Result(C->getInterface(), 0), CurContext,
+                            0, false);
+    }
+  }
+}
+
+void Sema::CodeCompleteObjCInterfaceDecl(Scope *S) { 
+  ResultBuilder Results(*this);
+  Results.EnterNewScope();
+  
+  // Add all classes.
+  AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, true,
+                      false, Results);
+
+  Results.ExitScope();
+  HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size());
+}
+
+void Sema::CodeCompleteObjCSuperclass(Scope *S, IdentifierInfo *ClassName) { 
+  ResultBuilder Results(*this);
+  Results.EnterNewScope();
+  
+  // Make sure that we ignore the class we're currently defining.
+  NamedDecl *CurClass
+    = LookupSingleName(TUScope, ClassName, LookupOrdinaryName);
+  if (CurClass && isa<ObjCInterfaceDecl>(CurClass))
+    Results.Ignore(CurClass);
+
+  // Add all classes.
+  AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, false,
+                      false, Results);
+
+  Results.ExitScope();
+  HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size());
+}
+
+void Sema::CodeCompleteObjCImplementationDecl(Scope *S) { 
+  ResultBuilder Results(*this);
+  Results.EnterNewScope();
+
+  // Add all unimplemented classes.
+  AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, false,
+                      true, Results);
+
+  Results.ExitScope();
+  HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size());
+}
+
+void Sema::CodeCompleteObjCInterfaceCategory(Scope *S, 
+                                             IdentifierInfo *ClassName) {
+  typedef CodeCompleteConsumer::Result Result;
+  
+  ResultBuilder Results(*this);
+  
+  // Ignore any categories we find that have already been implemented by this
+  // interface.
+  llvm::SmallPtrSet<IdentifierInfo *, 16> CategoryNames;
+  NamedDecl *CurClass
+    = LookupSingleName(TUScope, ClassName, LookupOrdinaryName);
+  if (ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurClass))
+    for (ObjCCategoryDecl *Category = Class->getCategoryList(); Category;
+         Category = Category->getNextClassCategory())
+      CategoryNames.insert(Category->getIdentifier());
+  
+  // Add all of the categories we know about.
+  Results.EnterNewScope();
+  TranslationUnitDecl *TU = Context.getTranslationUnitDecl();
+  for (DeclContext::decl_iterator D = TU->decls_begin(), 
+                               DEnd = TU->decls_end();
+       D != DEnd; ++D) 
+    if (ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(*D))
+      if (CategoryNames.insert(Category->getIdentifier()))
+        Results.AddResult(Result(Category, 0), CurContext, 0, false);
+  Results.ExitScope();
+  
+  HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size());  
+}
+
+void Sema::CodeCompleteObjCImplementationCategory(Scope *S, 
+                                                  IdentifierInfo *ClassName) {
+  typedef CodeCompleteConsumer::Result Result;
+  
+  // Find the corresponding interface. If we couldn't find the interface, the
+  // program itself is ill-formed. However, we'll try to be helpful still by
+  // providing the list of all of the categories we know about.
+  NamedDecl *CurClass
+    = LookupSingleName(TUScope, ClassName, LookupOrdinaryName);
+  ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurClass);
+  if (!Class)
+    return CodeCompleteObjCInterfaceCategory(S, ClassName);
+    
+  ResultBuilder Results(*this);
+  
+  // Add all of the categories that have have corresponding interface 
+  // declarations in this class and any of its superclasses, except for
+  // already-implemented categories in the class itself.
+  llvm::SmallPtrSet<IdentifierInfo *, 16> CategoryNames;
+  Results.EnterNewScope();
+  bool IgnoreImplemented = true;
+  while (Class) {
+    for (ObjCCategoryDecl *Category = Class->getCategoryList(); Category;
+         Category = Category->getNextClassCategory())
+      if ((!IgnoreImplemented || !Category->getImplementation()) &&
+          CategoryNames.insert(Category->getIdentifier()))
+        Results.AddResult(Result(Category, 0), CurContext, 0, false);
+    
+    Class = Class->getSuperClass();
+    IgnoreImplemented = false;
+  }
+  Results.ExitScope();
+  
+  HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size());  
+}
+
+void Sema::CodeCompleteObjCPropertyDefinition(Scope *S, DeclPtrTy ObjCImpDecl) {
+  typedef CodeCompleteConsumer::Result Result;
+  ResultBuilder Results(*this);
+
+  // Figure out where this @synthesize lives.
+  ObjCContainerDecl *Container
+    = dyn_cast_or_null<ObjCContainerDecl>(ObjCImpDecl.getAs<Decl>());
+  if (!Container || 
+      (!isa<ObjCImplementationDecl>(Container) && 
+       !isa<ObjCCategoryImplDecl>(Container)))
+    return; 
+
+  // Ignore any properties that have already been implemented.
+  for (DeclContext::decl_iterator D = Container->decls_begin(), 
+                               DEnd = Container->decls_end();
+       D != DEnd; ++D)
+    if (ObjCPropertyImplDecl *PropertyImpl = dyn_cast<ObjCPropertyImplDecl>(*D))
+      Results.Ignore(PropertyImpl->getPropertyDecl());
+  
+  // Add any properties that we find.
+  Results.EnterNewScope();
+  if (ObjCImplementationDecl *ClassImpl
+        = dyn_cast<ObjCImplementationDecl>(Container))
+    AddObjCProperties(ClassImpl->getClassInterface(), false, CurContext, 
+                      Results);
+  else
+    AddObjCProperties(cast<ObjCCategoryImplDecl>(Container)->getCategoryDecl(),
+                      false, CurContext, Results);
+  Results.ExitScope();
+  
+  HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size());  
+}
+
+void Sema::CodeCompleteObjCPropertySynthesizeIvar(Scope *S, 
+                                                  IdentifierInfo *PropertyName,
+                                                  DeclPtrTy ObjCImpDecl) {
+  typedef CodeCompleteConsumer::Result Result;
+  ResultBuilder Results(*this);
+
+  // Figure out where this @synthesize lives.
+  ObjCContainerDecl *Container
+    = dyn_cast_or_null<ObjCContainerDecl>(ObjCImpDecl.getAs<Decl>());
+  if (!Container || 
+      (!isa<ObjCImplementationDecl>(Container) && 
+       !isa<ObjCCategoryImplDecl>(Container)))
+    return; 
+  
+  // Figure out which interface we're looking into.
+  ObjCInterfaceDecl *Class = 0;
+  if (ObjCImplementationDecl *ClassImpl
+                                 = dyn_cast<ObjCImplementationDecl>(Container))  
+    Class = ClassImpl->getClassInterface();
+  else
+    Class = cast<ObjCCategoryImplDecl>(Container)->getCategoryDecl()
+                                                          ->getClassInterface();
+
+  // Add all of the instance variables in this class and its superclasses.
+  Results.EnterNewScope();
+  for(; Class; Class = Class->getSuperClass()) {
+    // FIXME: We could screen the type of each ivar for compatibility with
+    // the property, but is that being too paternal?
+    for (ObjCInterfaceDecl::ivar_iterator IVar = Class->ivar_begin(),
+                                       IVarEnd = Class->ivar_end();
+         IVar != IVarEnd; ++IVar) 
+      Results.AddResult(Result(*IVar, 0), CurContext, 0, false);
+  }
+  Results.ExitScope();
+  
+  HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size());
+}
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
new file mode 100644
index 0000000..e12902b
--- /dev/null
+++ b/lib/Sema/SemaDecl.cpp
@@ -0,0 +1,6123 @@
+//===--- SemaDecl.cpp - Semantic Analysis for Declarations ----------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+//  This file implements semantic analysis for declarations.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Sema.h"
+#include "SemaInit.h"
+#include "Lookup.h"
+#include "clang/Analysis/AnalysisContext.h"
+#include "clang/AST/APValue.h"
+#include "clang/AST/ASTConsumer.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/CXXInheritance.h"
+#include "clang/AST/DeclTemplate.h"
+#include "clang/AST/ExprCXX.h"
+#include "clang/AST/StmtCXX.h"
+#include "clang/Parse/DeclSpec.h"
+#include "clang/Parse/ParseDiagnostic.h"
+#include "clang/Parse/Template.h"
+#include "clang/Basic/PartialDiagnostic.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Basic/TargetInfo.h"
+// FIXME: layering (ideally, Sema shouldn't be dependent on Lex API's)
+#include "clang/Lex/Preprocessor.h"
+#include "clang/Lex/HeaderSearch.h"
+#include "llvm/ADT/Triple.h"
+#include <algorithm>
+#include <cstring>
+#include <functional>
+using namespace clang;
+
+/// getDeclName - Return a pretty name for the specified decl if possible, or
+/// an empty string if not.  This is used for pretty crash reporting.
+std::string Sema::getDeclName(DeclPtrTy d) {
+  Decl *D = d.getAs<Decl>();
+  if (NamedDecl *DN = dyn_cast_or_null<NamedDecl>(D))
+    return DN->getQualifiedNameAsString();
+  return "";
+}
+
+Sema::DeclGroupPtrTy Sema::ConvertDeclToDeclGroup(DeclPtrTy Ptr) {
+  return DeclGroupPtrTy::make(DeclGroupRef(Ptr.getAs<Decl>()));
+}
+
+/// \brief If the identifier refers to a type name within this scope,
+/// return the declaration of that type.
+///
+/// This routine performs ordinary name lookup of the identifier II
+/// within the given scope, with optional C++ scope specifier SS, to
+/// determine whether the name refers to a type. If so, returns an
+/// opaque pointer (actually a QualType) corresponding to that
+/// type. Otherwise, returns NULL.
+///
+/// If name lookup results in an ambiguity, this routine will complain
+/// and then return NULL.
+Sema::TypeTy *Sema::getTypeName(IdentifierInfo &II, SourceLocation NameLoc,
+                                Scope *S, const CXXScopeSpec *SS,
+                                bool isClassName,
+                                TypeTy *ObjectTypePtr) {
+  // Determine where we will perform name lookup.
+  DeclContext *LookupCtx = 0;
+  if (ObjectTypePtr) {
+    QualType ObjectType = QualType::getFromOpaquePtr(ObjectTypePtr);
+    if (ObjectType->isRecordType())
+      LookupCtx = computeDeclContext(ObjectType);
+  } else if (SS && SS->isSet()) {
+    LookupCtx = computeDeclContext(*SS, false);
+
+    if (!LookupCtx) {
+      if (isDependentScopeSpecifier(*SS)) {
+        // C++ [temp.res]p3:
+        //   A qualified-id that refers to a type and in which the
+        //   nested-name-specifier depends on a template-parameter (14.6.2)
+        //   shall be prefixed by the keyword typename to indicate that the
+        //   qualified-id denotes a type, forming an
+        //   elaborated-type-specifier (7.1.5.3).
+        //
+        // We therefore do not perform any name lookup if the result would
+        // refer to a member of an unknown specialization.
+        if (!isClassName)
+          return 0;
+        
+        // We know from the grammar that this name refers to a type, so build a
+        // TypenameType node to describe the type.
+        // FIXME: Record somewhere that this TypenameType node has no "typename"
+        // keyword associated with it.
+        return CheckTypenameType((NestedNameSpecifier *)SS->getScopeRep(),
+                                 II, SS->getRange()).getAsOpaquePtr();
+      }
+      
+      return 0;
+    }
+    
+    if (!LookupCtx->isDependentContext() && RequireCompleteDeclContext(*SS))
+      return 0;
+  }
+
+  // FIXME: LookupNestedNameSpecifierName isn't the right kind of
+  // lookup for class-names.
+  LookupNameKind Kind = isClassName ? LookupNestedNameSpecifierName :
+                                      LookupOrdinaryName;
+  LookupResult Result(*this, &II, NameLoc, Kind);
+  if (LookupCtx) {
+    // Perform "qualified" name lookup into the declaration context we
+    // computed, which is either the type of the base of a member access
+    // expression or the declaration context associated with a prior
+    // nested-name-specifier.
+    LookupQualifiedName(Result, LookupCtx);
+
+    if (ObjectTypePtr && Result.empty()) {
+      // C++ [basic.lookup.classref]p3:
+      //   If the unqualified-id is ~type-name, the type-name is looked up
+      //   in the context of the entire postfix-expression. If the type T of 
+      //   the object expression is of a class type C, the type-name is also
+      //   looked up in the scope of class C. At least one of the lookups shall
+      //   find a name that refers to (possibly cv-qualified) T.
+      LookupName(Result, S);
+    }
+  } else {
+    // Perform unqualified name lookup.
+    LookupName(Result, S);
+  }
+  
+  NamedDecl *IIDecl = 0;
+  switch (Result.getResultKind()) {
+  case LookupResult::NotFound:
+  case LookupResult::NotFoundInCurrentInstantiation:
+  case LookupResult::FoundOverloaded:
+  case LookupResult::FoundUnresolvedValue:
+    Result.suppressDiagnostics();
+    return 0;
+
+  case LookupResult::Ambiguous:
+    // Recover from type-hiding ambiguities by hiding the type.  We'll
+    // do the lookup again when looking for an object, and we can
+    // diagnose the error then.  If we don't do this, then the error
+    // about hiding the type will be immediately followed by an error
+    // that only makes sense if the identifier was treated like a type.
+    if (Result.getAmbiguityKind() == LookupResult::AmbiguousTagHiding) {
+      Result.suppressDiagnostics();
+      return 0;
+    }
+
+    // Look to see if we have a type anywhere in the list of results.
+    for (LookupResult::iterator Res = Result.begin(), ResEnd = Result.end();
+         Res != ResEnd; ++Res) {
+      if (isa<TypeDecl>(*Res) || isa<ObjCInterfaceDecl>(*Res)) {
+        if (!IIDecl ||
+            (*Res)->getLocation().getRawEncoding() <
+              IIDecl->getLocation().getRawEncoding())
+          IIDecl = *Res;
+      }
+    }
+
+    if (!IIDecl) {
+      // None of the entities we found is a type, so there is no way
+      // to even assume that the result is a type. In this case, don't
+      // complain about the ambiguity. The parser will either try to
+      // perform this lookup again (e.g., as an object name), which
+      // will produce the ambiguity, or will complain that it expected
+      // a type name.
+      Result.suppressDiagnostics();
+      return 0;
+    }
+
+    // We found a type within the ambiguous lookup; diagnose the
+    // ambiguity and then return that type. This might be the right
+    // answer, or it might not be, but it suppresses any attempt to
+    // perform the name lookup again.
+    break;
+
+  case LookupResult::Found:
+    IIDecl = Result.getFoundDecl();
+    break;
+  }
+
+  assert(IIDecl && "Didn't find decl");
+
+  QualType T;
+  if (TypeDecl *TD = dyn_cast<TypeDecl>(IIDecl)) {
+    DiagnoseUseOfDecl(IIDecl, NameLoc);
+
+    // C++ [temp.local]p2:
+    //   Within the scope of a class template specialization or
+    //   partial specialization, when the injected-class-name is
+    //   not followed by a <, it is equivalent to the
+    //   injected-class-name followed by the template-argument s
+    //   of the class template specialization or partial
+    //   specialization enclosed in <>.
+    if (CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(TD))
+      if (RD->isInjectedClassName())
+        if (ClassTemplateDecl *Template = RD->getDescribedClassTemplate())
+          T = Template->getInjectedClassNameType(Context);
+
+    if (T.isNull())
+      T = Context.getTypeDeclType(TD);
+    
+    if (SS)
+      T = getQualifiedNameType(*SS, T);
+    
+  } else if (ObjCInterfaceDecl *IDecl = dyn_cast<ObjCInterfaceDecl>(IIDecl)) {
+    T = Context.getObjCInterfaceType(IDecl);
+  } else if (UnresolvedUsingTypenameDecl *UUDecl =
+               dyn_cast<UnresolvedUsingTypenameDecl>(IIDecl)) {
+    // FIXME: preserve source structure information.
+    T = Context.getTypenameType(UUDecl->getTargetNestedNameSpecifier(), &II);
+  } else {
+    // If it's not plausibly a type, suppress diagnostics.
+    Result.suppressDiagnostics();
+    return 0;
+  }
+
+  return T.getAsOpaquePtr();
+}
+
+/// isTagName() - This method is called *for error recovery purposes only*
+/// to determine if the specified name is a valid tag name ("struct foo").  If
+/// so, this returns the TST for the tag corresponding to it (TST_enum,
+/// TST_union, TST_struct, TST_class).  This is used to diagnose cases in C
+/// where the user forgot to specify the tag.
+DeclSpec::TST Sema::isTagName(IdentifierInfo &II, Scope *S) {
+  // Do a tag name lookup in this scope.
+  LookupResult R(*this, &II, SourceLocation(), LookupTagName);
+  LookupName(R, S, false);
+  R.suppressDiagnostics();
+  if (R.getResultKind() == LookupResult::Found)
+    if (const TagDecl *TD = R.getAsSingle<TagDecl>()) {
+      switch (TD->getTagKind()) {
+      case TagDecl::TK_struct: return DeclSpec::TST_struct;
+      case TagDecl::TK_union:  return DeclSpec::TST_union;
+      case TagDecl::TK_class:  return DeclSpec::TST_class;
+      case TagDecl::TK_enum:   return DeclSpec::TST_enum;
+      }
+    }
+
+  return DeclSpec::TST_unspecified;
+}
+
+bool Sema::DiagnoseUnknownTypeName(const IdentifierInfo &II, 
+                                   SourceLocation IILoc,
+                                   Scope *S,
+                                   const CXXScopeSpec *SS,
+                                   TypeTy *&SuggestedType) {
+  // We don't have anything to suggest (yet).
+  SuggestedType = 0;
+  
+  // There may have been a typo in the name of the type. Look up typo
+  // results, in case we have something that we can suggest.
+  LookupResult Lookup(*this, &II, IILoc, LookupOrdinaryName, 
+                      NotForRedeclaration);
+
+  // FIXME: It would be nice if we could correct for typos in built-in
+  // names, such as "itn" for "int".
+
+  if (CorrectTypo(Lookup, S, SS) && Lookup.isSingleResult()) {
+    NamedDecl *Result = Lookup.getAsSingle<NamedDecl>();
+    if ((isa<TypeDecl>(Result) || isa<ObjCInterfaceDecl>(Result)) &&
+        !Result->isInvalidDecl()) {
+      // We found a similarly-named type or interface; suggest that.
+      if (!SS || !SS->isSet())
+        Diag(IILoc, diag::err_unknown_typename_suggest)
+          << &II << Lookup.getLookupName()
+          << CodeModificationHint::CreateReplacement(SourceRange(IILoc),
+                                                     Result->getNameAsString());
+      else if (DeclContext *DC = computeDeclContext(*SS, false))
+        Diag(IILoc, diag::err_unknown_nested_typename_suggest) 
+          << &II << DC << Lookup.getLookupName() << SS->getRange()
+          << CodeModificationHint::CreateReplacement(SourceRange(IILoc),
+                                                     Result->getNameAsString());
+      else
+        llvm_unreachable("could not have corrected a typo here");
+
+      Diag(Result->getLocation(), diag::note_previous_decl)
+        << Result->getDeclName();
+      
+      SuggestedType = getTypeName(*Result->getIdentifier(), IILoc, S, SS);
+      return true;
+    }
+  }
+
+  // FIXME: Should we move the logic that tries to recover from a missing tag
+  // (struct, union, enum) from Parser::ParseImplicitInt here, instead?
+  
+  if (!SS || (!SS->isSet() && !SS->isInvalid()))
+    Diag(IILoc, diag::err_unknown_typename) << &II;
+  else if (DeclContext *DC = computeDeclContext(*SS, false))
+    Diag(IILoc, diag::err_typename_nested_not_found) 
+      << &II << DC << SS->getRange();
+  else if (isDependentScopeSpecifier(*SS)) {
+    Diag(SS->getRange().getBegin(), diag::err_typename_missing)
+      << (NestedNameSpecifier *)SS->getScopeRep() << II.getName()
+      << SourceRange(SS->getRange().getBegin(), IILoc)
+      << CodeModificationHint::CreateInsertion(SS->getRange().getBegin(),
+                                               "typename ");
+    SuggestedType = ActOnTypenameType(SourceLocation(), *SS, II, IILoc).get();
+  } else {
+    assert(SS && SS->isInvalid() && 
+           "Invalid scope specifier has already been diagnosed");
+  }
+  
+  return true;
+}
+
+// Determines the context to return to after temporarily entering a
+// context.  This depends in an unnecessarily complicated way on the
+// exact ordering of callbacks from the parser.
+DeclContext *Sema::getContainingDC(DeclContext *DC) {
+
+  // Functions defined inline within classes aren't parsed until we've
+  // finished parsing the top-level class, so the top-level class is
+  // the context we'll need to return to.
+  if (isa<FunctionDecl>(DC)) {
+    DC = DC->getLexicalParent();
+
+    // A function not defined within a class will always return to its
+    // lexical context.
+    if (!isa<CXXRecordDecl>(DC))
+      return DC;
+
+    // A C++ inline method/friend is parsed *after* the topmost class
+    // it was declared in is fully parsed ("complete");  the topmost
+    // class is the context we need to return to.
+    while (CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(DC->getLexicalParent()))
+      DC = RD;
+
+    // Return the declaration context of the topmost class the inline method is
+    // declared in.
+    return DC;
+  }
+
+  if (isa<ObjCMethodDecl>(DC))
+    return Context.getTranslationUnitDecl();
+
+  return DC->getLexicalParent();
+}
+
+void Sema::PushDeclContext(Scope *S, DeclContext *DC) {
+  assert(getContainingDC(DC) == CurContext &&
+      "The next DeclContext should be lexically contained in the current one.");
+  CurContext = DC;
+  S->setEntity(DC);
+}
+
+void Sema::PopDeclContext() {
+  assert(CurContext && "DeclContext imbalance!");
+
+  CurContext = getContainingDC(CurContext);
+}
+
+/// EnterDeclaratorContext - Used when we must lookup names in the context
+/// of a declarator's nested name specifier.
+///
+void Sema::EnterDeclaratorContext(Scope *S, DeclContext *DC) {
+  // C++0x [basic.lookup.unqual]p13:
+  //   A name used in the definition of a static data member of class
+  //   X (after the qualified-id of the static member) is looked up as
+  //   if the name was used in a member function of X.
+  // C++0x [basic.lookup.unqual]p14:
+  //   If a variable member of a namespace is defined outside of the
+  //   scope of its namespace then any name used in the definition of
+  //   the variable member (after the declarator-id) is looked up as
+  //   if the definition of the variable member occurred in its
+  //   namespace.
+  // Both of these imply that we should push a scope whose context
+  // is the semantic context of the declaration.  We can't use
+  // PushDeclContext here because that context is not necessarily
+  // lexically contained in the current context.  Fortunately,
+  // the containing scope should have the appropriate information.
+
+  assert(!S->getEntity() && "scope already has entity");
+
+#ifndef NDEBUG
+  Scope *Ancestor = S->getParent();
+  while (!Ancestor->getEntity()) Ancestor = Ancestor->getParent();
+  assert(Ancestor->getEntity() == CurContext && "ancestor context mismatch");
+#endif
+
+  CurContext = DC;
+  S->setEntity(DC);
+}
+
+void Sema::ExitDeclaratorContext(Scope *S) {
+  assert(S->getEntity() == CurContext && "Context imbalance!");
+
+  // Switch back to the lexical context.  The safety of this is
+  // enforced by an assert in EnterDeclaratorContext.
+  Scope *Ancestor = S->getParent();
+  while (!Ancestor->getEntity()) Ancestor = Ancestor->getParent();
+  CurContext = (DeclContext*) Ancestor->getEntity();
+
+  // We don't need to do anything with the scope, which is going to
+  // disappear.
+}
+
+/// \brief Determine whether we allow overloading of the function
+/// PrevDecl with another declaration.
+///
+/// This routine determines whether overloading is possible, not
+/// whether some new function is actually an overload. It will return
+/// true in C++ (where we can always provide overloads) or, as an
+/// extension, in C when the previous function is already an
+/// overloaded function declaration or has the "overloadable"
+/// attribute.
+static bool AllowOverloadingOfFunction(LookupResult &Previous,
+                                       ASTContext &Context) {
+  if (Context.getLangOptions().CPlusPlus)
+    return true;
+
+  if (Previous.getResultKind() == LookupResult::FoundOverloaded)
+    return true;
+
+  return (Previous.getResultKind() == LookupResult::Found
+          && Previous.getFoundDecl()->hasAttr<OverloadableAttr>());
+}
+
+/// Add this decl to the scope shadowed decl chains.
+void Sema::PushOnScopeChains(NamedDecl *D, Scope *S, bool AddToContext) {
+  // Move up the scope chain until we find the nearest enclosing
+  // non-transparent context. The declaration will be introduced into this
+  // scope.
+  while (S->getEntity() &&
+         ((DeclContext *)S->getEntity())->isTransparentContext())
+    S = S->getParent();
+
+  // Add scoped declarations into their context, so that they can be
+  // found later. Declarations without a context won't be inserted
+  // into any context.
+  if (AddToContext)
+    CurContext->addDecl(D);
+
+  // Out-of-line function and variable definitions should not be pushed into
+  // scope.
+  if ((isa<FunctionTemplateDecl>(D) &&
+       cast<FunctionTemplateDecl>(D)->getTemplatedDecl()->isOutOfLine()) ||
+      (isa<FunctionDecl>(D) &&
+       (cast<FunctionDecl>(D)->isFunctionTemplateSpecialization() ||
+        cast<FunctionDecl>(D)->isOutOfLine())) ||
+      (isa<VarDecl>(D) && cast<VarDecl>(D)->isOutOfLine()))
+    return;
+
+  // If this replaces anything in the current scope, 
+  IdentifierResolver::iterator I = IdResolver.begin(D->getDeclName()),
+                               IEnd = IdResolver.end();
+  for (; I != IEnd; ++I) {
+    if (S->isDeclScope(DeclPtrTy::make(*I)) && D->declarationReplaces(*I)) {
+      S->RemoveDecl(DeclPtrTy::make(*I));
+      IdResolver.RemoveDecl(*I);
+
+      // Should only need to replace one decl.
+      break;
+    }
+  }
+
+  S->AddDecl(DeclPtrTy::make(D));
+  IdResolver.AddDecl(D);
+}
+
+bool Sema::isDeclInScope(NamedDecl *&D, DeclContext *Ctx, Scope *S) {
+  return IdResolver.isDeclInScope(D, Ctx, Context, S);
+}
+
+static bool isOutOfScopePreviousDeclaration(NamedDecl *,
+                                            DeclContext*,
+                                            ASTContext&);
+
+/// Filters out lookup results that don't fall within the given scope
+/// as determined by isDeclInScope.
+static void FilterLookupForScope(Sema &SemaRef, LookupResult &R,
+                                 DeclContext *Ctx, Scope *S,
+                                 bool ConsiderLinkage) {
+  LookupResult::Filter F = R.makeFilter();
+  while (F.hasNext()) {
+    NamedDecl *D = F.next();
+
+    if (SemaRef.isDeclInScope(D, Ctx, S))
+      continue;
+
+    if (ConsiderLinkage &&
+        isOutOfScopePreviousDeclaration(D, Ctx, SemaRef.Context))
+      continue;
+    
+    F.erase();
+  }
+
+  F.done();
+}
+
+static bool isUsingDecl(NamedDecl *D) {
+  return isa<UsingShadowDecl>(D) ||
+         isa<UnresolvedUsingTypenameDecl>(D) ||
+         isa<UnresolvedUsingValueDecl>(D);
+}
+
+/// Removes using shadow declarations from the lookup results.
+static void RemoveUsingDecls(LookupResult &R) {
+  LookupResult::Filter F = R.makeFilter();
+  while (F.hasNext())
+    if (isUsingDecl(F.next()))
+      F.erase();
+
+  F.done();
+}
+
+static bool ShouldDiagnoseUnusedDecl(const NamedDecl *D) {
+  if (D->isInvalidDecl())
+    return false;
+
+  if (D->isUsed() || D->hasAttr<UnusedAttr>())
+    return false;
+
+  // White-list anything that isn't a local variable.
+  if (!isa<VarDecl>(D) || isa<ParmVarDecl>(D) || isa<ImplicitParamDecl>(D) ||
+      !D->getDeclContext()->isFunctionOrMethod())
+    return false;
+
+  // Types of valid local variables should be complete, so this should succeed.
+  if (const ValueDecl *VD = dyn_cast<ValueDecl>(D)) {
+    if (const RecordType *RT = VD->getType()->getAs<RecordType>()) {
+      if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(RT->getDecl())) {
+        if (!RD->hasTrivialConstructor())
+          return false;
+        if (!RD->hasTrivialDestructor())
+          return false;
+      }
+    }
+  }
+  
+  return true;
+}
+
+void Sema::ActOnPopScope(SourceLocation Loc, Scope *S) {
+  if (S->decl_empty()) return;
+  assert((S->getFlags() & (Scope::DeclScope | Scope::TemplateParamScope)) &&
+         "Scope shouldn't contain decls!");
+
+  for (Scope::decl_iterator I = S->decl_begin(), E = S->decl_end();
+       I != E; ++I) {
+    Decl *TmpD = (*I).getAs<Decl>();
+    assert(TmpD && "This decl didn't get pushed??");
+
+    assert(isa<NamedDecl>(TmpD) && "Decl isn't NamedDecl?");
+    NamedDecl *D = cast<NamedDecl>(TmpD);
+
+    if (!D->getDeclName()) continue;
+
+    // Diagnose unused variables in this scope.
+    if (ShouldDiagnoseUnusedDecl(D))
+      Diag(D->getLocation(), diag::warn_unused_variable) << D->getDeclName();
+    
+    // Remove this name from our lexical scope.
+    IdResolver.RemoveDecl(D);
+  }
+}
+
+/// getObjCInterfaceDecl - Look up a for a class declaration in the scope.
+/// return 0 if one not found.
+///
+/// \param Id the name of the Objective-C class we're looking for. If
+/// typo-correction fixes this name, the Id will be updated
+/// to the fixed name.
+///
+/// \param RecoverLoc if provided, this routine will attempt to
+/// recover from a typo in the name of an existing Objective-C class
+/// and, if successful, will return the lookup that results from
+/// typo-correction.
+ObjCInterfaceDecl *Sema::getObjCInterfaceDecl(IdentifierInfo *&Id,
+                                              SourceLocation RecoverLoc) {
+  // The third "scope" argument is 0 since we aren't enabling lazy built-in
+  // creation from this context.
+  NamedDecl *IDecl = LookupSingleName(TUScope, Id, LookupOrdinaryName);
+
+  if (!IDecl && !RecoverLoc.isInvalid()) {
+    // Perform typo correction at the given location, but only if we
+    // find an Objective-C class name.
+    LookupResult R(*this, Id, RecoverLoc, LookupOrdinaryName);
+    if (CorrectTypo(R, TUScope, 0) &&
+        (IDecl = R.getAsSingle<ObjCInterfaceDecl>())) {
+      Diag(RecoverLoc, diag::err_undef_interface_suggest)
+        << Id << IDecl->getDeclName() 
+        << CodeModificationHint::CreateReplacement(RecoverLoc, 
+                                                   IDecl->getNameAsString());
+      Diag(IDecl->getLocation(), diag::note_previous_decl)
+        << IDecl->getDeclName();
+      
+      Id = IDecl->getIdentifier();
+    }
+  }
+
+  return dyn_cast_or_null<ObjCInterfaceDecl>(IDecl);
+}
+
+/// getNonFieldDeclScope - Retrieves the innermost scope, starting
+/// from S, where a non-field would be declared. This routine copes
+/// with the difference between C and C++ scoping rules in structs and
+/// unions. For example, the following code is well-formed in C but
+/// ill-formed in C++:
+/// @code
+/// struct S6 {
+///   enum { BAR } e;
+/// };
+///
+/// void test_S6() {
+///   struct S6 a;
+///   a.e = BAR;
+/// }
+/// @endcode
+/// For the declaration of BAR, this routine will return a different
+/// scope. The scope S will be the scope of the unnamed enumeration
+/// within S6. In C++, this routine will return the scope associated
+/// with S6, because the enumeration's scope is a transparent
+/// context but structures can contain non-field names. In C, this
+/// routine will return the translation unit scope, since the
+/// enumeration's scope is a transparent context and structures cannot
+/// contain non-field names.
+Scope *Sema::getNonFieldDeclScope(Scope *S) {
+  while (((S->getFlags() & Scope::DeclScope) == 0) ||
+         (S->getEntity() &&
+          ((DeclContext *)S->getEntity())->isTransparentContext()) ||
+         (S->isClassScope() && !getLangOptions().CPlusPlus))
+    S = S->getParent();
+  return S;
+}
+
+void Sema::InitBuiltinVaListType() {
+  if (!Context.getBuiltinVaListType().isNull())
+    return;
+
+  IdentifierInfo *VaIdent = &Context.Idents.get("__builtin_va_list");
+  NamedDecl *VaDecl = LookupSingleName(TUScope, VaIdent, LookupOrdinaryName);
+  TypedefDecl *VaTypedef = cast<TypedefDecl>(VaDecl);
+  Context.setBuiltinVaListType(Context.getTypedefType(VaTypedef));
+}
+
+/// LazilyCreateBuiltin - The specified Builtin-ID was first used at
+/// file scope.  lazily create a decl for it. ForRedeclaration is true
+/// if we're creating this built-in in anticipation of redeclaring the
+/// built-in.
+NamedDecl *Sema::LazilyCreateBuiltin(IdentifierInfo *II, unsigned bid,
+                                     Scope *S, bool ForRedeclaration,
+                                     SourceLocation Loc) {
+  Builtin::ID BID = (Builtin::ID)bid;
+
+  if (Context.BuiltinInfo.hasVAListUse(BID))
+    InitBuiltinVaListType();
+
+  ASTContext::GetBuiltinTypeError Error;
+  QualType R = Context.GetBuiltinType(BID, Error);
+  switch (Error) {
+  case ASTContext::GE_None:
+    // Okay
+    break;
+
+  case ASTContext::GE_Missing_stdio:
+    if (ForRedeclaration)
+      Diag(Loc, diag::err_implicit_decl_requires_stdio)
+        << Context.BuiltinInfo.GetName(BID);
+    return 0;
+
+  case ASTContext::GE_Missing_setjmp:
+    if (ForRedeclaration)
+      Diag(Loc, diag::err_implicit_decl_requires_setjmp)
+        << Context.BuiltinInfo.GetName(BID);
+    return 0;
+  }
+
+  if (!ForRedeclaration && Context.BuiltinInfo.isPredefinedLibFunction(BID)) {
+    Diag(Loc, diag::ext_implicit_lib_function_decl)
+      << Context.BuiltinInfo.GetName(BID)
+      << R;
+    if (Context.BuiltinInfo.getHeaderName(BID) &&
+        Diags.getDiagnosticLevel(diag::ext_implicit_lib_function_decl)
+          != Diagnostic::Ignored)
+      Diag(Loc, diag::note_please_include_header)
+        << Context.BuiltinInfo.getHeaderName(BID)
+        << Context.BuiltinInfo.GetName(BID);
+  }
+
+  FunctionDecl *New = FunctionDecl::Create(Context,
+                                           Context.getTranslationUnitDecl(),
+                                           Loc, II, R, /*TInfo=*/0,
+                                           FunctionDecl::Extern, false,
+                                           /*hasPrototype=*/true);
+  New->setImplicit();
+
+  // Create Decl objects for each parameter, adding them to the
+  // FunctionDecl.
+  if (FunctionProtoType *FT = dyn_cast<FunctionProtoType>(R)) {
+    llvm::SmallVector<ParmVarDecl*, 16> Params;
+    for (unsigned i = 0, e = FT->getNumArgs(); i != e; ++i)
+      Params.push_back(ParmVarDecl::Create(Context, New, SourceLocation(), 0,
+                                           FT->getArgType(i), /*TInfo=*/0,
+                                           VarDecl::None, 0));
+    New->setParams(Context, Params.data(), Params.size());
+  }
+
+  AddKnownFunctionAttributes(New);
+
+  // TUScope is the translation-unit scope to insert this function into.
+  // FIXME: This is hideous. We need to teach PushOnScopeChains to
+  // relate Scopes to DeclContexts, and probably eliminate CurContext
+  // entirely, but we're not there yet.
+  DeclContext *SavedContext = CurContext;
+  CurContext = Context.getTranslationUnitDecl();
+  PushOnScopeChains(New, TUScope);
+  CurContext = SavedContext;
+  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. If there was an error, set New to be invalid.
+///
+void Sema::MergeTypeDefDecl(TypedefDecl *New, LookupResult &OldDecls) {
+  // If the new decl is known invalid already, don't bother doing any
+  // merging checks.
+  if (New->isInvalidDecl()) return;
+
+  // Allow multiple definitions for ObjC built-in typedefs.
+  // FIXME: Verify the underlying types are equivalent!
+  if (getLangOptions().ObjC1) {
+    const IdentifierInfo *TypeID = New->getIdentifier();
+    switch (TypeID->getLength()) {
+    default: break;
+    case 2:
+      if (!TypeID->isStr("id"))
+        break;
+      Context.ObjCIdRedefinitionType = New->getUnderlyingType();
+      // Install the built-in type for 'id', ignoring the current definition.
+      New->setTypeForDecl(Context.getObjCIdType().getTypePtr());
+      return;
+    case 5:
+      if (!TypeID->isStr("Class"))
+        break;
+      Context.ObjCClassRedefinitionType = New->getUnderlyingType();
+      // Install the built-in type for 'Class', ignoring the current definition.
+      New->setTypeForDecl(Context.getObjCClassType().getTypePtr());
+      return;
+    case 3:
+      if (!TypeID->isStr("SEL"))
+        break;
+      Context.ObjCSelRedefinitionType = New->getUnderlyingType();
+      // Install the built-in type for 'SEL', ignoring the current definition.
+      New->setTypeForDecl(Context.getObjCSelType().getTypePtr());
+      return;
+    case 8:
+      if (!TypeID->isStr("Protocol"))
+        break;
+      Context.setObjCProtoType(New->getUnderlyingType());
+      return;
+    }
+    // Fall through - the typedef name was not a builtin type.
+  }
+
+  // Verify the old decl was also a type.
+  TypeDecl *Old = OldDecls.getAsSingle<TypeDecl>();
+  if (!Old) {
+    Diag(New->getLocation(), diag::err_redefinition_different_kind)
+      << New->getDeclName();
+
+    NamedDecl *OldD = OldDecls.getRepresentativeDecl();
+    if (OldD->getLocation().isValid())
+      Diag(OldD->getLocation(), diag::note_previous_definition);
+
+    return New->setInvalidDecl();
+  }
+
+  // If the old declaration is invalid, just give up here.
+  if (Old->isInvalidDecl())
+    return New->setInvalidDecl();
+
+  // Determine the "old" type we'll use for checking and diagnostics.
+  QualType OldType;
+  if (TypedefDecl *OldTypedef = dyn_cast<TypedefDecl>(Old))
+    OldType = OldTypedef->getUnderlyingType();
+  else
+    OldType = Context.getTypeDeclType(Old);
+
+  // If the typedef types are not identical, reject them in all languages and
+  // with any extensions enabled.
+
+  if (OldType != New->getUnderlyingType() &&
+      Context.getCanonicalType(OldType) !=
+      Context.getCanonicalType(New->getUnderlyingType())) {
+    Diag(New->getLocation(), diag::err_redefinition_different_typedef)
+      << New->getUnderlyingType() << OldType;
+    if (Old->getLocation().isValid())
+      Diag(Old->getLocation(), diag::note_previous_definition);
+    return New->setInvalidDecl();
+  }
+
+  // The types match.  Link up the redeclaration chain if the old
+  // declaration was a typedef.
+  // FIXME: this is a potential source of wierdness if the type
+  // spellings don't match exactly.
+  if (isa<TypedefDecl>(Old))
+    New->setPreviousDeclaration(cast<TypedefDecl>(Old));
+
+  if (getLangOptions().Microsoft)
+    return;
+
+  if (getLangOptions().CPlusPlus) {
+    // C++ [dcl.typedef]p2:
+    //   In a given non-class scope, a typedef specifier can be used to
+    //   redefine the name of any type declared in that scope to refer
+    //   to the type to which it already refers.
+    if (!isa<CXXRecordDecl>(CurContext))
+      return;
+
+    // C++0x [dcl.typedef]p4:
+    //   In a given class scope, a typedef specifier can be used to redefine 
+    //   any class-name declared in that scope that is not also a typedef-name
+    //   to refer to the type to which it already refers.
+    //
+    // This wording came in via DR424, which was a correction to the
+    // wording in DR56, which accidentally banned code like:
+    //
+    //   struct S {
+    //     typedef struct A { } A;
+    //   };
+    //
+    // in the C++03 standard. We implement the C++0x semantics, which
+    // allow the above but disallow
+    //
+    //   struct S {
+    //     typedef int I;
+    //     typedef int I;
+    //   };
+    //
+    // since that was the intent of DR56.
+    if (!isa<TypedefDecl >(Old))
+      return;
+
+    Diag(New->getLocation(), diag::err_redefinition)
+      << New->getDeclName();
+    Diag(Old->getLocation(), diag::note_previous_definition);
+    return New->setInvalidDecl();
+  }
+
+  // If we have a redefinition of a typedef in C, emit a warning.  This warning
+  // is normally mapped to an error, but can be controlled with
+  // -Wtypedef-redefinition.  If either the original or the redefinition is
+  // in a system header, don't emit this for compatibility with GCC.
+  if (PP.getDiagnostics().getSuppressSystemWarnings() &&
+      (Context.getSourceManager().isInSystemHeader(Old->getLocation()) ||
+       Context.getSourceManager().isInSystemHeader(New->getLocation())))
+    return;
+
+  Diag(New->getLocation(), diag::warn_redefinition_of_typedef)
+    << New->getDeclName();
+  Diag(Old->getLocation(), diag::note_previous_definition);
+  return;
+}
+
+/// DeclhasAttr - returns true if decl Declaration already has the target
+/// attribute.
+static bool
+DeclHasAttr(const Decl *decl, const Attr *target) {
+  for (const Attr *attr = decl->getAttrs(); attr; attr = attr->getNext())
+    if (attr->getKind() == target->getKind())
+      return true;
+
+  return false;
+}
+
+/// MergeAttributes - append attributes from the Old decl to the New one.
+static void MergeAttributes(Decl *New, Decl *Old, ASTContext &C) {
+  for (const Attr *attr = Old->getAttrs(); attr; attr = attr->getNext()) {
+    if (!DeclHasAttr(New, attr) && attr->isMerged()) {
+      Attr *NewAttr = attr->clone(C);
+      NewAttr->setInherited(true);
+      New->addAttr(NewAttr);
+    }
+  }
+}
+
+/// Used in MergeFunctionDecl to keep track of function parameters in
+/// C.
+struct GNUCompatibleParamWarning {
+  ParmVarDecl *OldParm;
+  ParmVarDecl *NewParm;
+  QualType PromotedType;
+};
+
+
+/// getSpecialMember - get the special member enum for a method.
+static Sema::CXXSpecialMember getSpecialMember(ASTContext &Ctx,
+                                               const CXXMethodDecl *MD) {
+  if (const CXXConstructorDecl *Ctor = dyn_cast<CXXConstructorDecl>(MD)) {
+    if (Ctor->isDefaultConstructor())
+      return Sema::CXXDefaultConstructor;
+    if (Ctor->isCopyConstructor())
+      return Sema::CXXCopyConstructor;
+  } 
+  
+  if (isa<CXXDestructorDecl>(MD))
+    return Sema::CXXDestructor;
+  
+  assert(MD->isCopyAssignment() && "Must have copy assignment operator");
+  return Sema::CXXCopyAssignment;
+}
+
+/// MergeFunctionDecl - We just parsed a function 'New' from
+/// declarator D 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.
+///
+/// In C++, New and Old must be declarations that are not
+/// overloaded. Use IsOverload to determine whether New and Old are
+/// overloaded, and to select the Old declaration that New should be
+/// merged with.
+///
+/// Returns true if there was an error, false otherwise.
+bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD) {
+  // Verify the old decl was also a function.
+  FunctionDecl *Old = 0;
+  if (FunctionTemplateDecl *OldFunctionTemplate
+        = dyn_cast<FunctionTemplateDecl>(OldD))
+    Old = OldFunctionTemplate->getTemplatedDecl();
+  else
+    Old = dyn_cast<FunctionDecl>(OldD);
+  if (!Old) {
+    if (UsingShadowDecl *Shadow = dyn_cast<UsingShadowDecl>(OldD)) {
+      Diag(New->getLocation(), diag::err_using_decl_conflict_reverse);
+      Diag(Shadow->getTargetDecl()->getLocation(),
+           diag::note_using_decl_target);
+      Diag(Shadow->getUsingDecl()->getLocation(),
+           diag::note_using_decl) << 0;
+      return true;
+    }
+
+    Diag(New->getLocation(), diag::err_redefinition_different_kind)
+      << New->getDeclName();
+    Diag(OldD->getLocation(), diag::note_previous_definition);
+    return true;
+  }
+
+  // Determine whether the previous declaration was a definition,
+  // implicit declaration, or a declaration.
+  diag::kind PrevDiag;
+  if (Old->isThisDeclarationADefinition())
+    PrevDiag = diag::note_previous_definition;
+  else if (Old->isImplicit())
+    PrevDiag = diag::note_previous_implicit_declaration;
+  else
+    PrevDiag = diag::note_previous_declaration;
+
+  QualType OldQType = Context.getCanonicalType(Old->getType());
+  QualType NewQType = Context.getCanonicalType(New->getType());
+
+  if (!isa<CXXMethodDecl>(New) && !isa<CXXMethodDecl>(Old) &&
+      New->getStorageClass() == FunctionDecl::Static &&
+      Old->getStorageClass() != FunctionDecl::Static) {
+    Diag(New->getLocation(), diag::err_static_non_static)
+      << New;
+    Diag(Old->getLocation(), PrevDiag);
+    return true;
+  }
+
+  // If a function is first declared with a calling convention, but is
+  // later declared or defined without one, the second decl assumes the
+  // calling convention of the first.
+  //
+  // For the new decl, we have to look at the NON-canonical type to tell the
+  // difference between a function that really doesn't have a calling
+  // convention and one that is declared cdecl. That's because in
+  // canonicalization (see ASTContext.cpp), cdecl is canonicalized away
+  // because it is the default calling convention.
+  //
+  // Note also that we DO NOT return at this point, because we still have
+  // other tests to run.
+  const FunctionType *OldType = OldQType->getAs<FunctionType>();
+  const FunctionType *NewType = New->getType()->getAs<FunctionType>();
+  if (OldType->getCallConv() != CC_Default &&
+      NewType->getCallConv() == CC_Default) {
+    NewQType = Context.getCallConvType(NewQType, OldType->getCallConv());
+    New->setType(NewQType);
+    NewQType = Context.getCanonicalType(NewQType);
+  } else if (!Context.isSameCallConv(OldType->getCallConv(),
+                                     NewType->getCallConv())) {
+    // Calling conventions really aren't compatible, so complain.
+    Diag(New->getLocation(), diag::err_cconv_change)
+      << FunctionType::getNameForCallConv(NewType->getCallConv())
+      << (OldType->getCallConv() == CC_Default)
+      << (OldType->getCallConv() == CC_Default ? "" :
+          FunctionType::getNameForCallConv(OldType->getCallConv()));
+    Diag(Old->getLocation(), diag::note_previous_declaration);
+    return true;
+  }
+
+  // FIXME: diagnose the other way around?
+  if (OldType->getNoReturnAttr() && !NewType->getNoReturnAttr()) {
+    NewQType = Context.getNoReturnType(NewQType);
+    New->setType(NewQType);
+    assert(NewQType.isCanonical());
+  }
+
+  if (getLangOptions().CPlusPlus) {
+    // (C++98 13.1p2):
+    //   Certain function declarations cannot be overloaded:
+    //     -- Function declarations that differ only in the return type
+    //        cannot be overloaded.
+    QualType OldReturnType
+      = cast<FunctionType>(OldQType.getTypePtr())->getResultType();
+    QualType NewReturnType
+      = cast<FunctionType>(NewQType.getTypePtr())->getResultType();
+    if (OldReturnType != NewReturnType) {
+      Diag(New->getLocation(), diag::err_ovl_diff_return_type);
+      Diag(Old->getLocation(), PrevDiag) << Old << Old->getType();
+      return true;
+    }
+
+    const CXXMethodDecl* OldMethod = dyn_cast<CXXMethodDecl>(Old);
+    const CXXMethodDecl* NewMethod = dyn_cast<CXXMethodDecl>(New);
+    if (OldMethod && NewMethod) {
+      if (!NewMethod->getFriendObjectKind() &&
+          NewMethod->getLexicalDeclContext()->isRecord()) {
+        //    -- Member function declarations with the same name and the
+        //       same parameter types cannot be overloaded if any of them
+        //       is a static member function declaration.
+        if (OldMethod->isStatic() || NewMethod->isStatic()) {
+          Diag(New->getLocation(), diag::err_ovl_static_nonstatic_member);
+          Diag(Old->getLocation(), PrevDiag) << Old << Old->getType();
+          return true;
+        }
+      
+        // C++ [class.mem]p1:
+        //   [...] A member shall not be declared twice in the
+        //   member-specification, except that a nested class or member
+        //   class template can be declared and then later defined.
+        unsigned NewDiag;
+        if (isa<CXXConstructorDecl>(OldMethod))
+          NewDiag = diag::err_constructor_redeclared;
+        else if (isa<CXXDestructorDecl>(NewMethod))
+          NewDiag = diag::err_destructor_redeclared;
+        else if (isa<CXXConversionDecl>(NewMethod))
+          NewDiag = diag::err_conv_function_redeclared;
+        else
+          NewDiag = diag::err_member_redeclared;
+
+        Diag(New->getLocation(), NewDiag);
+        Diag(Old->getLocation(), PrevDiag) << Old << Old->getType();
+      } else {
+        if (OldMethod->isImplicit()) {
+          Diag(NewMethod->getLocation(),
+               diag::err_definition_of_implicitly_declared_member) 
+          << New << getSpecialMember(Context, OldMethod);
+        
+          Diag(OldMethod->getLocation(),
+               diag::note_previous_implicit_declaration);
+          return true;
+        }
+      }
+    }
+
+    // (C++98 8.3.5p3):
+    //   All declarations for a function shall agree exactly in both the
+    //   return type and the parameter-type-list.
+    // attributes should be ignored when comparing.
+    if (Context.getNoReturnType(OldQType, false) ==
+        Context.getNoReturnType(NewQType, false))
+      return MergeCompatibleFunctionDecls(New, Old);
+
+    // Fall through for conflicting redeclarations and redefinitions.
+  }
+
+  // C: Function types need to be compatible, not identical. This handles
+  // duplicate function decls like "void f(int); void f(enum X);" properly.
+  if (!getLangOptions().CPlusPlus &&
+      Context.typesAreCompatible(OldQType, NewQType)) {
+    const FunctionType *OldFuncType = OldQType->getAs<FunctionType>();
+    const FunctionType *NewFuncType = NewQType->getAs<FunctionType>();
+    const FunctionProtoType *OldProto = 0;
+    if (isa<FunctionNoProtoType>(NewFuncType) &&
+        (OldProto = dyn_cast<FunctionProtoType>(OldFuncType))) {
+      // The old declaration provided a function prototype, but the
+      // new declaration does not. Merge in the prototype.
+      assert(!OldProto->hasExceptionSpec() && "Exception spec in C");
+      llvm::SmallVector<QualType, 16> ParamTypes(OldProto->arg_type_begin(),
+                                                 OldProto->arg_type_end());
+      NewQType = Context.getFunctionType(NewFuncType->getResultType(),
+                                         ParamTypes.data(), ParamTypes.size(),
+                                         OldProto->isVariadic(),
+                                         OldProto->getTypeQuals());
+      New->setType(NewQType);
+      New->setHasInheritedPrototype();
+
+      // Synthesize a parameter for each argument type.
+      llvm::SmallVector<ParmVarDecl*, 16> Params;
+      for (FunctionProtoType::arg_type_iterator
+             ParamType = OldProto->arg_type_begin(),
+             ParamEnd = OldProto->arg_type_end();
+           ParamType != ParamEnd; ++ParamType) {
+        ParmVarDecl *Param = ParmVarDecl::Create(Context, New,
+                                                 SourceLocation(), 0,
+                                                 *ParamType, /*TInfo=*/0,
+                                                 VarDecl::None, 0);
+        Param->setImplicit();
+        Params.push_back(Param);
+      }
+
+      New->setParams(Context, Params.data(), Params.size());
+    }
+
+    return MergeCompatibleFunctionDecls(New, Old);
+  }
+
+  // GNU C permits a K&R definition to follow a prototype declaration
+  // if the declared types of the parameters in the K&R definition
+  // match the types in the prototype declaration, even when the
+  // promoted types of the parameters from the K&R definition differ
+  // from the types in the prototype. GCC then keeps the types from
+  // the prototype.
+  //
+  // If a variadic prototype is followed by a non-variadic K&R definition,
+  // the K&R definition becomes variadic.  This is sort of an edge case, but
+  // it's legal per the standard depending on how you read C99 6.7.5.3p15 and
+  // C99 6.9.1p8.
+  if (!getLangOptions().CPlusPlus &&
+      Old->hasPrototype() && !New->hasPrototype() &&
+      New->getType()->getAs<FunctionProtoType>() &&
+      Old->getNumParams() == New->getNumParams()) {
+    llvm::SmallVector<QualType, 16> ArgTypes;
+    llvm::SmallVector<GNUCompatibleParamWarning, 16> Warnings;
+    const FunctionProtoType *OldProto
+      = Old->getType()->getAs<FunctionProtoType>();
+    const FunctionProtoType *NewProto
+      = New->getType()->getAs<FunctionProtoType>();
+
+    // Determine whether this is the GNU C extension.
+    QualType MergedReturn = Context.mergeTypes(OldProto->getResultType(),
+                                               NewProto->getResultType());
+    bool LooseCompatible = !MergedReturn.isNull();
+    for (unsigned Idx = 0, End = Old->getNumParams();
+         LooseCompatible && Idx != End; ++Idx) {
+      ParmVarDecl *OldParm = Old->getParamDecl(Idx);
+      ParmVarDecl *NewParm = New->getParamDecl(Idx);
+      if (Context.typesAreCompatible(OldParm->getType(),
+                                     NewProto->getArgType(Idx))) {
+        ArgTypes.push_back(NewParm->getType());
+      } else if (Context.typesAreCompatible(OldParm->getType(),
+                                            NewParm->getType())) {
+        GNUCompatibleParamWarning Warn
+          = { OldParm, NewParm, NewProto->getArgType(Idx) };
+        Warnings.push_back(Warn);
+        ArgTypes.push_back(NewParm->getType());
+      } else
+        LooseCompatible = false;
+    }
+
+    if (LooseCompatible) {
+      for (unsigned Warn = 0; Warn < Warnings.size(); ++Warn) {
+        Diag(Warnings[Warn].NewParm->getLocation(),
+             diag::ext_param_promoted_not_compatible_with_prototype)
+          << Warnings[Warn].PromotedType
+          << Warnings[Warn].OldParm->getType();
+        Diag(Warnings[Warn].OldParm->getLocation(),
+             diag::note_previous_declaration);
+      }
+
+      New->setType(Context.getFunctionType(MergedReturn, &ArgTypes[0],
+                                           ArgTypes.size(),
+                                           OldProto->isVariadic(), 0));
+      return MergeCompatibleFunctionDecls(New, Old);
+    }
+
+    // Fall through to diagnose conflicting types.
+  }
+
+  // A function that has already been declared has been redeclared or defined
+  // with a different type- show appropriate diagnostic
+  if (unsigned BuiltinID = Old->getBuiltinID()) {
+    // The user has declared a builtin function with an incompatible
+    // signature.
+    if (Context.BuiltinInfo.isPredefinedLibFunction(BuiltinID)) {
+      // The function the user is redeclaring is a library-defined
+      // function like 'malloc' or 'printf'. Warn about the
+      // redeclaration, then pretend that we don't know about this
+      // library built-in.
+      Diag(New->getLocation(), diag::warn_redecl_library_builtin) << New;
+      Diag(Old->getLocation(), diag::note_previous_builtin_declaration)
+        << Old << Old->getType();
+      New->getIdentifier()->setBuiltinID(Builtin::NotBuiltin);
+      Old->setInvalidDecl();
+      return false;
+    }
+
+    PrevDiag = diag::note_previous_builtin_declaration;
+  }
+
+  Diag(New->getLocation(), diag::err_conflicting_types) << New->getDeclName();
+  Diag(Old->getLocation(), PrevDiag) << Old << Old->getType();
+  return true;
+}
+
+/// \brief Completes the merge of two function declarations that are
+/// known to be compatible.
+///
+/// This routine handles the merging of attributes and other
+/// properties of function declarations form the old declaration to
+/// the new declaration, once we know that New is in fact a
+/// redeclaration of Old.
+///
+/// \returns false
+bool Sema::MergeCompatibleFunctionDecls(FunctionDecl *New, FunctionDecl *Old) {
+  // Merge the attributes
+  MergeAttributes(New, Old, Context);
+
+  // Merge the storage class.
+  if (Old->getStorageClass() != FunctionDecl::Extern &&
+      Old->getStorageClass() != FunctionDecl::None)
+    New->setStorageClass(Old->getStorageClass());
+
+  // Merge "pure" flag.
+  if (Old->isPure())
+    New->setPure();
+
+  // Merge the "deleted" flag.
+  if (Old->isDeleted())
+    New->setDeleted();
+
+  if (getLangOptions().CPlusPlus)
+    return MergeCXXFunctionDecl(New, Old);
+
+  return false;
+}
+
+/// 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.
+///
+/// Tentative definition rules (C99 6.9.2p2) are checked by
+/// FinalizeDeclaratorGroup. Unfortunately, we can't analyze tentative
+/// definitions here, since the initializer hasn't been attached.
+///
+void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous) {
+  // If the new decl is already invalid, don't do any other checking.
+  if (New->isInvalidDecl())
+    return;
+
+  // Verify the old decl was also a variable.
+  VarDecl *Old = 0;
+  if (!Previous.isSingleResult() ||
+      !(Old = dyn_cast<VarDecl>(Previous.getFoundDecl()))) {
+    Diag(New->getLocation(), diag::err_redefinition_different_kind)
+      << New->getDeclName();
+    Diag(Previous.getRepresentativeDecl()->getLocation(),
+         diag::note_previous_definition);
+    return New->setInvalidDecl();
+  }
+
+  MergeAttributes(New, Old, Context);
+
+  // Merge the types
+  QualType MergedT;
+  if (getLangOptions().CPlusPlus) {
+    if (Context.hasSameType(New->getType(), Old->getType()))
+      MergedT = New->getType();
+    // C++ [basic.link]p10:
+    //   [...] the types specified by all declarations referring to a given
+    //   object or function shall be identical, except that declarations for an
+    //   array object can specify array types that differ by the presence or
+    //   absence of a major array bound (8.3.4).
+    else if (Old->getType()->isIncompleteArrayType() &&
+             New->getType()->isArrayType()) {
+      CanQual<ArrayType> OldArray
+        = Context.getCanonicalType(Old->getType())->getAs<ArrayType>();
+      CanQual<ArrayType> NewArray
+        = Context.getCanonicalType(New->getType())->getAs<ArrayType>();
+      if (OldArray->getElementType() == NewArray->getElementType())
+        MergedT = New->getType();
+    } else if (Old->getType()->isArrayType() &&
+             New->getType()->isIncompleteArrayType()) {
+      CanQual<ArrayType> OldArray
+        = Context.getCanonicalType(Old->getType())->getAs<ArrayType>();
+      CanQual<ArrayType> NewArray
+        = Context.getCanonicalType(New->getType())->getAs<ArrayType>();
+      if (OldArray->getElementType() == NewArray->getElementType())
+        MergedT = Old->getType();
+    }
+  } else {
+    MergedT = Context.mergeTypes(New->getType(), Old->getType());
+  }
+  if (MergedT.isNull()) {
+    Diag(New->getLocation(), diag::err_redefinition_different_type)
+      << New->getDeclName();
+    Diag(Old->getLocation(), diag::note_previous_definition);
+    return New->setInvalidDecl();
+  }
+  New->setType(MergedT);
+
+  // C99 6.2.2p4: Check if we have a static decl followed by a non-static.
+  if (New->getStorageClass() == VarDecl::Static &&
+      (Old->getStorageClass() == VarDecl::None || Old->hasExternalStorage())) {
+    Diag(New->getLocation(), diag::err_static_non_static) << New->getDeclName();
+    Diag(Old->getLocation(), diag::note_previous_definition);
+    return New->setInvalidDecl();
+  }
+  // C99 6.2.2p4:
+  //   For an identifier declared with the storage-class specifier
+  //   extern in a scope in which a prior declaration of that
+  //   identifier is visible,23) if the prior declaration specifies
+  //   internal or external linkage, the linkage of the identifier at
+  //   the later declaration is the same as the linkage specified at
+  //   the prior declaration. If no prior declaration is visible, or
+  //   if the prior declaration specifies no linkage, then the
+  //   identifier has external linkage.
+  if (New->hasExternalStorage() && Old->hasLinkage())
+    /* Okay */;
+  else if (New->getStorageClass() != VarDecl::Static &&
+           Old->getStorageClass() == VarDecl::Static) {
+    Diag(New->getLocation(), diag::err_non_static_static) << New->getDeclName();
+    Diag(Old->getLocation(), diag::note_previous_definition);
+    return New->setInvalidDecl();
+  }
+
+  // Variables with external linkage are analyzed in FinalizeDeclaratorGroup.
+
+  // FIXME: The test for external storage here seems wrong? We still
+  // need to check for mismatches.
+  if (!New->hasExternalStorage() && !New->isFileVarDecl() &&
+      // Don't complain about out-of-line definitions of static members.
+      !(Old->getLexicalDeclContext()->isRecord() &&
+        !New->getLexicalDeclContext()->isRecord())) {
+    Diag(New->getLocation(), diag::err_redefinition) << New->getDeclName();
+    Diag(Old->getLocation(), diag::note_previous_definition);
+    return New->setInvalidDecl();
+  }
+
+  if (New->isThreadSpecified() && !Old->isThreadSpecified()) {
+    Diag(New->getLocation(), diag::err_thread_non_thread) << New->getDeclName();
+    Diag(Old->getLocation(), diag::note_previous_definition);
+  } else if (!New->isThreadSpecified() && Old->isThreadSpecified()) {
+    Diag(New->getLocation(), diag::err_non_thread_thread) << New->getDeclName();
+    Diag(Old->getLocation(), diag::note_previous_definition);
+  }
+
+  // C++ doesn't have tentative definitions, so go right ahead and check here.
+  const VarDecl *Def;
+  if (getLangOptions().CPlusPlus &&
+      New->isThisDeclarationADefinition() == VarDecl::Definition &&
+      (Def = Old->getDefinition())) {
+    Diag(New->getLocation(), diag::err_redefinition)
+      << New->getDeclName();
+    Diag(Def->getLocation(), diag::note_previous_definition);
+    New->setInvalidDecl();
+    return;
+  }
+
+  // Keep a chain of previous declarations.
+  New->setPreviousDeclaration(Old);
+
+  // Inherit access appropriately.
+  New->setAccess(Old->getAccess());
+}
+
+/// ParsedFreeStandingDeclSpec - This method is invoked when a declspec with
+/// no declarator (e.g. "struct foo;") is parsed.
+Sema::DeclPtrTy Sema::ParsedFreeStandingDeclSpec(Scope *S, DeclSpec &DS) {
+  // FIXME: Error on auto/register at file scope
+  // FIXME: Error on inline/virtual/explicit
+  // FIXME: Warn on useless __thread
+  // FIXME: Warn on useless const/volatile
+  // FIXME: Warn on useless static/extern/typedef/private_extern/mutable
+  // FIXME: Warn on useless attributes
+  Decl *TagD = 0;
+  TagDecl *Tag = 0;
+  if (DS.getTypeSpecType() == DeclSpec::TST_class ||
+      DS.getTypeSpecType() == DeclSpec::TST_struct ||
+      DS.getTypeSpecType() == DeclSpec::TST_union ||
+      DS.getTypeSpecType() == DeclSpec::TST_enum) {
+    TagD = static_cast<Decl *>(DS.getTypeRep());
+
+    if (!TagD) // We probably had an error
+      return DeclPtrTy();
+
+    // Note that the above type specs guarantee that the
+    // type rep is a Decl, whereas in many of the others
+    // it's a Type.
+    Tag = dyn_cast<TagDecl>(TagD);
+  }
+
+  if (unsigned TypeQuals = DS.getTypeQualifiers()) {
+    // Enforce C99 6.7.3p2: "Types other than pointer types derived from object
+    // or incomplete types shall not be restrict-qualified."
+    if (TypeQuals & DeclSpec::TQ_restrict)
+      Diag(DS.getRestrictSpecLoc(),
+           diag::err_typecheck_invalid_restrict_not_pointer_noarg)
+           << DS.getSourceRange();
+  }
+
+  if (DS.isFriendSpecified()) {
+    // If we're dealing with a class template decl, assume that the
+    // template routines are handling it.
+    if (TagD && isa<ClassTemplateDecl>(TagD))
+      return DeclPtrTy();
+    return ActOnFriendTypeDecl(S, DS, MultiTemplateParamsArg(*this, 0, 0));
+  }
+         
+  if (RecordDecl *Record = dyn_cast_or_null<RecordDecl>(Tag)) {
+    // If there are attributes in the DeclSpec, apply them to the record.
+    if (const AttributeList *AL = DS.getAttributes())
+      ProcessDeclAttributeList(S, Record, AL);
+    
+    if (!Record->getDeclName() && Record->isDefinition() &&
+        DS.getStorageClassSpec() != DeclSpec::SCS_typedef) {
+      if (getLangOptions().CPlusPlus ||
+          Record->getDeclContext()->isRecord())
+        return BuildAnonymousStructOrUnion(S, DS, Record);
+
+      Diag(DS.getSourceRange().getBegin(), diag::err_no_declarators)
+        << DS.getSourceRange();
+    }
+
+    // Microsoft allows unnamed struct/union fields. Don't complain
+    // about them.
+    // FIXME: Should we support Microsoft's extensions in this area?
+    if (Record->getDeclName() && getLangOptions().Microsoft)
+      return DeclPtrTy::make(Tag);
+  }
+  
+  if (!DS.isMissingDeclaratorOk() &&
+      DS.getTypeSpecType() != DeclSpec::TST_error) {
+    // Warn about typedefs of enums without names, since this is an
+    // extension in both Microsoft an GNU.
+    if (DS.getStorageClassSpec() == DeclSpec::SCS_typedef &&
+        Tag && isa<EnumDecl>(Tag)) {
+      Diag(DS.getSourceRange().getBegin(), diag::ext_typedef_without_a_name)
+        << DS.getSourceRange();
+      return DeclPtrTy::make(Tag);
+    }
+
+    Diag(DS.getSourceRange().getBegin(), diag::err_no_declarators)
+      << DS.getSourceRange();
+    return DeclPtrTy();
+  }
+
+  return DeclPtrTy::make(Tag);
+}
+
+/// We are trying to inject an anonymous member into the given scope;
+/// check if there's an existing declaration that can't be overloaded.
+///
+/// \return true if this is a forbidden redeclaration
+static bool CheckAnonMemberRedeclaration(Sema &SemaRef,
+                                         Scope *S,
+                                         DeclContext *Owner,
+                                         DeclarationName Name,
+                                         SourceLocation NameLoc,
+                                         unsigned diagnostic) {
+  LookupResult R(SemaRef, Name, NameLoc, Sema::LookupMemberName,
+                 Sema::ForRedeclaration);
+  if (!SemaRef.LookupName(R, S)) return false;
+
+  if (R.getAsSingle<TagDecl>())
+    return false;
+
+  // Pick a representative declaration.
+  NamedDecl *PrevDecl = R.getRepresentativeDecl()->getUnderlyingDecl();
+  if (PrevDecl && Owner->isRecord()) {
+    RecordDecl *Record = cast<RecordDecl>(Owner);
+    if (!SemaRef.isDeclInScope(PrevDecl, Record, S))
+      return false;
+  }
+
+  SemaRef.Diag(NameLoc, diagnostic) << Name;
+  SemaRef.Diag(PrevDecl->getLocation(), diag::note_previous_declaration);
+
+  return true;
+}
+
+/// InjectAnonymousStructOrUnionMembers - Inject the members of the
+/// anonymous struct or union AnonRecord into the owning context Owner
+/// and scope S. This routine will be invoked just after we realize
+/// that an unnamed union or struct is actually an anonymous union or
+/// struct, e.g.,
+///
+/// @code
+/// union {
+///   int i;
+///   float f;
+/// }; // InjectAnonymousStructOrUnionMembers called here to inject i and
+///    // f into the surrounding scope.x
+/// @endcode
+///
+/// This routine is recursive, injecting the names of nested anonymous
+/// structs/unions into the owning context and scope as well.
+bool Sema::InjectAnonymousStructOrUnionMembers(Scope *S, DeclContext *Owner,
+                                               RecordDecl *AnonRecord) {
+  unsigned diagKind
+    = AnonRecord->isUnion() ? diag::err_anonymous_union_member_redecl
+                            : diag::err_anonymous_struct_member_redecl;
+
+  bool Invalid = false;
+  for (RecordDecl::field_iterator F = AnonRecord->field_begin(),
+                               FEnd = AnonRecord->field_end();
+       F != FEnd; ++F) {
+    if ((*F)->getDeclName()) {
+      if (CheckAnonMemberRedeclaration(*this, S, Owner, (*F)->getDeclName(),
+                                       (*F)->getLocation(), diagKind)) {
+        // C++ [class.union]p2:
+        //   The names of the members of an anonymous union shall be
+        //   distinct from the names of any other entity in the
+        //   scope in which the anonymous union is declared.
+        Invalid = true;
+      } else {
+        // C++ [class.union]p2:
+        //   For the purpose of name lookup, after the anonymous union
+        //   definition, the members of the anonymous union are
+        //   considered to have been defined in the scope in which the
+        //   anonymous union is declared.
+        Owner->makeDeclVisibleInContext(*F);
+        S->AddDecl(DeclPtrTy::make(*F));
+        IdResolver.AddDecl(*F);
+      }
+    } else if (const RecordType *InnerRecordType
+                 = (*F)->getType()->getAs<RecordType>()) {
+      RecordDecl *InnerRecord = InnerRecordType->getDecl();
+      if (InnerRecord->isAnonymousStructOrUnion())
+        Invalid = Invalid ||
+          InjectAnonymousStructOrUnionMembers(S, Owner, InnerRecord);
+    }
+  }
+
+  return Invalid;
+}
+
+/// ActOnAnonymousStructOrUnion - Handle the declaration of an
+/// anonymous structure or union. Anonymous unions are a C++ feature
+/// (C++ [class.union]) and a GNU C extension; anonymous structures
+/// are a GNU C and GNU C++ extension.
+Sema::DeclPtrTy Sema::BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS,
+                                                  RecordDecl *Record) {
+  DeclContext *Owner = Record->getDeclContext();
+
+  // Diagnose whether this anonymous struct/union is an extension.
+  if (Record->isUnion() && !getLangOptions().CPlusPlus)
+    Diag(Record->getLocation(), diag::ext_anonymous_union);
+  else if (!Record->isUnion())
+    Diag(Record->getLocation(), diag::ext_anonymous_struct);
+
+  // C and C++ require different kinds of checks for anonymous
+  // structs/unions.
+  bool Invalid = false;
+  if (getLangOptions().CPlusPlus) {
+    const char* PrevSpec = 0;
+    unsigned DiagID;
+    // C++ [class.union]p3:
+    //   Anonymous unions declared in a named namespace or in the
+    //   global namespace shall be declared static.
+    if (DS.getStorageClassSpec() != DeclSpec::SCS_static &&
+        (isa<TranslationUnitDecl>(Owner) ||
+         (isa<NamespaceDecl>(Owner) &&
+          cast<NamespaceDecl>(Owner)->getDeclName()))) {
+      Diag(Record->getLocation(), diag::err_anonymous_union_not_static);
+      Invalid = true;
+
+      // Recover by adding 'static'.
+      DS.SetStorageClassSpec(DeclSpec::SCS_static, SourceLocation(),
+                             PrevSpec, DiagID);
+    }
+    // C++ [class.union]p3:
+    //   A storage class is not allowed in a declaration of an
+    //   anonymous union in a class scope.
+    else if (DS.getStorageClassSpec() != DeclSpec::SCS_unspecified &&
+             isa<RecordDecl>(Owner)) {
+      Diag(DS.getStorageClassSpecLoc(),
+           diag::err_anonymous_union_with_storage_spec);
+      Invalid = true;
+
+      // Recover by removing the storage specifier.
+      DS.SetStorageClassSpec(DeclSpec::SCS_unspecified, SourceLocation(),
+                             PrevSpec, DiagID);
+    }
+
+    // C++ [class.union]p2:
+    //   The member-specification of an anonymous union shall only
+    //   define non-static data members. [Note: nested types and
+    //   functions cannot be declared within an anonymous union. ]
+    for (DeclContext::decl_iterator Mem = Record->decls_begin(),
+                                 MemEnd = Record->decls_end();
+         Mem != MemEnd; ++Mem) {
+      if (FieldDecl *FD = dyn_cast<FieldDecl>(*Mem)) {
+        // C++ [class.union]p3:
+        //   An anonymous union shall not have private or protected
+        //   members (clause 11).
+        if (FD->getAccess() == AS_protected || FD->getAccess() == AS_private) {
+          Diag(FD->getLocation(), diag::err_anonymous_record_nonpublic_member)
+            << (int)Record->isUnion() << (int)(FD->getAccess() == AS_protected);
+          Invalid = true;
+        }
+      } else if ((*Mem)->isImplicit()) {
+        // Any implicit members are fine.
+      } else if (isa<TagDecl>(*Mem) && (*Mem)->getDeclContext() != Record) {
+        // This is a type that showed up in an
+        // elaborated-type-specifier inside the anonymous struct or
+        // union, but which actually declares a type outside of the
+        // anonymous struct or union. It's okay.
+      } else if (RecordDecl *MemRecord = dyn_cast<RecordDecl>(*Mem)) {
+        if (!MemRecord->isAnonymousStructOrUnion() &&
+            MemRecord->getDeclName()) {
+          // This is a nested type declaration.
+          Diag(MemRecord->getLocation(), diag::err_anonymous_record_with_type)
+            << (int)Record->isUnion();
+          Invalid = true;
+        }
+      } else {
+        // We have something that isn't a non-static data
+        // member. Complain about it.
+        unsigned DK = diag::err_anonymous_record_bad_member;
+        if (isa<TypeDecl>(*Mem))
+          DK = diag::err_anonymous_record_with_type;
+        else if (isa<FunctionDecl>(*Mem))
+          DK = diag::err_anonymous_record_with_function;
+        else if (isa<VarDecl>(*Mem))
+          DK = diag::err_anonymous_record_with_static;
+        Diag((*Mem)->getLocation(), DK)
+            << (int)Record->isUnion();
+          Invalid = true;
+      }
+    }
+  }
+
+  if (!Record->isUnion() && !Owner->isRecord()) {
+    Diag(Record->getLocation(), diag::err_anonymous_struct_not_member)
+      << (int)getLangOptions().CPlusPlus;
+    Invalid = true;
+  }
+
+  // Mock up a declarator.
+  Declarator Dc(DS, Declarator::TypeNameContext);
+  TypeSourceInfo *TInfo = 0;
+  GetTypeForDeclarator(Dc, S, &TInfo);
+  assert(TInfo && "couldn't build declarator info for anonymous struct/union");
+
+  // Create a declaration for this anonymous struct/union.
+  NamedDecl *Anon = 0;
+  if (RecordDecl *OwningClass = dyn_cast<RecordDecl>(Owner)) {
+    Anon = FieldDecl::Create(Context, OwningClass, Record->getLocation(),
+                             /*IdentifierInfo=*/0,
+                             Context.getTypeDeclType(Record),
+                             TInfo,
+                             /*BitWidth=*/0, /*Mutable=*/false);
+    Anon->setAccess(AS_public);
+    if (getLangOptions().CPlusPlus)
+      FieldCollector->Add(cast<FieldDecl>(Anon));
+  } else {
+    VarDecl::StorageClass SC;
+    switch (DS.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;
+    case DeclSpec::SCS_private_extern: SC = VarDecl::PrivateExtern; break;
+    case DeclSpec::SCS_mutable:
+      // mutable can only appear on non-static class members, so it's always
+      // an error here
+      Diag(Record->getLocation(), diag::err_mutable_nonmember);
+      Invalid = true;
+      SC = VarDecl::None;
+      break;
+    }
+
+    Anon = VarDecl::Create(Context, Owner, Record->getLocation(),
+                           /*IdentifierInfo=*/0,
+                           Context.getTypeDeclType(Record),
+                           TInfo,
+                           SC);
+  }
+  Anon->setImplicit();
+
+  // Add the anonymous struct/union object to the current
+  // context. We'll be referencing this object when we refer to one of
+  // its members.
+  Owner->addDecl(Anon);
+
+  // Inject the members of the anonymous struct/union into the owning
+  // context and into the identifier resolver chain for name lookup
+  // purposes.
+  if (InjectAnonymousStructOrUnionMembers(S, Owner, Record))
+    Invalid = true;
+
+  // Mark this as an anonymous struct/union type. Note that we do not
+  // do this until after we have already checked and injected the
+  // members of this anonymous struct/union type, because otherwise
+  // the members could be injected twice: once by DeclContext when it
+  // builds its lookup table, and once by
+  // InjectAnonymousStructOrUnionMembers.
+  Record->setAnonymousStructOrUnion(true);
+
+  if (Invalid)
+    Anon->setInvalidDecl();
+
+  return DeclPtrTy::make(Anon);
+}
+
+
+/// GetNameForDeclarator - Determine the full declaration name for the
+/// given Declarator.
+DeclarationName Sema::GetNameForDeclarator(Declarator &D) {
+  return GetNameFromUnqualifiedId(D.getName());
+}
+
+/// \brief Retrieves the canonicalized name from a parsed unqualified-id.
+DeclarationName Sema::GetNameFromUnqualifiedId(const UnqualifiedId &Name) {
+  switch (Name.getKind()) {
+    case UnqualifiedId::IK_Identifier:
+      return DeclarationName(Name.Identifier);
+      
+    case UnqualifiedId::IK_OperatorFunctionId:
+      return Context.DeclarationNames.getCXXOperatorName(
+                                              Name.OperatorFunctionId.Operator);
+
+    case UnqualifiedId::IK_LiteralOperatorId:
+      return Context.DeclarationNames.getCXXLiteralOperatorName(
+                                                               Name.Identifier);
+
+    case UnqualifiedId::IK_ConversionFunctionId: {
+      QualType Ty = GetTypeFromParser(Name.ConversionFunctionId);
+      if (Ty.isNull())
+        return DeclarationName();
+      
+      return Context.DeclarationNames.getCXXConversionFunctionName(
+                                                  Context.getCanonicalType(Ty));
+    }
+      
+    case UnqualifiedId::IK_ConstructorName: {
+      QualType Ty = GetTypeFromParser(Name.ConstructorName);
+      if (Ty.isNull())
+        return DeclarationName();
+      
+      return Context.DeclarationNames.getCXXConstructorName(
+                                                  Context.getCanonicalType(Ty));
+    }
+      
+    case UnqualifiedId::IK_ConstructorTemplateId: {
+      // In well-formed code, we can only have a constructor
+      // template-id that refers to the current context, so go there
+      // to find the actual type being constructed.
+      CXXRecordDecl *CurClass = dyn_cast<CXXRecordDecl>(CurContext);
+      if (!CurClass || CurClass->getIdentifier() != Name.TemplateId->Name)
+        return DeclarationName();
+
+      // Determine the type of the class being constructed.
+      QualType CurClassType;
+      if (ClassTemplateDecl *ClassTemplate
+            = CurClass->getDescribedClassTemplate())
+        CurClassType = ClassTemplate->getInjectedClassNameType(Context);
+      else
+        CurClassType = Context.getTypeDeclType(CurClass);
+
+      // FIXME: Check two things: that the template-id names the same type as
+      // CurClassType, and that the template-id does not occur when the name
+      // was qualified.
+
+      return Context.DeclarationNames.getCXXConstructorName(
+                                       Context.getCanonicalType(CurClassType));
+    }
+
+    case UnqualifiedId::IK_DestructorName: {
+      QualType Ty = GetTypeFromParser(Name.DestructorName);
+      if (Ty.isNull())
+        return DeclarationName();
+      
+      return Context.DeclarationNames.getCXXDestructorName(
+                                                           Context.getCanonicalType(Ty));
+    }
+      
+    case UnqualifiedId::IK_TemplateId: {
+      TemplateName TName
+        = TemplateName::getFromVoidPointer(Name.TemplateId->Template);
+      return Context.getNameForTemplate(TName);
+    }
+  }
+  
+  assert(false && "Unknown name kind");
+  return DeclarationName();  
+}
+
+/// isNearlyMatchingFunction - Determine whether the C++ functions
+/// Declaration and Definition are "nearly" matching. This heuristic
+/// is used to improve diagnostics in the case where an out-of-line
+/// function definition doesn't match any declaration within
+/// the class or namespace.
+static bool isNearlyMatchingFunction(ASTContext &Context,
+                                     FunctionDecl *Declaration,
+                                     FunctionDecl *Definition) {
+  if (Declaration->param_size() != Definition->param_size())
+    return false;
+  for (unsigned Idx = 0; Idx < Declaration->param_size(); ++Idx) {
+    QualType DeclParamTy = Declaration->getParamDecl(Idx)->getType();
+    QualType DefParamTy = Definition->getParamDecl(Idx)->getType();
+
+    if (!Context.hasSameUnqualifiedType(DeclParamTy.getNonReferenceType(),
+                                        DefParamTy.getNonReferenceType()))
+      return false;
+  }
+
+  return true;
+}
+
+Sema::DeclPtrTy
+Sema::HandleDeclarator(Scope *S, Declarator &D,
+                       MultiTemplateParamsArg TemplateParamLists,
+                       bool IsFunctionDefinition) {
+  DeclarationName Name = GetNameForDeclarator(D);
+
+  // All of these full declarators require an identifier.  If it doesn't have
+  // one, the ParsedFreeStandingDeclSpec action should be used.
+  if (!Name) {
+    if (!D.isInvalidType())  // Reject this if we think it is valid.
+      Diag(D.getDeclSpec().getSourceRange().getBegin(),
+           diag::err_declarator_need_ident)
+        << D.getDeclSpec().getSourceRange() << D.getSourceRange();
+    return DeclPtrTy();
+  }
+
+  // The scope passed in may not be a decl scope.  Zip up the scope tree until
+  // we find one that is.
+  while ((S->getFlags() & Scope::DeclScope) == 0 ||
+         (S->getFlags() & Scope::TemplateParamScope) != 0)
+    S = S->getParent();
+
+  // If this is an out-of-line definition of a member of a class template
+  // or class template partial specialization, we may need to rebuild the
+  // type specifier in the declarator. See RebuildTypeInCurrentInstantiation()
+  // for more information.
+  // FIXME: cope with decltype(expr) and typeof(expr) once the rebuilder can
+  // handle expressions properly.
+  DeclSpec &DS = const_cast<DeclSpec&>(D.getDeclSpec());
+  if (D.getCXXScopeSpec().isSet() && !D.getCXXScopeSpec().isInvalid() &&
+      isDependentScopeSpecifier(D.getCXXScopeSpec()) &&
+      (DS.getTypeSpecType() == DeclSpec::TST_typename ||
+       DS.getTypeSpecType() == DeclSpec::TST_typeofType ||
+       DS.getTypeSpecType() == DeclSpec::TST_typeofExpr ||
+       DS.getTypeSpecType() == DeclSpec::TST_decltype)) {
+    if (DeclContext *DC = computeDeclContext(D.getCXXScopeSpec(), true)) {
+      // FIXME: Preserve type source info.
+      QualType T = GetTypeFromParser(DS.getTypeRep());
+
+      DeclContext *SavedContext = CurContext;
+      CurContext = DC;
+      T = RebuildTypeInCurrentInstantiation(T, D.getIdentifierLoc(), Name);
+      CurContext = SavedContext;
+
+      if (T.isNull())
+        return DeclPtrTy();
+      DS.UpdateTypeRep(T.getAsOpaquePtr());
+    }
+  }
+
+  DeclContext *DC;
+  NamedDecl *New;
+
+  TypeSourceInfo *TInfo = 0;
+  QualType R = GetTypeForDeclarator(D, S, &TInfo);
+
+  LookupResult Previous(*this, Name, D.getIdentifierLoc(), LookupOrdinaryName,
+                        ForRedeclaration);
+
+  // See if this is a redefinition of a variable in the same scope.
+  if (D.getCXXScopeSpec().isInvalid()) {
+    DC = CurContext;
+    D.setInvalidType();
+  } else if (!D.getCXXScopeSpec().isSet()) {
+    bool IsLinkageLookup = false;
+
+    // If the declaration we're planning to build will be a function
+    // or object with linkage, then look for another declaration with
+    // linkage (C99 6.2.2p4-5 and C++ [basic.link]p6).
+    if (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_typedef)
+      /* Do nothing*/;
+    else if (R->isFunctionType()) {
+      if (CurContext->isFunctionOrMethod() ||
+          D.getDeclSpec().getStorageClassSpec() != DeclSpec::SCS_static)
+        IsLinkageLookup = true;
+    } else if (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_extern)
+      IsLinkageLookup = true;
+    else if (CurContext->getLookupContext()->isTranslationUnit() &&
+             D.getDeclSpec().getStorageClassSpec() != DeclSpec::SCS_static)
+      IsLinkageLookup = true;
+
+    if (IsLinkageLookup)
+      Previous.clear(LookupRedeclarationWithLinkage);
+
+    DC = CurContext;
+    LookupName(Previous, S, /* CreateBuiltins = */ IsLinkageLookup);
+  } else { // Something like "int foo::x;"
+    DC = computeDeclContext(D.getCXXScopeSpec(), true);
+
+    if (!DC) {
+      // If we could not compute the declaration context, it's because the
+      // declaration context is dependent but does not refer to a class,
+      // class template, or class template partial specialization. Complain
+      // and return early, to avoid the coming semantic disaster.
+      Diag(D.getIdentifierLoc(),
+           diag::err_template_qualified_declarator_no_match)
+        << (NestedNameSpecifier*)D.getCXXScopeSpec().getScopeRep()
+        << D.getCXXScopeSpec().getRange();
+      return DeclPtrTy();
+    }
+
+    if (!DC->isDependentContext() && 
+        RequireCompleteDeclContext(D.getCXXScopeSpec()))
+      return DeclPtrTy();
+
+    if (isa<CXXRecordDecl>(DC) && !cast<CXXRecordDecl>(DC)->hasDefinition()) {
+      Diag(D.getIdentifierLoc(),
+           diag::err_member_def_undefined_record)
+        << Name << DC << D.getCXXScopeSpec().getRange();
+      D.setInvalidType();
+    }
+    
+    LookupQualifiedName(Previous, DC);
+
+    // Don't consider using declarations as previous declarations for
+    // out-of-line members.
+    RemoveUsingDecls(Previous);
+
+    // C++ 7.3.1.2p2:
+    // Members (including explicit specializations of templates) of a named
+    // namespace can also be defined outside that namespace by explicit
+    // qualification of the name being defined, provided that the entity being
+    // defined was already declared in the namespace and the definition appears
+    // after the point of declaration in a namespace that encloses the
+    // declarations namespace.
+    //
+    // Note that we only check the context at this point. We don't yet
+    // have enough information to make sure that PrevDecl is actually
+    // the declaration we want to match. For example, given:
+    //
+    //   class X {
+    //     void f();
+    //     void f(float);
+    //   };
+    //
+    //   void X::f(int) { } // ill-formed
+    //
+    // In this case, PrevDecl will point to the overload set
+    // containing the two f's declared in X, but neither of them
+    // matches.
+
+    // First check whether we named the global scope.
+    if (isa<TranslationUnitDecl>(DC)) {
+      Diag(D.getIdentifierLoc(), diag::err_invalid_declarator_global_scope)
+        << Name << D.getCXXScopeSpec().getRange();
+    } else {
+      DeclContext *Cur = CurContext;
+      while (isa<LinkageSpecDecl>(Cur))
+        Cur = Cur->getParent();
+      if (!Cur->Encloses(DC)) {
+        // The qualifying scope doesn't enclose the original declaration.
+        // Emit diagnostic based on current scope.
+        SourceLocation L = D.getIdentifierLoc();
+        SourceRange R = D.getCXXScopeSpec().getRange();
+        if (isa<FunctionDecl>(Cur))
+          Diag(L, diag::err_invalid_declarator_in_function) << Name << R;
+        else
+          Diag(L, diag::err_invalid_declarator_scope)
+            << Name << cast<NamedDecl>(DC) << R;
+        D.setInvalidType();
+      }
+    }
+  }
+
+  if (Previous.isSingleResult() &&
+      Previous.getFoundDecl()->isTemplateParameter()) {
+    // Maybe we will complain about the shadowed template parameter.
+    if (!D.isInvalidType())
+      if (DiagnoseTemplateParameterShadow(D.getIdentifierLoc(),
+                                          Previous.getFoundDecl()))
+        D.setInvalidType();
+
+    // Just pretend that we didn't see the previous declaration.
+    Previous.clear();
+  }
+
+  // In C++, the previous declaration we find might be a tag type
+  // (class or enum). In this case, the new declaration will hide the
+  // tag type. Note that this does does not apply if we're declaring a
+  // typedef (C++ [dcl.typedef]p4).
+  if (Previous.isSingleTagDecl() &&
+      D.getDeclSpec().getStorageClassSpec() != DeclSpec::SCS_typedef)
+    Previous.clear();
+
+  bool Redeclaration = false;
+  if (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_typedef) {
+    if (TemplateParamLists.size()) {
+      Diag(D.getIdentifierLoc(), diag::err_template_typedef);
+      return DeclPtrTy();
+    }
+
+    New = ActOnTypedefDeclarator(S, D, DC, R, TInfo, Previous, Redeclaration);
+  } else if (R->isFunctionType()) {
+    New = ActOnFunctionDeclarator(S, D, DC, R, TInfo, Previous,
+                                  move(TemplateParamLists),
+                                  IsFunctionDefinition, Redeclaration);
+  } else {
+    New = ActOnVariableDeclarator(S, D, DC, R, TInfo, Previous,
+                                  move(TemplateParamLists),
+                                  Redeclaration);
+  }
+
+  if (New == 0)
+    return DeclPtrTy();
+
+  // If this has an identifier and is not an invalid redeclaration or 
+  // function template specialization, add it to the scope stack.
+  if (Name && !(Redeclaration && New->isInvalidDecl()))
+    PushOnScopeChains(New, S);
+
+  return DeclPtrTy::make(New);
+}
+
+/// TryToFixInvalidVariablyModifiedType - Helper method to turn variable array
+/// types into constant array types in certain situations which would otherwise
+/// be errors (for GCC compatibility).
+static QualType TryToFixInvalidVariablyModifiedType(QualType T,
+                                                    ASTContext &Context,
+                                                    bool &SizeIsNegative) {
+  // This method tries to turn a variable array into a constant
+  // array even when the size isn't an ICE.  This is necessary
+  // for compatibility with code that depends on gcc's buggy
+  // constant expression folding, like struct {char x[(int)(char*)2];}
+  SizeIsNegative = false;
+
+  QualifierCollector Qs;
+  const Type *Ty = Qs.strip(T);
+
+  if (const PointerType* PTy = dyn_cast<PointerType>(Ty)) {
+    QualType Pointee = PTy->getPointeeType();
+    QualType FixedType =
+        TryToFixInvalidVariablyModifiedType(Pointee, Context, SizeIsNegative);
+    if (FixedType.isNull()) return FixedType;
+    FixedType = Context.getPointerType(FixedType);
+    return Qs.apply(FixedType);
+  }
+
+  const VariableArrayType* VLATy = dyn_cast<VariableArrayType>(T);
+  if (!VLATy)
+    return QualType();
+  // FIXME: We should probably handle this case
+  if (VLATy->getElementType()->isVariablyModifiedType())
+    return QualType();
+
+  Expr::EvalResult EvalResult;
+  if (!VLATy->getSizeExpr() ||
+      !VLATy->getSizeExpr()->Evaluate(EvalResult, Context) ||
+      !EvalResult.Val.isInt())
+    return QualType();
+
+  llvm::APSInt &Res = EvalResult.Val.getInt();
+  if (Res >= llvm::APSInt(Res.getBitWidth(), Res.isUnsigned())) {
+    // TODO: preserve the size expression in declarator info
+    return Context.getConstantArrayType(VLATy->getElementType(),
+                                        Res, ArrayType::Normal, 0);
+  }
+
+  SizeIsNegative = true;
+  return QualType();
+}
+
+/// \brief Register the given locally-scoped external C declaration so
+/// that it can be found later for redeclarations
+void
+Sema::RegisterLocallyScopedExternCDecl(NamedDecl *ND,
+                                       const LookupResult &Previous,
+                                       Scope *S) {
+  assert(ND->getLexicalDeclContext()->isFunctionOrMethod() &&
+         "Decl is not a locally-scoped decl!");
+  // Note that we have a locally-scoped external with this name.
+  LocallyScopedExternalDecls[ND->getDeclName()] = ND;
+
+  if (!Previous.isSingleResult())
+    return;
+
+  NamedDecl *PrevDecl = Previous.getFoundDecl();
+
+  // If there was a previous declaration of this variable, it may be
+  // in our identifier chain. Update the identifier chain with the new
+  // declaration.
+  if (S && IdResolver.ReplaceDecl(PrevDecl, ND)) {
+    // The previous declaration was found on the identifer resolver
+    // chain, so remove it from its scope.
+    while (S && !S->isDeclScope(DeclPtrTy::make(PrevDecl)))
+      S = S->getParent();
+
+    if (S)
+      S->RemoveDecl(DeclPtrTy::make(PrevDecl));
+  }
+}
+
+/// \brief Diagnose function specifiers on a declaration of an identifier that
+/// does not identify a function.
+void Sema::DiagnoseFunctionSpecifiers(Declarator& D) {
+  // FIXME: We should probably indicate the identifier in question to avoid
+  // confusion for constructs like "inline int a(), b;"
+  if (D.getDeclSpec().isInlineSpecified())
+    Diag(D.getDeclSpec().getInlineSpecLoc(),
+         diag::err_inline_non_function);
+
+  if (D.getDeclSpec().isVirtualSpecified())
+    Diag(D.getDeclSpec().getVirtualSpecLoc(),
+         diag::err_virtual_non_function);
+
+  if (D.getDeclSpec().isExplicitSpecified())
+    Diag(D.getDeclSpec().getExplicitSpecLoc(),
+         diag::err_explicit_non_function);
+}
+
+NamedDecl*
+Sema::ActOnTypedefDeclarator(Scope* S, Declarator& D, DeclContext* DC,
+                             QualType R,  TypeSourceInfo *TInfo,
+                             LookupResult &Previous, bool &Redeclaration) {
+  // Typedef declarators cannot be qualified (C++ [dcl.meaning]p1).
+  if (D.getCXXScopeSpec().isSet()) {
+    Diag(D.getIdentifierLoc(), diag::err_qualified_typedef_declarator)
+      << D.getCXXScopeSpec().getRange();
+    D.setInvalidType();
+    // Pretend we didn't see the scope specifier.
+    DC = 0;
+  }
+
+  if (getLangOptions().CPlusPlus) {
+    // Check that there are no default arguments (C++ only).
+    CheckExtraCXXDefaultArguments(D);
+  }
+
+  DiagnoseFunctionSpecifiers(D);
+
+  if (D.getDeclSpec().isThreadSpecified())
+    Diag(D.getDeclSpec().getThreadSpecLoc(), diag::err_invalid_thread);
+
+  TypedefDecl *NewTD = ParseTypedefDecl(S, D, R, TInfo);
+  if (!NewTD) return 0;
+
+  // Handle attributes prior to checking for duplicates in MergeVarDecl
+  ProcessDeclAttributes(S, NewTD, D);
+
+  // Merge the decl with the existing one if appropriate. If the decl is
+  // in an outer scope, it isn't the same thing.
+  FilterLookupForScope(*this, Previous, DC, S, /*ConsiderLinkage*/ false);
+  if (!Previous.empty()) {
+    Redeclaration = true;
+    MergeTypeDefDecl(NewTD, Previous);
+  }
+
+  // C99 6.7.7p2: If a typedef name specifies a variably modified type
+  // then it shall have block scope.
+  QualType T = NewTD->getUnderlyingType();
+  if (T->isVariablyModifiedType()) {
+    CurFunctionNeedsScopeChecking = true;
+
+    if (S->getFnParent() == 0) {
+      bool SizeIsNegative;
+      QualType FixedTy =
+          TryToFixInvalidVariablyModifiedType(T, Context, SizeIsNegative);
+      if (!FixedTy.isNull()) {
+        Diag(D.getIdentifierLoc(), diag::warn_illegal_constant_array_size);
+        NewTD->setTypeSourceInfo(Context.getTrivialTypeSourceInfo(FixedTy));
+      } else {
+        if (SizeIsNegative)
+          Diag(D.getIdentifierLoc(), diag::err_typecheck_negative_array_size);
+        else if (T->isVariableArrayType())
+          Diag(D.getIdentifierLoc(), diag::err_vla_decl_in_file_scope);
+        else
+          Diag(D.getIdentifierLoc(), diag::err_vm_decl_in_file_scope);
+        NewTD->setInvalidDecl();
+      }
+    }
+  }
+
+  // If this is the C FILE type, notify the AST context.
+  if (IdentifierInfo *II = NewTD->getIdentifier())
+    if (!NewTD->isInvalidDecl() &&
+        NewTD->getDeclContext()->getLookupContext()->isTranslationUnit()) {
+      if (II->isStr("FILE"))
+        Context.setFILEDecl(NewTD);
+      else if (II->isStr("jmp_buf"))
+        Context.setjmp_bufDecl(NewTD);
+      else if (II->isStr("sigjmp_buf"))
+        Context.setsigjmp_bufDecl(NewTD);
+    }
+
+  return NewTD;
+}
+
+/// \brief Determines whether the given declaration is an out-of-scope
+/// previous declaration.
+///
+/// This routine should be invoked when name lookup has found a
+/// previous declaration (PrevDecl) that is not in the scope where a
+/// new declaration by the same name is being introduced. If the new
+/// declaration occurs in a local scope, previous declarations with
+/// linkage may still be considered previous declarations (C99
+/// 6.2.2p4-5, C++ [basic.link]p6).
+///
+/// \param PrevDecl the previous declaration found by name
+/// lookup
+///
+/// \param DC the context in which the new declaration is being
+/// declared.
+///
+/// \returns true if PrevDecl is an out-of-scope previous declaration
+/// for a new delcaration with the same name.
+static bool
+isOutOfScopePreviousDeclaration(NamedDecl *PrevDecl, DeclContext *DC,
+                                ASTContext &Context) {
+  if (!PrevDecl)
+    return 0;
+
+  if (!PrevDecl->hasLinkage())
+    return false;
+
+  if (Context.getLangOptions().CPlusPlus) {
+    // C++ [basic.link]p6:
+    //   If there is a visible declaration of an entity with linkage
+    //   having the same name and type, ignoring entities declared
+    //   outside the innermost enclosing namespace scope, the block
+    //   scope declaration declares that same entity and receives the
+    //   linkage of the previous declaration.
+    DeclContext *OuterContext = DC->getLookupContext();
+    if (!OuterContext->isFunctionOrMethod())
+      // This rule only applies to block-scope declarations.
+      return false;
+    else {
+      DeclContext *PrevOuterContext = PrevDecl->getDeclContext();
+      if (PrevOuterContext->isRecord())
+        // We found a member function: ignore it.
+        return false;
+      else {
+        // Find the innermost enclosing namespace for the new and
+        // previous declarations.
+        while (!OuterContext->isFileContext())
+          OuterContext = OuterContext->getParent();
+        while (!PrevOuterContext->isFileContext())
+          PrevOuterContext = PrevOuterContext->getParent();
+
+        // The previous declaration is in a different namespace, so it
+        // isn't the same function.
+        if (OuterContext->getPrimaryContext() !=
+            PrevOuterContext->getPrimaryContext())
+          return false;
+      }
+    }
+  }
+
+  return true;
+}
+
+NamedDecl*
+Sema::ActOnVariableDeclarator(Scope* S, Declarator& D, DeclContext* DC,
+                              QualType R, TypeSourceInfo *TInfo,
+                              LookupResult &Previous,
+                              MultiTemplateParamsArg TemplateParamLists,
+                              bool &Redeclaration) {
+  DeclarationName Name = GetNameForDeclarator(D);
+
+  // Check that there are no default arguments (C++ only).
+  if (getLangOptions().CPlusPlus)
+    CheckExtraCXXDefaultArguments(D);
+
+  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;
+  case DeclSpec::SCS_private_extern: SC = VarDecl::PrivateExtern; break;
+  case DeclSpec::SCS_mutable:
+    // mutable can only appear on non-static class members, so it's always
+    // an error here
+    Diag(D.getIdentifierLoc(), diag::err_mutable_nonmember);
+    D.setInvalidType();
+    SC = VarDecl::None;
+    break;
+  }
+
+  IdentifierInfo *II = Name.getAsIdentifierInfo();
+  if (!II) {
+    Diag(D.getIdentifierLoc(), diag::err_bad_variable_name)
+      << Name.getAsString();
+    return 0;
+  }
+
+  DiagnoseFunctionSpecifiers(D);
+
+  if (!DC->isRecord() && S->getFnParent() == 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) {
+
+      // If this is a register variable with an asm label specified, then this
+      // is a GNU extension.
+      if (SC == VarDecl::Register && D.getAsmLabel())
+        Diag(D.getIdentifierLoc(), diag::err_unsupported_global_register);
+      else
+        Diag(D.getIdentifierLoc(), diag::err_typecheck_sclass_fscope);
+      D.setInvalidType();
+    }
+  }
+  if (DC->isRecord() && !CurContext->isRecord()) {
+    // This is an out-of-line definition of a static data member.
+    if (SC == VarDecl::Static) {
+      Diag(D.getDeclSpec().getStorageClassSpecLoc(),
+           diag::err_static_out_of_line)
+        << CodeModificationHint::CreateRemoval(
+                                      D.getDeclSpec().getStorageClassSpecLoc());
+    } else if (SC == VarDecl::None)
+      SC = VarDecl::Static;
+  }
+  if (SC == VarDecl::Static) {
+    if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(DC)) {
+      if (RD->isLocalClass())
+        Diag(D.getIdentifierLoc(),
+             diag::err_static_data_member_not_allowed_in_local_class)
+          << Name << RD->getDeclName();
+    }
+  }
+
+  // Match up the template parameter lists with the scope specifier, then
+  // determine whether we have a template or a template specialization.
+  bool isExplicitSpecialization = false;
+  if (TemplateParameterList *TemplateParams
+        = MatchTemplateParametersToScopeSpecifier(
+                                  D.getDeclSpec().getSourceRange().getBegin(),
+                                                  D.getCXXScopeSpec(),
+                        (TemplateParameterList**)TemplateParamLists.get(),
+                                                   TemplateParamLists.size(),
+                                                  isExplicitSpecialization)) {
+    if (TemplateParams->size() > 0) {
+      // There is no such thing as a variable template.
+      Diag(D.getIdentifierLoc(), diag::err_template_variable)
+        << II
+        << SourceRange(TemplateParams->getTemplateLoc(),
+                       TemplateParams->getRAngleLoc());
+      return 0;
+    } else {
+      // There is an extraneous 'template<>' for this variable. Complain
+      // about it, but allow the declaration of the variable.
+      Diag(TemplateParams->getTemplateLoc(),
+           diag::err_template_variable_noparams)
+        << II
+        << SourceRange(TemplateParams->getTemplateLoc(),
+                       TemplateParams->getRAngleLoc());
+      
+      isExplicitSpecialization = true;
+    }
+  }
+
+  NewVD = VarDecl::Create(Context, DC, D.getIdentifierLoc(),
+                          II, R, TInfo, SC);
+
+  if (D.isInvalidType())
+    NewVD->setInvalidDecl();
+
+  if (D.getDeclSpec().isThreadSpecified()) {
+    if (NewVD->hasLocalStorage())
+      Diag(D.getDeclSpec().getThreadSpecLoc(), diag::err_thread_non_global);
+    else if (!Context.Target.isTLSSupported())
+      Diag(D.getDeclSpec().getThreadSpecLoc(), diag::err_thread_unsupported);
+    else
+      NewVD->setThreadSpecified(true);
+  }
+
+  // Set the lexical context. If the declarator has a C++ scope specifier, the
+  // lexical context will be different from the semantic context.
+  NewVD->setLexicalDeclContext(CurContext);
+
+  // Handle attributes prior to checking for duplicates in MergeVarDecl
+  ProcessDeclAttributes(S, NewVD, D);
+
+  // Handle GNU asm-label extension (encoded as an attribute).
+  if (Expr *E = (Expr*) D.getAsmLabel()) {
+    // The parser guarantees this is a string.
+    StringLiteral *SE = cast<StringLiteral>(E);
+    NewVD->addAttr(::new (Context) AsmLabelAttr(SE->getString()));
+  }
+
+  // Don't consider existing declarations that are in a different
+  // scope and are out-of-semantic-context declarations (if the new
+  // declaration has linkage).
+  FilterLookupForScope(*this, Previous, DC, S, NewVD->hasLinkage());
+  
+  // Merge the decl with the existing one if appropriate.
+  if (!Previous.empty()) {
+    if (Previous.isSingleResult() &&
+        isa<FieldDecl>(Previous.getFoundDecl()) &&
+        D.getCXXScopeSpec().isSet()) {
+      // The user tried to define a non-static data member
+      // out-of-line (C++ [dcl.meaning]p1).
+      Diag(NewVD->getLocation(), diag::err_nonstatic_member_out_of_line)
+        << D.getCXXScopeSpec().getRange();
+      Previous.clear();
+      NewVD->setInvalidDecl();
+    }
+  } else if (D.getCXXScopeSpec().isSet()) {
+    // No previous declaration in the qualifying scope.
+    Diag(D.getIdentifierLoc(), diag::err_no_member)
+      << Name << computeDeclContext(D.getCXXScopeSpec(), true)
+      << D.getCXXScopeSpec().getRange();
+    NewVD->setInvalidDecl();
+  }
+
+  CheckVariableDeclaration(NewVD, Previous, Redeclaration);
+
+  // This is an explicit specialization of a static data member. Check it.
+  if (isExplicitSpecialization && !NewVD->isInvalidDecl() &&
+      CheckMemberSpecialization(NewVD, Previous))
+    NewVD->setInvalidDecl();
+
+  // attributes declared post-definition are currently ignored
+  if (Previous.isSingleResult()) {
+    VarDecl *Def = dyn_cast<VarDecl>(Previous.getFoundDecl());
+    if (Def && (Def = Def->getDefinition()) &&
+        Def != NewVD && D.hasAttributes()) {
+      Diag(NewVD->getLocation(), diag::warn_attribute_precede_definition);
+      Diag(Def->getLocation(), diag::note_previous_definition);
+    }
+  }
+
+  // If this is a locally-scoped extern C variable, update the map of
+  // such variables.
+  if (CurContext->isFunctionOrMethod() && NewVD->isExternC() &&
+      !NewVD->isInvalidDecl())
+    RegisterLocallyScopedExternCDecl(NewVD, Previous, S);
+
+  return NewVD;
+}
+
+/// \brief Perform semantic checking on a newly-created variable
+/// declaration.
+///
+/// This routine performs all of the type-checking required for a
+/// variable declaration once it has been built. It is used both to
+/// check variables after they have been parsed and their declarators
+/// have been translated into a declaration, and to check variables
+/// that have been instantiated from a template.
+///
+/// Sets NewVD->isInvalidDecl() if an error was encountered.
+void Sema::CheckVariableDeclaration(VarDecl *NewVD,
+                                    LookupResult &Previous,
+                                    bool &Redeclaration) {
+  // If the decl is already known invalid, don't check it.
+  if (NewVD->isInvalidDecl())
+    return;
+
+  QualType T = NewVD->getType();
+
+  if (T->isObjCInterfaceType()) {
+    Diag(NewVD->getLocation(), diag::err_statically_allocated_object);
+    return NewVD->setInvalidDecl();
+  }
+
+  // Emit an error if an address space was applied to decl with local storage.
+  // This includes arrays of objects with address space qualifiers, but not
+  // automatic variables that point to other address spaces.
+  // ISO/IEC TR 18037 S5.1.2
+  if (NewVD->hasLocalStorage() && (T.getAddressSpace() != 0)) {
+    Diag(NewVD->getLocation(), diag::err_as_qualified_auto_decl);
+    return NewVD->setInvalidDecl();
+  }
+
+  if (NewVD->hasLocalStorage() && T.isObjCGCWeak()
+      && !NewVD->hasAttr<BlocksAttr>())
+    Diag(NewVD->getLocation(), diag::warn_attribute_weak_on_local);
+
+  bool isVM = T->isVariablyModifiedType();
+  if (isVM || NewVD->hasAttr<CleanupAttr>() ||
+      NewVD->hasAttr<BlocksAttr>())
+    CurFunctionNeedsScopeChecking = true;
+
+  if ((isVM && NewVD->hasLinkage()) ||
+      (T->isVariableArrayType() && NewVD->hasGlobalStorage())) {
+    bool SizeIsNegative;
+    QualType FixedTy =
+        TryToFixInvalidVariablyModifiedType(T, Context, SizeIsNegative);
+
+    if (FixedTy.isNull() && T->isVariableArrayType()) {
+      const VariableArrayType *VAT = Context.getAsVariableArrayType(T);
+      // FIXME: This won't give the correct result for
+      // int a[10][n];
+      SourceRange SizeRange = VAT->getSizeExpr()->getSourceRange();
+
+      if (NewVD->isFileVarDecl())
+        Diag(NewVD->getLocation(), diag::err_vla_decl_in_file_scope)
+        << SizeRange;
+      else if (NewVD->getStorageClass() == VarDecl::Static)
+        Diag(NewVD->getLocation(), diag::err_vla_decl_has_static_storage)
+        << SizeRange;
+      else
+        Diag(NewVD->getLocation(), diag::err_vla_decl_has_extern_linkage)
+        << SizeRange;
+      return NewVD->setInvalidDecl();
+    }
+
+    if (FixedTy.isNull()) {
+      if (NewVD->isFileVarDecl())
+        Diag(NewVD->getLocation(), diag::err_vm_decl_in_file_scope);
+      else
+        Diag(NewVD->getLocation(), diag::err_vm_decl_has_extern_linkage);
+      return NewVD->setInvalidDecl();
+    }
+
+    Diag(NewVD->getLocation(), diag::warn_illegal_constant_array_size);
+    NewVD->setType(FixedTy);
+  }
+
+  if (Previous.empty() && NewVD->isExternC()) {
+    // Since we did not find anything by this name and we're declaring
+    // an extern "C" variable, look for a non-visible extern "C"
+    // declaration with the same name.
+    llvm::DenseMap<DeclarationName, NamedDecl *>::iterator Pos
+      = LocallyScopedExternalDecls.find(NewVD->getDeclName());
+    if (Pos != LocallyScopedExternalDecls.end())
+      Previous.addDecl(Pos->second);
+  }
+
+  if (T->isVoidType() && !NewVD->hasExternalStorage()) {
+    Diag(NewVD->getLocation(), diag::err_typecheck_decl_incomplete_type)
+      << T;
+    return NewVD->setInvalidDecl();
+  }
+
+  if (!NewVD->hasLocalStorage() && NewVD->hasAttr<BlocksAttr>()) {
+    Diag(NewVD->getLocation(), diag::err_block_on_nonlocal);
+    return NewVD->setInvalidDecl();
+  }
+
+  if (isVM && NewVD->hasAttr<BlocksAttr>()) {
+    Diag(NewVD->getLocation(), diag::err_block_on_vm);
+    return NewVD->setInvalidDecl();
+  }
+
+  if (!Previous.empty()) {
+    Redeclaration = true;
+    MergeVarDecl(NewVD, Previous);
+  }
+}
+
+/// \brief Data used with FindOverriddenMethod
+struct FindOverriddenMethodData {
+  Sema *S;
+  CXXMethodDecl *Method;
+};
+
+/// \brief Member lookup function that determines whether a given C++
+/// method overrides a method in a base class, to be used with
+/// CXXRecordDecl::lookupInBases().
+static bool FindOverriddenMethod(const CXXBaseSpecifier *Specifier,
+                                 CXXBasePath &Path,
+                                 void *UserData) {
+  RecordDecl *BaseRecord = Specifier->getType()->getAs<RecordType>()->getDecl();
+
+  FindOverriddenMethodData *Data 
+    = reinterpret_cast<FindOverriddenMethodData*>(UserData);
+  
+  DeclarationName Name = Data->Method->getDeclName();
+  
+  // FIXME: Do we care about other names here too?
+  if (Name.getNameKind() == DeclarationName::CXXDestructorName) {
+    // We really want to find the base class constructor here.
+    QualType T = Data->S->Context.getTypeDeclType(BaseRecord);
+    CanQualType CT = Data->S->Context.getCanonicalType(T);
+    
+    Name = Data->S->Context.DeclarationNames.getCXXDestructorName(CT);
+  }    
+  
+  for (Path.Decls = BaseRecord->lookup(Name);
+       Path.Decls.first != Path.Decls.second;
+       ++Path.Decls.first) {
+    if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(*Path.Decls.first)) {
+      if (MD->isVirtual() && !Data->S->IsOverload(Data->Method, MD))
+        return true;
+    }
+  }
+  
+  return false;
+}
+
+/// AddOverriddenMethods - See if a method overrides any in the base classes,
+/// and if so, check that it's a valid override and remember it.
+void Sema::AddOverriddenMethods(CXXRecordDecl *DC, CXXMethodDecl *MD) {
+  // Look for virtual methods in base classes that this method might override.
+  CXXBasePaths Paths;
+  FindOverriddenMethodData Data;
+  Data.Method = MD;
+  Data.S = this;
+  if (DC->lookupInBases(&FindOverriddenMethod, &Data, Paths)) {
+    for (CXXBasePaths::decl_iterator I = Paths.found_decls_begin(),
+         E = Paths.found_decls_end(); I != E; ++I) {
+      if (CXXMethodDecl *OldMD = dyn_cast<CXXMethodDecl>(*I)) {
+        if (!CheckOverridingFunctionReturnType(MD, OldMD) &&
+            !CheckOverridingFunctionExceptionSpec(MD, OldMD) &&
+            !CheckOverridingFunctionAttributes(MD, OldMD))
+          MD->addOverriddenMethod(OldMD->getCanonicalDecl());
+      }
+    }
+  }
+}
+
+NamedDecl*
+Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
+                              QualType R, TypeSourceInfo *TInfo,
+                              LookupResult &Previous,
+                              MultiTemplateParamsArg TemplateParamLists,
+                              bool IsFunctionDefinition, bool &Redeclaration) {
+  assert(R.getTypePtr()->isFunctionType());
+
+  DeclarationName Name = GetNameForDeclarator(D);
+  FunctionDecl::StorageClass SC = FunctionDecl::None;
+  switch (D.getDeclSpec().getStorageClassSpec()) {
+  default: assert(0 && "Unknown storage class!");
+  case DeclSpec::SCS_auto:
+  case DeclSpec::SCS_register:
+  case DeclSpec::SCS_mutable:
+    Diag(D.getDeclSpec().getStorageClassSpecLoc(),
+         diag::err_typecheck_sclass_func);
+    D.setInvalidType();
+    break;
+  case DeclSpec::SCS_unspecified: SC = FunctionDecl::None; break;
+  case DeclSpec::SCS_extern:      SC = FunctionDecl::Extern; break;
+  case DeclSpec::SCS_static: {
+    if (CurContext->getLookupContext()->isFunctionOrMethod()) {
+      // C99 6.7.1p5:
+      //   The declaration of an identifier for a function that has
+      //   block scope shall have no explicit storage-class specifier
+      //   other than extern
+      // See also (C++ [dcl.stc]p4).
+      Diag(D.getDeclSpec().getStorageClassSpecLoc(),
+           diag::err_static_block_func);
+      SC = FunctionDecl::None;
+    } else
+      SC = FunctionDecl::Static;
+    break;
+  }
+  case DeclSpec::SCS_private_extern: SC = FunctionDecl::PrivateExtern;break;
+  }
+
+  if (D.getDeclSpec().isThreadSpecified())
+    Diag(D.getDeclSpec().getThreadSpecLoc(), diag::err_invalid_thread);
+
+  bool isFriend = D.getDeclSpec().isFriendSpecified();
+  bool isInline = D.getDeclSpec().isInlineSpecified();
+  bool isVirtual = D.getDeclSpec().isVirtualSpecified();
+  bool isExplicit = D.getDeclSpec().isExplicitSpecified();
+
+  // Check that the return type is not an abstract class type.
+  // For record types, this is done by the AbstractClassUsageDiagnoser once
+  // the class has been completely parsed.
+  if (!DC->isRecord() &&
+      RequireNonAbstractType(D.getIdentifierLoc(),
+                             R->getAs<FunctionType>()->getResultType(),
+                             diag::err_abstract_type_in_decl,
+                             AbstractReturnType))
+    D.setInvalidType();
+
+  // Do not allow returning a objc interface by-value.
+  if (R->getAs<FunctionType>()->getResultType()->isObjCInterfaceType()) {
+    Diag(D.getIdentifierLoc(),
+         diag::err_object_cannot_be_passed_returned_by_value) << 0
+      << R->getAs<FunctionType>()->getResultType();
+    D.setInvalidType();
+  }
+
+  bool isVirtualOkay = false;
+  FunctionDecl *NewFD;
+
+  if (isFriend) {
+    // C++ [class.friend]p5
+    //   A function can be defined in a friend declaration of a
+    //   class . . . . Such a function is implicitly inline.
+    isInline |= IsFunctionDefinition;
+  }
+
+  if (Name.getNameKind() == DeclarationName::CXXConstructorName) {
+    // This is a C++ constructor declaration.
+    assert(DC->isRecord() &&
+           "Constructors can only be declared in a member context");
+
+    R = CheckConstructorDeclarator(D, R, SC);
+
+    // Create the new declaration
+    NewFD = CXXConstructorDecl::Create(Context,
+                                       cast<CXXRecordDecl>(DC),
+                                       D.getIdentifierLoc(), Name, R, TInfo,
+                                       isExplicit, isInline,
+                                       /*isImplicitlyDeclared=*/false);
+  } else if (Name.getNameKind() == DeclarationName::CXXDestructorName) {
+    // This is a C++ destructor declaration.
+    if (DC->isRecord()) {
+      R = CheckDestructorDeclarator(D, SC);
+
+      NewFD = CXXDestructorDecl::Create(Context,
+                                        cast<CXXRecordDecl>(DC),
+                                        D.getIdentifierLoc(), Name, R,
+                                        isInline,
+                                        /*isImplicitlyDeclared=*/false);
+
+      isVirtualOkay = true;
+    } else {
+      Diag(D.getIdentifierLoc(), diag::err_destructor_not_member);
+
+      // Create a FunctionDecl to satisfy the function definition parsing
+      // code path.
+      NewFD = FunctionDecl::Create(Context, DC, D.getIdentifierLoc(),
+                                   Name, R, TInfo, SC, isInline,
+                                   /*hasPrototype=*/true);
+      D.setInvalidType();
+    }
+  } else if (Name.getNameKind() == DeclarationName::CXXConversionFunctionName) {
+    if (!DC->isRecord()) {
+      Diag(D.getIdentifierLoc(),
+           diag::err_conv_function_not_member);
+      return 0;
+    }
+
+    CheckConversionDeclarator(D, R, SC);
+    NewFD = CXXConversionDecl::Create(Context, cast<CXXRecordDecl>(DC),
+                                      D.getIdentifierLoc(), Name, R, TInfo,
+                                      isInline, isExplicit);
+
+    isVirtualOkay = true;
+  } else if (DC->isRecord()) {
+    // If the of the function is the same as the name of the record, then this
+    // must be an invalid constructor that has a return type.
+    // (The parser checks for a return type and makes the declarator a
+    // constructor if it has no return type).
+    // must have an invalid constructor that has a return type
+    if (Name.getAsIdentifierInfo() &&
+        Name.getAsIdentifierInfo() == cast<CXXRecordDecl>(DC)->getIdentifier()){
+      Diag(D.getIdentifierLoc(), diag::err_constructor_return_type)
+        << SourceRange(D.getDeclSpec().getTypeSpecTypeLoc())
+        << SourceRange(D.getIdentifierLoc());
+      return 0;
+    }
+
+    bool isStatic = SC == FunctionDecl::Static;
+    
+    // [class.free]p1:
+    // Any allocation function for a class T is a static member
+    // (even if not explicitly declared static).
+    if (Name.getCXXOverloadedOperator() == OO_New ||
+        Name.getCXXOverloadedOperator() == OO_Array_New)
+      isStatic = true;
+
+    // [class.free]p6 Any deallocation function for a class X is a static member
+    // (even if not explicitly declared static).
+    if (Name.getCXXOverloadedOperator() == OO_Delete ||
+        Name.getCXXOverloadedOperator() == OO_Array_Delete)
+      isStatic = true;
+    
+    // This is a C++ method declaration.
+    NewFD = CXXMethodDecl::Create(Context, cast<CXXRecordDecl>(DC),
+                                  D.getIdentifierLoc(), Name, R, TInfo,
+                                  isStatic, isInline);
+
+    isVirtualOkay = !isStatic;
+  } else {
+    // Determine whether the function was written with a
+    // prototype. This true when:
+    //   - we're in C++ (where every function has a prototype),
+    //   - there is a prototype in the declarator, or
+    //   - the type R of the function is some kind of typedef or other reference
+    //     to a type name (which eventually refers to a function type).
+    bool HasPrototype =
+       getLangOptions().CPlusPlus ||
+       (D.getNumTypeObjects() && D.getTypeObject(0).Fun.hasPrototype) ||
+       (!isa<FunctionType>(R.getTypePtr()) && R->isFunctionProtoType());
+
+    NewFD = FunctionDecl::Create(Context, DC,
+                                 D.getIdentifierLoc(),
+                                 Name, R, TInfo, SC, isInline, HasPrototype);
+  }
+
+  if (D.isInvalidType())
+    NewFD->setInvalidDecl();
+
+  // Set the lexical context. If the declarator has a C++
+  // scope specifier, or is the object of a friend declaration, the
+  // lexical context will be different from the semantic context.
+  NewFD->setLexicalDeclContext(CurContext);
+
+  // Match up the template parameter lists with the scope specifier, then
+  // determine whether we have a template or a template specialization.
+  FunctionTemplateDecl *FunctionTemplate = 0;
+  bool isExplicitSpecialization = false;
+  bool isFunctionTemplateSpecialization = false;
+  if (TemplateParameterList *TemplateParams
+        = MatchTemplateParametersToScopeSpecifier(
+                                  D.getDeclSpec().getSourceRange().getBegin(),
+                                  D.getCXXScopeSpec(),
+                           (TemplateParameterList**)TemplateParamLists.get(),
+                                                  TemplateParamLists.size(),
+                                                  isExplicitSpecialization)) {
+    if (TemplateParams->size() > 0) {
+      // This is a function template
+
+      // Check that we can declare a template here.
+      if (CheckTemplateDeclScope(S, TemplateParams))
+        return 0;
+
+      FunctionTemplate = FunctionTemplateDecl::Create(Context, DC,
+                                                      NewFD->getLocation(),
+                                                      Name, TemplateParams,
+                                                      NewFD);
+      FunctionTemplate->setLexicalDeclContext(CurContext);
+      NewFD->setDescribedFunctionTemplate(FunctionTemplate);
+    } else {
+      // This is a function template specialization.
+      isFunctionTemplateSpecialization = true;
+    }
+
+    // FIXME: Free this memory properly.
+    TemplateParamLists.release();
+  }
+  
+  // C++ [dcl.fct.spec]p5:
+  //   The virtual specifier shall only be used in declarations of
+  //   nonstatic class member functions that appear within a
+  //   member-specification of a class declaration; see 10.3.
+  //
+  if (isVirtual && !NewFD->isInvalidDecl()) {
+    if (!isVirtualOkay) {
+       Diag(D.getDeclSpec().getVirtualSpecLoc(),
+           diag::err_virtual_non_function);
+    } else if (!CurContext->isRecord()) {
+      // 'virtual' was specified outside of the class.
+      Diag(D.getDeclSpec().getVirtualSpecLoc(), diag::err_virtual_out_of_class)
+        << CodeModificationHint::CreateRemoval(
+                                           D.getDeclSpec().getVirtualSpecLoc());
+    } else {
+      // Okay: Add virtual to the method.
+      CXXRecordDecl *CurClass = cast<CXXRecordDecl>(DC);
+      CurClass->setMethodAsVirtual(NewFD);
+    }
+  }
+
+  // C++ [dcl.fct.spec]p6:
+  //  The explicit specifier shall be used only in the declaration of a
+  //  constructor or conversion function within its class definition; see 12.3.1
+  //  and 12.3.2.
+  if (isExplicit && !NewFD->isInvalidDecl()) {
+    if (!CurContext->isRecord()) {
+      // 'explicit' was specified outside of the class.
+      Diag(D.getDeclSpec().getExplicitSpecLoc(), 
+           diag::err_explicit_out_of_class)
+        << CodeModificationHint::CreateRemoval(
+                                          D.getDeclSpec().getExplicitSpecLoc());
+    } else if (!isa<CXXConstructorDecl>(NewFD) && 
+               !isa<CXXConversionDecl>(NewFD)) {
+      // 'explicit' was specified on a function that wasn't a constructor
+      // or conversion function.
+      Diag(D.getDeclSpec().getExplicitSpecLoc(),
+           diag::err_explicit_non_ctor_or_conv_function)
+        << CodeModificationHint::CreateRemoval(
+                                          D.getDeclSpec().getExplicitSpecLoc());
+    }      
+  }
+
+  // Filter out previous declarations that don't match the scope.
+  FilterLookupForScope(*this, Previous, DC, S, NewFD->hasLinkage());
+
+  if (isFriend) {
+    // DC is the namespace in which the function is being declared.
+    assert((DC->isFileContext() || !Previous.empty()) &&
+           "previously-undeclared friend function being created "
+           "in a non-namespace context");
+
+    if (FunctionTemplate) {
+      FunctionTemplate->setObjectOfFriendDecl(
+                                   /* PreviouslyDeclared= */ !Previous.empty());
+      FunctionTemplate->setAccess(AS_public);
+    }
+    else
+      NewFD->setObjectOfFriendDecl(/* PreviouslyDeclared= */ !Previous.empty());
+
+    NewFD->setAccess(AS_public);
+  }
+
+  if (SC == FunctionDecl::Static && isa<CXXMethodDecl>(NewFD) &&
+      !CurContext->isRecord()) {
+    // C++ [class.static]p1:
+    //   A data or function member of a class may be declared static
+    //   in a class definition, in which case it is a static member of
+    //   the class.
+
+    // Complain about the 'static' specifier if it's on an out-of-line
+    // member function definition.
+    Diag(D.getDeclSpec().getStorageClassSpecLoc(),
+         diag::err_static_out_of_line)
+      << CodeModificationHint::CreateRemoval(
+                                      D.getDeclSpec().getStorageClassSpecLoc());
+  }
+
+  // Handle GNU asm-label extension (encoded as an attribute).
+  if (Expr *E = (Expr*) D.getAsmLabel()) {
+    // The parser guarantees this is a string.
+    StringLiteral *SE = cast<StringLiteral>(E);
+    NewFD->addAttr(::new (Context) AsmLabelAttr(SE->getString()));
+  }
+
+  // Copy the parameter declarations from the declarator D to the function
+  // declaration NewFD, if they are available.  First scavenge them into Params.
+  llvm::SmallVector<ParmVarDecl*, 16> Params;
+  if (D.getNumTypeObjects() > 0) {
+    DeclaratorChunk::FunctionTypeInfo &FTI = D.getTypeObject(0).Fun;
+
+    // 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.
+    // We let through "const void" here because Sema::GetTypeForDeclarator
+    // already checks for that case.
+    if (FTI.NumArgs == 1 && !FTI.isVariadic && FTI.ArgInfo[0].Ident == 0 &&
+        FTI.ArgInfo[0].Param &&
+        FTI.ArgInfo[0].Param.getAs<ParmVarDecl>()->getType()->isVoidType()) {
+      // Empty arg list, don't push any params.
+      ParmVarDecl *Param = FTI.ArgInfo[0].Param.getAs<ParmVarDecl>();
+
+      // In C++, the empty parameter-type-list must be spelled "void"; a
+      // typedef of void is not permitted.
+      if (getLangOptions().CPlusPlus &&
+          Param->getType().getUnqualifiedType() != Context.VoidTy)
+        Diag(Param->getLocation(), diag::err_param_typedef_of_void);
+      // FIXME: Leaks decl?
+    } else if (FTI.NumArgs > 0 && FTI.ArgInfo[0].Param != 0) {
+      for (unsigned i = 0, e = FTI.NumArgs; i != e; ++i) {
+        ParmVarDecl *Param = FTI.ArgInfo[i].Param.getAs<ParmVarDecl>();
+        assert(Param->getDeclContext() != NewFD && "Was set before ?");
+        Param->setDeclContext(NewFD);
+        Params.push_back(Param);
+      }
+    }
+
+  } else if (const FunctionProtoType *FT = R->getAs<FunctionProtoType>()) {
+    // When we're declaring a function with a typedef, typeof, etc as in the
+    // following example, we'll need to synthesize (unnamed)
+    // parameters for use in the declaration.
+    //
+    // @code
+    // typedef void fn(int);
+    // fn f;
+    // @endcode
+
+    // Synthesize a parameter for each argument type.
+    for (FunctionProtoType::arg_type_iterator AI = FT->arg_type_begin(),
+         AE = FT->arg_type_end(); AI != AE; ++AI) {
+      ParmVarDecl *Param = ParmVarDecl::Create(Context, NewFD,
+                                               SourceLocation(), 0,
+                                               *AI, /*TInfo=*/0,
+                                               VarDecl::None, 0);
+      Param->setImplicit();
+      Params.push_back(Param);
+    }
+  } else {
+    assert(R->isFunctionNoProtoType() && NewFD->getNumParams() == 0 &&
+           "Should not need args for typedef of non-prototype fn");
+  }
+  // Finally, we know we have the right number of parameters, install them.
+  NewFD->setParams(Context, Params.data(), Params.size());
+
+  // If the declarator is a template-id, translate the parser's template 
+  // argument list into our AST format.
+  bool HasExplicitTemplateArgs = false;
+  TemplateArgumentListInfo TemplateArgs;
+  if (D.getName().getKind() == UnqualifiedId::IK_TemplateId) {
+    TemplateIdAnnotation *TemplateId = D.getName().TemplateId;
+    TemplateArgs.setLAngleLoc(TemplateId->LAngleLoc);
+    TemplateArgs.setRAngleLoc(TemplateId->RAngleLoc);
+    ASTTemplateArgsPtr TemplateArgsPtr(*this,
+                                       TemplateId->getTemplateArgs(),
+                                       TemplateId->NumArgs);
+    translateTemplateArguments(TemplateArgsPtr,
+                               TemplateArgs);
+    TemplateArgsPtr.release();
+    
+    HasExplicitTemplateArgs = true;
+    
+    if (FunctionTemplate) {
+      // FIXME: Diagnose function template with explicit template
+      // arguments.
+      HasExplicitTemplateArgs = false;
+    } else if (!isFunctionTemplateSpecialization && 
+               !D.getDeclSpec().isFriendSpecified()) {
+      // We have encountered something that the user meant to be a 
+      // specialization (because it has explicitly-specified template
+      // arguments) but that was not introduced with a "template<>" (or had
+      // too few of them).
+      Diag(D.getIdentifierLoc(), diag::err_template_spec_needs_header)
+        << SourceRange(TemplateId->LAngleLoc, TemplateId->RAngleLoc)
+        << CodeModificationHint::CreateInsertion(
+                                   D.getDeclSpec().getSourceRange().getBegin(),
+                                                 "template<> ");
+      isFunctionTemplateSpecialization = true;
+    }
+  }
+
+  if (isFunctionTemplateSpecialization) {
+      if (CheckFunctionTemplateSpecialization(NewFD,
+                               (HasExplicitTemplateArgs ? &TemplateArgs : 0),
+                                              Previous))
+        NewFD->setInvalidDecl();
+  } else if (isExplicitSpecialization && isa<CXXMethodDecl>(NewFD) &&
+             CheckMemberSpecialization(NewFD, Previous))
+    NewFD->setInvalidDecl();
+    
+  // Perform semantic checking on the function declaration.
+  bool OverloadableAttrRequired = false; // FIXME: HACK!
+  CheckFunctionDeclaration(S, NewFD, Previous, isExplicitSpecialization,
+                           Redeclaration, /*FIXME:*/OverloadableAttrRequired);
+
+  assert((NewFD->isInvalidDecl() || !Redeclaration ||
+          Previous.getResultKind() != LookupResult::FoundOverloaded) &&
+         "previous declaration set still overloaded");
+
+  // If we have a function template, check the template parameter
+  // list. This will check and merge default template arguments.
+  if (FunctionTemplate) {
+    FunctionTemplateDecl *PrevTemplate = FunctionTemplate->getPreviousDeclaration();
+    CheckTemplateParameterList(FunctionTemplate->getTemplateParameters(),
+                      PrevTemplate? PrevTemplate->getTemplateParameters() : 0,
+             D.getDeclSpec().isFriendSpecified()? TPC_FriendFunctionTemplate
+                                                : TPC_FunctionTemplate);
+  }
+
+  if (D.getCXXScopeSpec().isSet() && !NewFD->isInvalidDecl()) {
+    // Fake up an access specifier if it's supposed to be a class member.
+    if (!Redeclaration && isa<CXXRecordDecl>(NewFD->getDeclContext()))
+      NewFD->setAccess(AS_public);
+
+    // An out-of-line member function declaration must also be a
+    // definition (C++ [dcl.meaning]p1).
+    // Note that this is not the case for explicit specializations of
+    // function templates or member functions of class templates, per
+    // C++ [temp.expl.spec]p2.
+    if (!IsFunctionDefinition && !isFriend &&
+        !isFunctionTemplateSpecialization && !isExplicitSpecialization) {
+      Diag(NewFD->getLocation(), diag::err_out_of_line_declaration)
+        << D.getCXXScopeSpec().getRange();
+      NewFD->setInvalidDecl();
+    } else if (!Redeclaration && 
+               !(isFriend && CurContext->isDependentContext())) {
+      // The user tried to provide an out-of-line definition for a
+      // function that is a member of a class or namespace, but there
+      // was no such member function declared (C++ [class.mfct]p2,
+      // C++ [namespace.memdef]p2). For example:
+      //
+      // class X {
+      //   void f() const;
+      // };
+      //
+      // void X::f() { } // ill-formed
+      //
+      // Complain about this problem, and attempt to suggest close
+      // matches (e.g., those that differ only in cv-qualifiers and
+      // whether the parameter types are references).
+      Diag(D.getIdentifierLoc(), diag::err_member_def_does_not_match)
+        << Name << DC << D.getCXXScopeSpec().getRange();
+      NewFD->setInvalidDecl();
+
+      LookupResult Prev(*this, Name, D.getIdentifierLoc(), LookupOrdinaryName,
+                        ForRedeclaration);
+      LookupQualifiedName(Prev, DC);
+      assert(!Prev.isAmbiguous() &&
+             "Cannot have an ambiguity in previous-declaration lookup");
+      for (LookupResult::iterator Func = Prev.begin(), FuncEnd = Prev.end();
+           Func != FuncEnd; ++Func) {
+        if (isa<FunctionDecl>(*Func) &&
+            isNearlyMatchingFunction(Context, cast<FunctionDecl>(*Func), NewFD))
+          Diag((*Func)->getLocation(), diag::note_member_def_close_match);
+      }
+    }
+  }
+
+  // Handle attributes. We need to have merged decls when handling attributes
+  // (for example to check for conflicts, etc).
+  // FIXME: This needs to happen before we merge declarations. Then,
+  // let attribute merging cope with attribute conflicts.
+  ProcessDeclAttributes(S, NewFD, D);
+
+  // attributes declared post-definition are currently ignored
+  if (Redeclaration && Previous.isSingleResult()) {
+    const FunctionDecl *Def;
+    FunctionDecl *PrevFD = dyn_cast<FunctionDecl>(Previous.getFoundDecl());
+    if (PrevFD && PrevFD->getBody(Def) && D.hasAttributes()) {
+      Diag(NewFD->getLocation(), diag::warn_attribute_precede_definition);
+      Diag(Def->getLocation(), diag::note_previous_definition);
+    }
+  }
+
+  AddKnownFunctionAttributes(NewFD);
+
+  if (OverloadableAttrRequired && !NewFD->getAttr<OverloadableAttr>()) {
+    // If a function name is overloadable in C, then every function
+    // with that name must be marked "overloadable".
+    Diag(NewFD->getLocation(), diag::err_attribute_overloadable_missing)
+      << Redeclaration << NewFD;
+    if (!Previous.empty())
+      Diag(Previous.getRepresentativeDecl()->getLocation(),
+           diag::note_attribute_overloadable_prev_overload);
+    NewFD->addAttr(::new (Context) OverloadableAttr());
+  }
+
+  // If this is a locally-scoped extern C function, update the
+  // map of such names.
+  if (CurContext->isFunctionOrMethod() && NewFD->isExternC()
+      && !NewFD->isInvalidDecl())
+    RegisterLocallyScopedExternCDecl(NewFD, Previous, S);
+
+  // Set this FunctionDecl's range up to the right paren.
+  NewFD->setLocEnd(D.getSourceRange().getEnd());
+
+  if (FunctionTemplate && NewFD->isInvalidDecl())
+    FunctionTemplate->setInvalidDecl();
+
+  if (FunctionTemplate)
+    return FunctionTemplate;
+
+  return NewFD;
+}
+
+/// \brief Perform semantic checking of a new function declaration.
+///
+/// Performs semantic analysis of the new function declaration
+/// NewFD. This routine performs all semantic checking that does not
+/// require the actual declarator involved in the declaration, and is
+/// used both for the declaration of functions as they are parsed
+/// (called via ActOnDeclarator) and for the declaration of functions
+/// that have been instantiated via C++ template instantiation (called
+/// via InstantiateDecl).
+///
+/// \param IsExplicitSpecialiation whether this new function declaration is
+/// an explicit specialization of the previous declaration.
+///
+/// This sets NewFD->isInvalidDecl() to true if there was an error.
+void Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD,
+                                    LookupResult &Previous,
+                                    bool IsExplicitSpecialization,
+                                    bool &Redeclaration,
+                                    bool &OverloadableAttrRequired) {
+  // If NewFD is already known erroneous, don't do any of this checking.
+  if (NewFD->isInvalidDecl())
+    return;
+
+  if (NewFD->getResultType()->isVariablyModifiedType()) {
+    // Functions returning a variably modified type violate C99 6.7.5.2p2
+    // because all functions have linkage.
+    Diag(NewFD->getLocation(), diag::err_vm_func_decl);
+    return NewFD->setInvalidDecl();
+  }
+
+  if (NewFD->isMain()) 
+    CheckMain(NewFD);
+
+  // Check for a previous declaration of this name.
+  if (Previous.empty() && NewFD->isExternC()) {
+    // Since we did not find anything by this name and we're declaring
+    // an extern "C" function, look for a non-visible extern "C"
+    // declaration with the same name.
+    llvm::DenseMap<DeclarationName, NamedDecl *>::iterator Pos
+      = LocallyScopedExternalDecls.find(NewFD->getDeclName());
+    if (Pos != LocallyScopedExternalDecls.end())
+      Previous.addDecl(Pos->second);
+  }
+
+  // Merge or overload the declaration with an existing declaration of
+  // the same name, if appropriate.
+  if (!Previous.empty()) {
+    // Determine whether NewFD is an overload of PrevDecl or
+    // a declaration that requires merging. If it's an overload,
+    // there's no more work to do here; we'll just add the new
+    // function to the scope.
+
+    NamedDecl *OldDecl = 0;
+    if (!AllowOverloadingOfFunction(Previous, Context)) {
+      Redeclaration = true;
+      OldDecl = Previous.getFoundDecl();
+    } else {
+      if (!getLangOptions().CPlusPlus) {
+        OverloadableAttrRequired = true;
+
+        // Functions marked "overloadable" must have a prototype (that
+        // we can't get through declaration merging).
+        if (!NewFD->getType()->getAs<FunctionProtoType>()) {
+          Diag(NewFD->getLocation(),
+               diag::err_attribute_overloadable_no_prototype)
+            << NewFD;
+          Redeclaration = true;
+
+          // Turn this into a variadic function with no parameters.
+          QualType R = Context.getFunctionType(
+                     NewFD->getType()->getAs<FunctionType>()->getResultType(),
+                     0, 0, true, 0);
+          NewFD->setType(R);
+          return NewFD->setInvalidDecl();
+        }
+      }
+
+      switch (CheckOverload(NewFD, Previous, OldDecl)) {
+      case Ovl_Match:
+        Redeclaration = true;
+        if (isa<UsingShadowDecl>(OldDecl) && CurContext->isRecord()) {
+          HideUsingShadowDecl(S, cast<UsingShadowDecl>(OldDecl));
+          Redeclaration = false;
+        }
+        break;
+
+      case Ovl_NonFunction:
+        Redeclaration = true;
+        break;
+
+      case Ovl_Overload:
+        Redeclaration = false;
+        break;
+      }
+    }
+
+    if (Redeclaration) {
+      // NewFD and OldDecl represent declarations that need to be
+      // merged.
+      if (MergeFunctionDecl(NewFD, OldDecl))
+        return NewFD->setInvalidDecl();
+
+      Previous.clear();
+      Previous.addDecl(OldDecl);
+
+      if (FunctionTemplateDecl *OldTemplateDecl
+                                    = dyn_cast<FunctionTemplateDecl>(OldDecl)) {
+        NewFD->setPreviousDeclaration(OldTemplateDecl->getTemplatedDecl());        
+        FunctionTemplateDecl *NewTemplateDecl
+          = NewFD->getDescribedFunctionTemplate();
+        assert(NewTemplateDecl && "Template/non-template mismatch");
+        if (CXXMethodDecl *Method 
+              = dyn_cast<CXXMethodDecl>(NewTemplateDecl->getTemplatedDecl())) {
+          Method->setAccess(OldTemplateDecl->getAccess());
+          NewTemplateDecl->setAccess(OldTemplateDecl->getAccess());
+        }
+        
+        // If this is an explicit specialization of a member that is a function
+        // template, mark it as a member specialization.
+        if (IsExplicitSpecialization && 
+            NewTemplateDecl->getInstantiatedFromMemberTemplate()) {
+          NewTemplateDecl->setMemberSpecialization();
+          assert(OldTemplateDecl->isMemberSpecialization());
+        }
+      } else {
+        if (isa<CXXMethodDecl>(NewFD)) // Set access for out-of-line definitions
+          NewFD->setAccess(OldDecl->getAccess());
+        NewFD->setPreviousDeclaration(cast<FunctionDecl>(OldDecl));
+      }
+    }
+  }
+
+  // Semantic checking for this function declaration (in isolation).
+  if (getLangOptions().CPlusPlus) {
+    // C++-specific checks.
+    if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(NewFD)) {
+      CheckConstructor(Constructor);
+    } else if (CXXDestructorDecl *Destructor = 
+                dyn_cast<CXXDestructorDecl>(NewFD)) {
+      CXXRecordDecl *Record = Destructor->getParent();
+      QualType ClassType = Context.getTypeDeclType(Record);
+      
+      // FIXME: Shouldn't we be able to perform thisc heck even when the class
+      // type is dependent? Both gcc and edg can handle that.
+      if (!ClassType->isDependentType()) {
+        DeclarationName Name
+          = Context.DeclarationNames.getCXXDestructorName(
+                                        Context.getCanonicalType(ClassType));
+        if (NewFD->getDeclName() != Name) {
+          Diag(NewFD->getLocation(), diag::err_destructor_name);
+          return NewFD->setInvalidDecl();
+        }
+      }
+
+      Record->setUserDeclaredDestructor(true);
+      // C++ [class]p4: A POD-struct is an aggregate class that has [...] no
+      // user-defined destructor.
+      Record->setPOD(false);
+
+      // C++ [class.dtor]p3: A destructor is trivial if it is an implicitly-
+      // declared destructor.
+      // FIXME: C++0x: don't do this for "= default" destructors
+      Record->setHasTrivialDestructor(false);
+    } else if (CXXConversionDecl *Conversion
+               = dyn_cast<CXXConversionDecl>(NewFD)) {
+      ActOnConversionDeclarator(Conversion);
+    }
+
+    // Find any virtual functions that this function overrides.
+    if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(NewFD)) {
+      if (!Method->isFunctionTemplateSpecialization() && 
+          !Method->getDescribedFunctionTemplate())
+        AddOverriddenMethods(Method->getParent(), Method);
+    }
+
+    // Additional checks for the destructor; make sure we do this after we
+    // figure out whether the destructor is virtual.
+    if (CXXDestructorDecl *Destructor = dyn_cast<CXXDestructorDecl>(NewFD))
+      if (!Destructor->getParent()->isDependentType())
+        CheckDestructor(Destructor);
+
+    // Extra checking for C++ overloaded operators (C++ [over.oper]).
+    if (NewFD->isOverloadedOperator() &&
+        CheckOverloadedOperatorDeclaration(NewFD))
+      return NewFD->setInvalidDecl();
+
+    // Extra checking for C++0x literal operators (C++0x [over.literal]).
+    if (NewFD->getLiteralIdentifier() &&
+        CheckLiteralOperatorDeclaration(NewFD))
+      return NewFD->setInvalidDecl();
+
+    // In C++, check default arguments now that we have merged decls. Unless
+    // the lexical context is the class, because in this case this is done
+    // during delayed parsing anyway.
+    if (!CurContext->isRecord())
+      CheckCXXDefaultArguments(NewFD);
+  }
+}
+
+void Sema::CheckMain(FunctionDecl* FD) {
+  // C++ [basic.start.main]p3:  A program that declares main to be inline
+  //   or static is ill-formed.
+  // C99 6.7.4p4:  In a hosted environment, the inline function specifier
+  //   shall not appear in a declaration of main.
+  // static main is not an error under C99, but we should warn about it.
+  bool isInline = FD->isInlineSpecified();
+  bool isStatic = FD->getStorageClass() == FunctionDecl::Static;
+  if (isInline || isStatic) {
+    unsigned diagID = diag::warn_unusual_main_decl;
+    if (isInline || getLangOptions().CPlusPlus)
+      diagID = diag::err_unusual_main_decl;
+
+    int which = isStatic + (isInline << 1) - 1;
+    Diag(FD->getLocation(), diagID) << which;
+  }
+
+  QualType T = FD->getType();
+  assert(T->isFunctionType() && "function decl is not of function type");
+  const FunctionType* FT = T->getAs<FunctionType>();
+
+  if (!Context.hasSameUnqualifiedType(FT->getResultType(), Context.IntTy)) {
+    // TODO: add a replacement fixit to turn the return type into 'int'.
+    Diag(FD->getTypeSpecStartLoc(), diag::err_main_returns_nonint);
+    FD->setInvalidDecl(true);
+  }
+
+  // Treat protoless main() as nullary.
+  if (isa<FunctionNoProtoType>(FT)) return;
+
+  const FunctionProtoType* FTP = cast<const FunctionProtoType>(FT);
+  unsigned nparams = FTP->getNumArgs();
+  assert(FD->getNumParams() == nparams);
+
+  bool HasExtraParameters = (nparams > 3);
+
+  // Darwin passes an undocumented fourth argument of type char**.  If
+  // other platforms start sprouting these, the logic below will start
+  // getting shifty.
+  if (nparams == 4 &&
+      Context.Target.getTriple().getOS() == llvm::Triple::Darwin)
+    HasExtraParameters = false;
+
+  if (HasExtraParameters) {
+    Diag(FD->getLocation(), diag::err_main_surplus_args) << nparams;
+    FD->setInvalidDecl(true);
+    nparams = 3;
+  }
+
+  // FIXME: a lot of the following diagnostics would be improved
+  // if we had some location information about types.
+
+  QualType CharPP =
+    Context.getPointerType(Context.getPointerType(Context.CharTy));
+  QualType Expected[] = { Context.IntTy, CharPP, CharPP, CharPP };
+
+  for (unsigned i = 0; i < nparams; ++i) {
+    QualType AT = FTP->getArgType(i);
+
+    bool mismatch = true;
+
+    if (Context.hasSameUnqualifiedType(AT, Expected[i]))
+      mismatch = false;
+    else if (Expected[i] == CharPP) {
+      // As an extension, the following forms are okay:
+      //   char const **
+      //   char const * const *
+      //   char * const *
+
+      QualifierCollector qs;
+      const PointerType* PT;
+      if ((PT = qs.strip(AT)->getAs<PointerType>()) &&
+          (PT = qs.strip(PT->getPointeeType())->getAs<PointerType>()) &&
+          (QualType(qs.strip(PT->getPointeeType()), 0) == Context.CharTy)) {
+        qs.removeConst();
+        mismatch = !qs.empty();
+      }
+    }
+
+    if (mismatch) {
+      Diag(FD->getLocation(), diag::err_main_arg_wrong) << i << Expected[i];
+      // TODO: suggest replacing given type with expected type
+      FD->setInvalidDecl(true);
+    }
+  }
+
+  if (nparams == 1 && !FD->isInvalidDecl()) {
+    Diag(FD->getLocation(), diag::warn_main_one_arg);
+  }
+}
+
+bool Sema::CheckForConstantInitializer(Expr *Init, QualType DclT) {
+  // FIXME: Need strict checking.  In C89, we need to check for
+  // any assignment, increment, decrement, function-calls, or
+  // commas outside of a sizeof.  In C99, it's the same list,
+  // except that the aforementioned are allowed in unevaluated
+  // expressions.  Everything else falls under the
+  // "may accept other forms of constant expressions" exception.
+  // (We never end up here for C++, so the constant expression
+  // rules there don't matter.)
+  if (Init->isConstantInitializer(Context))
+    return false;
+  Diag(Init->getExprLoc(), diag::err_init_element_not_constant)
+    << Init->getSourceRange();
+  return true;
+}
+
+void Sema::AddInitializerToDecl(DeclPtrTy dcl, ExprArg init) {
+  AddInitializerToDecl(dcl, move(init), /*DirectInit=*/false);
+}
+
+/// AddInitializerToDecl - Adds the initializer Init to the
+/// declaration dcl. If DirectInit is true, this is C++ direct
+/// initialization rather than copy initialization.
+void Sema::AddInitializerToDecl(DeclPtrTy dcl, ExprArg init, bool DirectInit) {
+  Decl *RealDecl = dcl.getAs<Decl>();
+  // If there is no declaration, there was an error parsing it.  Just ignore
+  // the initializer.
+  if (RealDecl == 0)
+    return;
+
+  if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(RealDecl)) {
+    // With declarators parsed the way they are, the parser cannot
+    // distinguish between a normal initializer and a pure-specifier.
+    // Thus this grotesque test.
+    IntegerLiteral *IL;
+    Expr *Init = static_cast<Expr *>(init.get());
+    if ((IL = dyn_cast<IntegerLiteral>(Init)) && IL->getValue() == 0 &&
+        Context.getCanonicalType(IL->getType()) == Context.IntTy)
+      CheckPureMethod(Method, Init->getSourceRange());
+    else {
+      Diag(Method->getLocation(), diag::err_member_function_initialization)
+        << Method->getDeclName() << Init->getSourceRange();
+      Method->setInvalidDecl();
+    }
+    return;
+  }
+
+  VarDecl *VDecl = dyn_cast<VarDecl>(RealDecl);
+  if (!VDecl) {
+    if (getLangOptions().CPlusPlus &&
+        RealDecl->getLexicalDeclContext()->isRecord() &&
+        isa<NamedDecl>(RealDecl))
+      Diag(RealDecl->getLocation(), diag::err_member_initialization)
+        << cast<NamedDecl>(RealDecl)->getDeclName();
+    else
+      Diag(RealDecl->getLocation(), diag::err_illegal_initializer);
+    RealDecl->setInvalidDecl();
+    return;
+  }
+
+  // A definition must end up with a complete type, which means it must be
+  // complete with the restriction that an array type might be completed by the
+  // initializer; note that later code assumes this restriction.
+  QualType BaseDeclType = VDecl->getType();
+  if (const ArrayType *Array = Context.getAsIncompleteArrayType(BaseDeclType))
+    BaseDeclType = Array->getElementType();
+  if (RequireCompleteType(VDecl->getLocation(), BaseDeclType,
+                          diag::err_typecheck_decl_incomplete_type)) {
+    RealDecl->setInvalidDecl();
+    return;
+  }
+
+  // The variable can not have an abstract class type.
+  if (RequireNonAbstractType(VDecl->getLocation(), VDecl->getType(),
+                             diag::err_abstract_type_in_decl,
+                             AbstractVariableType))
+    VDecl->setInvalidDecl();
+
+  const VarDecl *Def;
+  if ((Def = VDecl->getDefinition()) && Def != VDecl) {
+    Diag(VDecl->getLocation(), diag::err_redefinition)
+      << VDecl->getDeclName();
+    Diag(Def->getLocation(), diag::note_previous_definition);
+    VDecl->setInvalidDecl();
+    return;
+  }
+
+  // Take ownership of the expression, now that we're sure we have somewhere
+  // to put it.
+  Expr *Init = init.takeAs<Expr>();
+  assert(Init && "missing initializer");
+
+  // Capture the variable that is being initialized and the style of
+  // initialization.
+  InitializedEntity Entity = InitializedEntity::InitializeVariable(VDecl);
+  
+  // FIXME: Poor source location information.
+  InitializationKind Kind
+    = DirectInit? InitializationKind::CreateDirect(VDecl->getLocation(),
+                                                   Init->getLocStart(),
+                                                   Init->getLocEnd())
+                : InitializationKind::CreateCopy(VDecl->getLocation(),
+                                                 Init->getLocStart());
+  
+  // Get the decls type and save a reference for later, since
+  // CheckInitializerTypes may change it.
+  QualType DclT = VDecl->getType(), SavT = DclT;
+  if (VDecl->isBlockVarDecl()) {
+    if (VDecl->hasExternalStorage()) { // C99 6.7.8p5
+      Diag(VDecl->getLocation(), diag::err_block_extern_cant_init);
+      VDecl->setInvalidDecl();
+    } else if (!VDecl->isInvalidDecl()) {
+      InitializationSequence InitSeq(*this, Entity, Kind, &Init, 1);
+      OwningExprResult Result = InitSeq.Perform(*this, Entity, Kind,
+                                          MultiExprArg(*this, (void**)&Init, 1),
+                                                &DclT);
+      if (Result.isInvalid()) {
+        VDecl->setInvalidDecl();
+        return;
+      }
+
+      Init = Result.takeAs<Expr>();
+
+      // C++ 3.6.2p2, allow dynamic initialization of static initializers.
+      // Don't check invalid declarations to avoid emitting useless diagnostics.
+      if (!getLangOptions().CPlusPlus && !VDecl->isInvalidDecl()) {
+        if (VDecl->getStorageClass() == VarDecl::Static) // C99 6.7.8p4.
+          CheckForConstantInitializer(Init, DclT);
+      }
+    }
+  } else if (VDecl->isStaticDataMember() &&
+             VDecl->getLexicalDeclContext()->isRecord()) {
+    // This is an in-class initialization for a static data member, e.g.,
+    //
+    // struct S {
+    //   static const int value = 17;
+    // };
+
+    // Attach the initializer
+    VDecl->setInit(Context, Init);
+
+    // C++ [class.mem]p4:
+    //   A member-declarator can contain a constant-initializer only
+    //   if it declares a static member (9.4) of const integral or
+    //   const enumeration type, see 9.4.2.
+    QualType T = VDecl->getType();
+    if (!T->isDependentType() &&
+        (!Context.getCanonicalType(T).isConstQualified() ||
+         !T->isIntegralType())) {
+      Diag(VDecl->getLocation(), diag::err_member_initialization)
+        << VDecl->getDeclName() << Init->getSourceRange();
+      VDecl->setInvalidDecl();
+    } else {
+      // C++ [class.static.data]p4:
+      //   If a static data member is of const integral or const
+      //   enumeration type, its declaration in the class definition
+      //   can specify a constant-initializer which shall be an
+      //   integral constant expression (5.19).
+      if (!Init->isTypeDependent() &&
+          !Init->getType()->isIntegralType()) {
+        // We have a non-dependent, non-integral or enumeration type.
+        Diag(Init->getSourceRange().getBegin(),
+             diag::err_in_class_initializer_non_integral_type)
+          << Init->getType() << Init->getSourceRange();
+        VDecl->setInvalidDecl();
+      } else if (!Init->isTypeDependent() && !Init->isValueDependent()) {
+        // Check whether the expression is a constant expression.
+        llvm::APSInt Value;
+        SourceLocation Loc;
+        if (!Init->isIntegerConstantExpr(Value, Context, &Loc)) {
+          Diag(Loc, diag::err_in_class_initializer_non_constant)
+            << Init->getSourceRange();
+          VDecl->setInvalidDecl();
+        } else if (!VDecl->getType()->isDependentType())
+          ImpCastExprToType(Init, VDecl->getType(), CastExpr::CK_IntegralCast);
+      }
+    }
+  } else if (VDecl->isFileVarDecl()) {
+    if (VDecl->getStorageClass() == VarDecl::Extern)
+      Diag(VDecl->getLocation(), diag::warn_extern_init);
+    if (!VDecl->isInvalidDecl()) {
+      InitializationSequence InitSeq(*this, Entity, Kind, &Init, 1);
+      OwningExprResult Result = InitSeq.Perform(*this, Entity, Kind,
+                                          MultiExprArg(*this, (void**)&Init, 1),
+                                                &DclT);
+      if (Result.isInvalid()) {
+        VDecl->setInvalidDecl();
+        return;
+      }
+
+      Init = Result.takeAs<Expr>();
+    }
+
+    // C++ 3.6.2p2, allow dynamic initialization of static initializers.
+    // Don't check invalid declarations to avoid emitting useless diagnostics.
+    if (!getLangOptions().CPlusPlus && !VDecl->isInvalidDecl()) {
+      // C99 6.7.8p4. All file scoped initializers need to be constant.
+      CheckForConstantInitializer(Init, DclT);
+    }
+  }
+  // If the type changed, it means we had an incomplete type that was
+  // completed by the initializer. For example:
+  //   int ary[] = { 1, 3, 5 };
+  // "ary" transitions from a VariableArrayType to a ConstantArrayType.
+  if (!VDecl->isInvalidDecl() && (DclT != SavT)) {
+    VDecl->setType(DclT);
+    Init->setType(DclT);
+  }
+
+  Init = MaybeCreateCXXExprWithTemporaries(Init);
+  // Attach the initializer to the decl.
+  VDecl->setInit(Context, Init);
+
+  if (getLangOptions().CPlusPlus) {
+    // Make sure we mark the destructor as used if necessary.
+    QualType InitType = VDecl->getType();
+    while (const ArrayType *Array = Context.getAsArrayType(InitType))
+      InitType = Context.getBaseElementType(Array);
+    if (const RecordType *Record = InitType->getAs<RecordType>())
+      FinalizeVarWithDestructor(VDecl, Record);
+  }
+
+  return;
+}
+
+void Sema::ActOnUninitializedDecl(DeclPtrTy dcl,
+                                  bool TypeContainsUndeducedAuto) {
+  Decl *RealDecl = dcl.getAs<Decl>();
+
+  // If there is no declaration, there was an error parsing it. Just ignore it.
+  if (RealDecl == 0)
+    return;
+
+  if (VarDecl *Var = dyn_cast<VarDecl>(RealDecl)) {
+    QualType Type = Var->getType();
+
+    // C++0x [dcl.spec.auto]p3
+    if (TypeContainsUndeducedAuto) {
+      Diag(Var->getLocation(), diag::err_auto_var_requires_init)
+        << Var->getDeclName() << Type;
+      Var->setInvalidDecl();
+      return;
+    }
+
+    switch (Var->isThisDeclarationADefinition()) {
+    case VarDecl::Definition:
+      if (!Var->isStaticDataMember() || !Var->getAnyInitializer())
+        break;
+
+      // We have an out-of-line definition of a static data member
+      // that has an in-class initializer, so we type-check this like
+      // a declaration. 
+      //
+      // Fall through
+      
+    case VarDecl::DeclarationOnly:
+      // It's only a declaration. 
+
+      // 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 (!Type->isDependentType() && Var->isBlockVarDecl() && 
+          !Var->getLinkage() && !Var->isInvalidDecl() &&
+          RequireCompleteType(Var->getLocation(), Type,
+                              diag::err_typecheck_decl_incomplete_type))
+        Var->setInvalidDecl();
+
+      // Make sure that the type is not abstract.
+      if (!Type->isDependentType() && !Var->isInvalidDecl() &&
+          RequireNonAbstractType(Var->getLocation(), Type,
+                                 diag::err_abstract_type_in_decl,
+                                 AbstractVariableType))
+        Var->setInvalidDecl();
+      return;
+
+    case VarDecl::TentativeDefinition:
+      // File scope. C99 6.9.2p2: A declaration of an identifier for an
+      // 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 (!Var->isInvalidDecl()) {
+        if (const IncompleteArrayType *ArrayT
+                                    = Context.getAsIncompleteArrayType(Type)) {
+          if (RequireCompleteType(Var->getLocation(),
+                                  ArrayT->getElementType(),
+                                  diag::err_illegal_decl_array_incomplete_type))
+            Var->setInvalidDecl();
+        } else if (Var->getStorageClass() == 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.
+          // NOTE: code such as the following
+          //     static struct s;
+          //     struct s { int a; };
+          // is accepted by gcc. Hence here we issue a warning instead of
+          // an error and we do not invalidate the static declaration.
+          // NOTE: to avoid multiple warnings, only check the first declaration.
+          if (Var->getPreviousDeclaration() == 0)
+            RequireCompleteType(Var->getLocation(), Type,
+                                diag::ext_typecheck_decl_incomplete_type);
+        }
+      }
+
+      // Record the tentative definition; we're done.
+      if (!Var->isInvalidDecl())
+        TentativeDefinitions.push_back(Var);
+      return;
+    }
+
+    // Provide a specific diagnostic for uninitialized variable
+    // definitions with incomplete array type.
+    if (Type->isIncompleteArrayType()) {
+      Diag(Var->getLocation(),
+           diag::err_typecheck_incomplete_array_needs_initializer);
+      Var->setInvalidDecl();
+      return;
+    }
+
+   // Provide a specific diagnostic for uninitialized variable
+   // definitions with reference type.
+   if (Type->isReferenceType()) {
+     Diag(Var->getLocation(), diag::err_reference_var_requires_init)
+       << Var->getDeclName()
+       << SourceRange(Var->getLocation(), Var->getLocation());
+     Var->setInvalidDecl();
+     return;
+   }
+
+    // Do not attempt to type-check the default initializer for a
+    // variable with dependent type.
+    if (Type->isDependentType())
+      return;
+
+    if (Var->isInvalidDecl())
+      return;
+
+    if (RequireCompleteType(Var->getLocation(), 
+                            Context.getBaseElementType(Type),
+                            diag::err_typecheck_decl_incomplete_type)) {
+      Var->setInvalidDecl();
+      return;
+    }
+
+    // The variable can not have an abstract class type.
+    if (RequireNonAbstractType(Var->getLocation(), Type,
+                               diag::err_abstract_type_in_decl,
+                               AbstractVariableType)) {
+      Var->setInvalidDecl();
+      return;
+    }
+
+    InitializedEntity Entity = InitializedEntity::InitializeVariable(Var);
+    InitializationKind Kind
+      = InitializationKind::CreateDefault(Var->getLocation());
+    
+    InitializationSequence InitSeq(*this, Entity, Kind, 0, 0);
+    OwningExprResult Init = InitSeq.Perform(*this, Entity, Kind,
+                                            MultiExprArg(*this, 0, 0));
+    if (Init.isInvalid())
+      Var->setInvalidDecl();
+    else {
+      if (Init.get())
+        Var->setInit(Context, 
+                     MaybeCreateCXXExprWithTemporaries(Init.takeAs<Expr>()));
+
+      if (getLangOptions().CPlusPlus)
+        if (const RecordType *Record
+                        = Context.getBaseElementType(Type)->getAs<RecordType>())
+          FinalizeVarWithDestructor(Var, Record);
+    }
+  }
+}
+
+Sema::DeclGroupPtrTy Sema::FinalizeDeclaratorGroup(Scope *S, const DeclSpec &DS,
+                                                   DeclPtrTy *Group,
+                                                   unsigned NumDecls) {
+  llvm::SmallVector<Decl*, 8> Decls;
+
+  if (DS.isTypeSpecOwned())
+    Decls.push_back((Decl*)DS.getTypeRep());
+
+  for (unsigned i = 0; i != NumDecls; ++i)
+    if (Decl *D = Group[i].getAs<Decl>())
+      Decls.push_back(D);
+
+  return DeclGroupPtrTy::make(DeclGroupRef::Create(Context,
+                                                   Decls.data(), Decls.size()));
+}
+
+
+/// ActOnParamDeclarator - Called from Parser::ParseFunctionDeclarator()
+/// to introduce parameters into function prototype scope.
+Sema::DeclPtrTy
+Sema::ActOnParamDeclarator(Scope *S, Declarator &D) {
+  const DeclSpec &DS = D.getDeclSpec();
+
+  // Verify C99 6.7.5.3p2: The only SCS allowed is 'register'.
+  VarDecl::StorageClass StorageClass = VarDecl::None;
+  if (DS.getStorageClassSpec() == DeclSpec::SCS_register) {
+    StorageClass = VarDecl::Register;
+  } else if (DS.getStorageClassSpec() != DeclSpec::SCS_unspecified) {
+    Diag(DS.getStorageClassSpecLoc(),
+         diag::err_invalid_storage_class_in_func_decl);
+    D.getMutableDeclSpec().ClearStorageClassSpecs();
+  }
+
+  if (D.getDeclSpec().isThreadSpecified())
+    Diag(D.getDeclSpec().getThreadSpecLoc(), diag::err_invalid_thread);
+
+  DiagnoseFunctionSpecifiers(D);
+
+  // Check that there are no default arguments inside the type of this
+  // parameter (C++ only).
+  if (getLangOptions().CPlusPlus)
+    CheckExtraCXXDefaultArguments(D);
+
+  TypeSourceInfo *TInfo = 0;
+  TagDecl *OwnedDecl = 0;
+  QualType parmDeclType = GetTypeForDeclarator(D, S, &TInfo, &OwnedDecl);
+
+  if (getLangOptions().CPlusPlus && OwnedDecl && OwnedDecl->isDefinition()) {
+    // C++ [dcl.fct]p6:
+    //   Types shall not be defined in return or parameter types.
+    Diag(OwnedDecl->getLocation(), diag::err_type_defined_in_param_type)
+      << Context.getTypeDeclType(OwnedDecl);
+  }
+
+  // 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.
+  IdentifierInfo *II = D.getIdentifier();
+  if (II) {
+    if (NamedDecl *PrevDecl = LookupSingleName(S, II, LookupOrdinaryName)) {
+      if (PrevDecl->isTemplateParameter()) {
+        // Maybe we will complain about the shadowed template parameter.
+        DiagnoseTemplateParameterShadow(D.getIdentifierLoc(), PrevDecl);
+        // Just pretend that we didn't see the previous declaration.
+        PrevDecl = 0;
+      } else if (S->isDeclScope(DeclPtrTy::make(PrevDecl))) {
+        Diag(D.getIdentifierLoc(), diag::err_param_redefinition) << II;
+
+        // Recover by removing the name
+        II = 0;
+        D.SetIdentifier(0, D.getIdentifierLoc());
+      }
+    }
+  }
+
+  // Parameters can not be abstract class types.
+  // For record types, this is done by the AbstractClassUsageDiagnoser once
+  // the class has been completely parsed.
+  if (!CurContext->isRecord() &&
+      RequireNonAbstractType(D.getIdentifierLoc(), parmDeclType,
+                             diag::err_abstract_type_in_decl,
+                             AbstractParamType))
+    D.setInvalidType(true);
+
+  QualType T = adjustParameterType(parmDeclType);
+
+  // Temporarily put parameter variables in the translation unit, not
+  // the enclosing context.  This prevents them from accidentally
+  // looking like class members in C++.
+  DeclContext *DC = Context.getTranslationUnitDecl();
+
+  ParmVarDecl *New
+    = ParmVarDecl::Create(Context, DC, D.getIdentifierLoc(), II,
+                          T, TInfo, StorageClass, 0);
+
+  if (D.isInvalidType())
+    New->setInvalidDecl();
+
+  // Parameter declarators cannot be interface types. All ObjC objects are
+  // passed by reference.
+  if (T->isObjCInterfaceType()) {
+    Diag(D.getIdentifierLoc(),
+         diag::err_object_cannot_be_passed_returned_by_value) << 1 << T;
+    New->setInvalidDecl();
+  }
+
+  // Parameter declarators cannot be qualified (C++ [dcl.meaning]p1).
+  if (D.getCXXScopeSpec().isSet()) {
+    Diag(D.getIdentifierLoc(), diag::err_qualified_param_declarator)
+      << D.getCXXScopeSpec().getRange();
+    New->setInvalidDecl();
+  }
+  
+  // ISO/IEC TR 18037 S6.7.3: "The type of an object with automatic storage 
+  // duration shall not be qualified by an address-space qualifier."
+  // Since all parameters have automatic store duration, they can not have
+  // an address space.
+  if (T.getAddressSpace() != 0) {
+    Diag(D.getIdentifierLoc(),  
+         diag::err_arg_with_address_space);
+    New->setInvalidDecl();
+  }   
+  
+  
+  // Add the parameter declaration into this scope.
+  S->AddDecl(DeclPtrTy::make(New));
+  if (II)
+    IdResolver.AddDecl(New);
+
+  ProcessDeclAttributes(S, New, D);
+
+  if (New->hasAttr<BlocksAttr>()) {
+    Diag(New->getLocation(), diag::err_block_on_nonlocal);
+  }
+  return DeclPtrTy::make(New);
+}
+
+void Sema::ActOnObjCCatchParam(DeclPtrTy D) {
+  ParmVarDecl *Param = cast<ParmVarDecl>(D.getAs<Decl>());
+  Param->setDeclContext(CurContext);
+}
+
+void Sema::ActOnFinishKNRParamDeclarations(Scope *S, Declarator &D,
+                                           SourceLocation LocAfterDecls) {
+  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 (int i = FTI.NumArgs; i != 0; /* decrement in loop */) {
+      --i;
+      if (FTI.ArgInfo[i].Param == 0) {
+        llvm::SmallString<256> Code;
+        llvm::raw_svector_ostream(Code) << "  int "
+                                        << FTI.ArgInfo[i].Ident->getName()
+                                        << ";\n";
+        Diag(FTI.ArgInfo[i].IdentLoc, diag::ext_param_not_declared)
+          << FTI.ArgInfo[i].Ident
+          << CodeModificationHint::CreateInsertion(LocAfterDecls, Code.str());
+
+        // Implicitly declare the argument as type 'int' for lack of a better
+        // type.
+        DeclSpec DS;
+        const char* PrevSpec; // unused
+        unsigned DiagID; // unused
+        DS.SetTypeSpecType(DeclSpec::TST_int, FTI.ArgInfo[i].IdentLoc,
+                           PrevSpec, DiagID);
+        Declarator ParamD(DS, Declarator::KNRTypeListContext);
+        ParamD.SetIdentifier(FTI.ArgInfo[i].Ident, FTI.ArgInfo[i].IdentLoc);
+        FTI.ArgInfo[i].Param = ActOnParamDeclarator(S, ParamD);
+      }
+    }
+  }
+}
+
+Sema::DeclPtrTy Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope,
+                                              Declarator &D) {
+  assert(getCurFunctionDecl() == 0 && "Function parsing confused");
+  assert(D.getTypeObject(0).Kind == DeclaratorChunk::Function &&
+         "Not a function declarator!");
+  DeclaratorChunk::FunctionTypeInfo &FTI = D.getTypeObject(0).Fun;
+
+  if (FTI.hasPrototype) {
+    // FIXME: Diagnose arguments without names in C.
+  }
+
+  Scope *ParentScope = FnBodyScope->getParent();
+
+  DeclPtrTy DP = HandleDeclarator(ParentScope, D,
+                                  MultiTemplateParamsArg(*this),
+                                  /*IsFunctionDefinition=*/true);
+  return ActOnStartOfFunctionDef(FnBodyScope, DP);
+}
+
+static bool ShouldWarnAboutMissingPrototype(const FunctionDecl *FD) {
+  // Don't warn about invalid declarations.
+  if (FD->isInvalidDecl())
+    return false;
+
+  // Or declarations that aren't global.
+  if (!FD->isGlobal())
+    return false;
+
+  // Don't warn about C++ member functions.
+  if (isa<CXXMethodDecl>(FD))
+    return false;
+
+  // Don't warn about 'main'.
+  if (FD->isMain())
+    return false;
+
+  // Don't warn about inline functions.
+  if (FD->isInlineSpecified())
+    return false;
+
+  // Don't warn about function templates.
+  if (FD->getDescribedFunctionTemplate())
+    return false;
+
+  // Don't warn about function template specializations.
+  if (FD->isFunctionTemplateSpecialization())
+    return false;
+
+  bool MissingPrototype = true;
+  for (const FunctionDecl *Prev = FD->getPreviousDeclaration();
+       Prev; Prev = Prev->getPreviousDeclaration()) {
+    // Ignore any declarations that occur in function or method
+    // scope, because they aren't visible from the header.
+    if (Prev->getDeclContext()->isFunctionOrMethod())
+      continue;
+      
+    MissingPrototype = !Prev->getType()->isFunctionProtoType();
+    break;
+  }
+    
+  return MissingPrototype;
+}
+
+Sema::DeclPtrTy Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, DeclPtrTy D) {
+  // Clear the last template instantiation error context.
+  LastTemplateInstantiationErrorContext = ActiveTemplateInstantiation();
+  
+  if (!D)
+    return D;
+  FunctionDecl *FD = 0;
+
+  if (FunctionTemplateDecl *FunTmpl
+        = dyn_cast<FunctionTemplateDecl>(D.getAs<Decl>()))
+    FD = FunTmpl->getTemplatedDecl();
+  else
+    FD = cast<FunctionDecl>(D.getAs<Decl>());
+
+  CurFunctionNeedsScopeChecking = false;
+
+  // See if this is a redefinition.
+  const FunctionDecl *Definition;
+  if (FD->getBody(Definition)) {
+    Diag(FD->getLocation(), diag::err_redefinition) << FD->getDeclName();
+    Diag(Definition->getLocation(), diag::note_previous_definition);
+  }
+
+  // Builtin functions cannot be defined.
+  if (unsigned BuiltinID = FD->getBuiltinID()) {
+    if (!Context.BuiltinInfo.isPredefinedLibFunction(BuiltinID)) {
+      Diag(FD->getLocation(), diag::err_builtin_definition) << FD;
+      FD->setInvalidDecl();
+    }
+  }
+
+  // The return type of a function definition must be complete
+  // (C99 6.9.1p3, C++ [dcl.fct]p6).
+  QualType ResultType = FD->getResultType();
+  if (!ResultType->isDependentType() && !ResultType->isVoidType() &&
+      !FD->isInvalidDecl() &&
+      RequireCompleteType(FD->getLocation(), ResultType,
+                          diag::err_func_def_incomplete_result))
+    FD->setInvalidDecl();
+
+  // GNU warning -Wmissing-prototypes:
+  //   Warn if a global function is defined without a previous
+  //   prototype declaration. This warning is issued even if the
+  //   definition itself provides a prototype. The aim is to detect
+  //   global functions that fail to be declared in header files.
+  if (ShouldWarnAboutMissingPrototype(FD))
+    Diag(FD->getLocation(), diag::warn_missing_prototype) << FD;
+
+  if (FnBodyScope)
+    PushDeclContext(FnBodyScope, FD);
+
+  // Check the validity of our function parameters
+  CheckParmsForFunctionDef(FD);
+
+  // Introduce our parameters into the function scope
+  for (unsigned p = 0, NumParams = FD->getNumParams(); p < NumParams; ++p) {
+    ParmVarDecl *Param = FD->getParamDecl(p);
+    Param->setOwningFunction(FD);
+
+    // If this has an identifier, add it to the scope stack.
+    if (Param->getIdentifier() && FnBodyScope)
+      PushOnScopeChains(Param, FnBodyScope);
+  }
+
+  // Checking attributes of current function definition
+  // dllimport attribute.
+  if (FD->getAttr<DLLImportAttr>() &&
+      (!FD->getAttr<DLLExportAttr>())) {
+    // dllimport attribute cannot be applied to definition.
+    if (!(FD->getAttr<DLLImportAttr>())->isInherited()) {
+      Diag(FD->getLocation(),
+           diag::err_attribute_can_be_applied_only_to_symbol_declaration)
+        << "dllimport";
+      FD->setInvalidDecl();
+      return DeclPtrTy::make(FD);
+    } else {
+      // If a symbol previously declared dllimport is later defined, the
+      // attribute is ignored in subsequent references, and a warning is
+      // emitted.
+      Diag(FD->getLocation(),
+           diag::warn_redeclaration_without_attribute_prev_attribute_ignored)
+        << FD->getNameAsCString() << "dllimport";
+    }
+  }
+  return DeclPtrTy::make(FD);
+}
+
+Sema::DeclPtrTy Sema::ActOnFinishFunctionBody(DeclPtrTy D, StmtArg BodyArg) {
+  return ActOnFinishFunctionBody(D, move(BodyArg), false);
+}
+
+Sema::DeclPtrTy Sema::ActOnFinishFunctionBody(DeclPtrTy D, StmtArg BodyArg,
+                                              bool IsInstantiation) {
+  Decl *dcl = D.getAs<Decl>();
+  Stmt *Body = BodyArg.takeAs<Stmt>();
+
+  // Don't generate EH edges for CallExprs as we'd like to avoid the n^2
+  // explosion for destrutors that can result and the compile time hit.
+  AnalysisContext AC(dcl, false);
+  FunctionDecl *FD = 0;
+  FunctionTemplateDecl *FunTmpl = dyn_cast_or_null<FunctionTemplateDecl>(dcl);
+  if (FunTmpl)
+    FD = FunTmpl->getTemplatedDecl();
+  else
+    FD = dyn_cast_or_null<FunctionDecl>(dcl);
+
+  if (FD) {
+    FD->setBody(Body);
+    if (FD->isMain())
+      // C and C++ allow for main to automagically return 0.
+      // Implements C++ [basic.start.main]p5 and C99 5.1.2.2.3.
+      FD->setHasImplicitReturnZero(true);
+    else
+      CheckFallThroughForFunctionDef(FD, Body, AC);
+
+    if (!FD->isInvalidDecl())
+      DiagnoseUnusedParameters(FD->param_begin(), FD->param_end());
+
+    if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(FD))
+      MaybeMarkVirtualMembersReferenced(Method->getLocation(), Method);
+
+    assert(FD == getCurFunctionDecl() && "Function parsing confused");
+  } else if (ObjCMethodDecl *MD = dyn_cast_or_null<ObjCMethodDecl>(dcl)) {
+    assert(MD == getCurMethodDecl() && "Method parsing confused");
+    MD->setBody(Body);
+    CheckFallThroughForFunctionDef(MD, Body, AC);
+    MD->setEndLoc(Body->getLocEnd());
+
+    if (!MD->isInvalidDecl())
+      DiagnoseUnusedParameters(MD->param_begin(), MD->param_end());
+  } else {
+    Body->Destroy(Context);
+    return DeclPtrTy();
+  }
+  if (!IsInstantiation)
+    PopDeclContext();
+
+  // Verify and clean out per-function state.
+
+  assert(&getLabelMap() == &FunctionLabelMap && "Didn't pop block right?");
+
+  // Check goto/label use.
+  for (llvm::DenseMap<IdentifierInfo*, LabelStmt*>::iterator
+       I = FunctionLabelMap.begin(), E = FunctionLabelMap.end(); I != E; ++I) {
+    LabelStmt *L = I->second;
+
+    // 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 (L->getSubStmt() != 0)
+      continue;
+
+    // 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.
+    if (Body == 0) {
+      // The whole function wasn't parsed correctly, just delete this.
+      L->Destroy(Context);
+      continue;
+    }
+
+    // Otherwise, the body is valid: we want to stitch the label decl into the
+    // function somewhere so that it is properly owned and so that the goto
+    // has a valid target.  Do this by creating a new compound stmt with the
+    // label in it.
+
+    // Give the label a sub-statement.
+    L->setSubStmt(new (Context) NullStmt(L->getIdentLoc()));
+
+    CompoundStmt *Compound = isa<CXXTryStmt>(Body) ?
+                               cast<CXXTryStmt>(Body)->getTryBlock() :
+                               cast<CompoundStmt>(Body);
+    std::vector<Stmt*> Elements(Compound->body_begin(), Compound->body_end());
+    Elements.push_back(L);
+    Compound->setStmts(Context, &Elements[0], Elements.size());
+  }
+  FunctionLabelMap.clear();
+
+  if (!Body) return D;
+
+  CheckUnreachable(AC);
+
+  // Verify that that gotos and switch cases don't jump into scopes illegally.
+  if (CurFunctionNeedsScopeChecking)
+    DiagnoseInvalidJumps(Body);
+
+  // C++ constructors that have function-try-blocks can't have return
+  // statements in the handlers of that block. (C++ [except.handle]p14)
+  // Verify this.
+  if (FD && isa<CXXConstructorDecl>(FD) && isa<CXXTryStmt>(Body))
+    DiagnoseReturnInConstructorExceptionHandler(cast<CXXTryStmt>(Body));
+
+  if (CXXDestructorDecl *Destructor = dyn_cast<CXXDestructorDecl>(dcl))
+    MarkBaseAndMemberDestructorsReferenced(Destructor);
+  
+  // If any errors have occurred, clear out any temporaries that may have
+  // been leftover. This ensures that these temporaries won't be picked up for
+  // deletion in some later function.
+  if (PP.getDiagnostics().hasErrorOccurred())
+    ExprTemporaries.clear();
+  
+  assert(ExprTemporaries.empty() && "Leftover temporaries in function");
+  return D;
+}
+
+/// ImplicitlyDefineFunction - An undeclared identifier was used in a function
+/// call, forming a call to an implicitly defined function (per C99 6.5.1p2).
+NamedDecl *Sema::ImplicitlyDefineFunction(SourceLocation Loc,
+                                          IdentifierInfo &II, Scope *S) {
+  // Before we produce a declaration for an implicitly defined
+  // function, see whether there was a locally-scoped declaration of
+  // this name as a function or variable. If so, use that
+  // (non-visible) declaration, and complain about it.
+  llvm::DenseMap<DeclarationName, NamedDecl *>::iterator Pos
+    = LocallyScopedExternalDecls.find(&II);
+  if (Pos != LocallyScopedExternalDecls.end()) {
+    Diag(Loc, diag::warn_use_out_of_scope_declaration) << Pos->second;
+    Diag(Pos->second->getLocation(), diag::note_previous_declaration);
+    return Pos->second;
+  }
+
+  // Extension in C99.  Legal in C90, but warn about it.
+  if (II.getName().startswith("__builtin_"))
+    Diag(Loc, diag::warn_builtin_unknown) << &II;
+  else if (getLangOptions().C99)
+    Diag(Loc, diag::ext_implicit_function_decl) << &II;
+  else
+    Diag(Loc, diag::warn_implicit_function_decl) << &II;
+
+  // Set a Declarator for the implicit definition: int foo();
+  const char *Dummy;
+  DeclSpec DS;
+  unsigned DiagID;
+  bool Error = DS.SetTypeSpecType(DeclSpec::TST_int, Loc, Dummy, DiagID);
+  Error = Error; // Silence warning.
+  assert(!Error && "Error setting up implicit decl!");
+  Declarator D(DS, Declarator::BlockContext);
+  D.AddTypeInfo(DeclaratorChunk::getFunction(false, false, SourceLocation(), 0,
+                                             0, 0, false, SourceLocation(),
+                                             false, 0,0,0, Loc, Loc, D),
+                SourceLocation());
+  D.SetIdentifier(&II, Loc);
+
+  // Insert this function into translation-unit scope.
+
+  DeclContext *PrevDC = CurContext;
+  CurContext = Context.getTranslationUnitDecl();
+
+  FunctionDecl *FD =
+ dyn_cast<FunctionDecl>(ActOnDeclarator(TUScope, D).getAs<Decl>());
+  FD->setImplicit();
+
+  CurContext = PrevDC;
+
+  AddKnownFunctionAttributes(FD);
+
+  return FD;
+}
+
+/// \brief Adds any function attributes that we know a priori based on
+/// the declaration of this function.
+///
+/// These attributes can apply both to implicitly-declared builtins
+/// (like __builtin___printf_chk) or to library-declared functions
+/// like NSLog or printf.
+void Sema::AddKnownFunctionAttributes(FunctionDecl *FD) {
+  if (FD->isInvalidDecl())
+    return;
+
+  // If this is a built-in function, map its builtin attributes to
+  // actual attributes.
+  if (unsigned BuiltinID = FD->getBuiltinID()) {
+    // Handle printf-formatting attributes.
+    unsigned FormatIdx;
+    bool HasVAListArg;
+    if (Context.BuiltinInfo.isPrintfLike(BuiltinID, FormatIdx, HasVAListArg)) {
+      if (!FD->getAttr<FormatAttr>())
+        FD->addAttr(::new (Context) FormatAttr("printf", FormatIdx + 1,
+                                             HasVAListArg ? 0 : FormatIdx + 2));
+    }
+
+    // Mark const if we don't care about errno and that is the only
+    // thing preventing the function from being const. This allows
+    // IRgen to use LLVM intrinsics for such functions.
+    if (!getLangOptions().MathErrno &&
+        Context.BuiltinInfo.isConstWithoutErrno(BuiltinID)) {
+      if (!FD->getAttr<ConstAttr>())
+        FD->addAttr(::new (Context) ConstAttr());
+    }
+
+    if (Context.BuiltinInfo.isNoReturn(BuiltinID))
+      FD->setType(Context.getNoReturnType(FD->getType()));
+    if (Context.BuiltinInfo.isNoThrow(BuiltinID))
+      FD->addAttr(::new (Context) NoThrowAttr());
+    if (Context.BuiltinInfo.isConst(BuiltinID))
+      FD->addAttr(::new (Context) ConstAttr());
+  }
+
+  IdentifierInfo *Name = FD->getIdentifier();
+  if (!Name)
+    return;
+  if ((!getLangOptions().CPlusPlus &&
+       FD->getDeclContext()->isTranslationUnit()) ||
+      (isa<LinkageSpecDecl>(FD->getDeclContext()) &&
+       cast<LinkageSpecDecl>(FD->getDeclContext())->getLanguage() ==
+       LinkageSpecDecl::lang_c)) {
+    // Okay: this could be a libc/libm/Objective-C function we know
+    // about.
+  } else
+    return;
+
+  if (Name->isStr("NSLog") || Name->isStr("NSLogv")) {
+    // FIXME: NSLog and NSLogv should be target specific
+    if (const FormatAttr *Format = FD->getAttr<FormatAttr>()) {
+      // FIXME: We known better than our headers.
+      const_cast<FormatAttr *>(Format)->setType("printf");
+    } else
+      FD->addAttr(::new (Context) FormatAttr("printf", 1,
+                                             Name->isStr("NSLogv") ? 0 : 2));
+  } else if (Name->isStr("asprintf") || Name->isStr("vasprintf")) {
+    // FIXME: asprintf and vasprintf aren't C99 functions. Should they be
+    // target-specific builtins, perhaps?
+    if (!FD->getAttr<FormatAttr>())
+      FD->addAttr(::new (Context) FormatAttr("printf", 2,
+                                             Name->isStr("vasprintf") ? 0 : 3));
+  }
+}
+
+TypedefDecl *Sema::ParseTypedefDecl(Scope *S, Declarator &D, QualType T,
+                                    TypeSourceInfo *TInfo) {
+  assert(D.getIdentifier() && "Wrong callback for declspec without declarator");
+  assert(!T.isNull() && "GetTypeForDeclarator() returned null type");
+
+  if (!TInfo) {
+    assert(D.isInvalidType() && "no declarator info for valid type");
+    TInfo = Context.getTrivialTypeSourceInfo(T);
+  }
+
+  // Scope manipulation handled by caller.
+  TypedefDecl *NewTD = TypedefDecl::Create(Context, CurContext,
+                                           D.getIdentifierLoc(),
+                                           D.getIdentifier(),
+                                           TInfo);
+
+  if (const TagType *TT = T->getAs<TagType>()) {
+    TagDecl *TD = TT->getDecl();
+
+    // If the TagDecl that the TypedefDecl points to is an anonymous decl
+    // keep track of the TypedefDecl.
+    if (!TD->getIdentifier() && !TD->getTypedefForAnonDecl())
+      TD->setTypedefForAnonDecl(NewTD);
+  }
+
+  if (D.isInvalidType())
+    NewTD->setInvalidDecl();
+  return NewTD;
+}
+
+
+/// \brief Determine whether a tag with a given kind is acceptable
+/// as a redeclaration of the given tag declaration.
+///
+/// \returns true if the new tag kind is acceptable, false otherwise.
+bool Sema::isAcceptableTagRedeclaration(const TagDecl *Previous,
+                                        TagDecl::TagKind NewTag,
+                                        SourceLocation NewTagLoc,
+                                        const IdentifierInfo &Name) {
+  // C++ [dcl.type.elab]p3:
+  //   The class-key or enum keyword present in the
+  //   elaborated-type-specifier shall agree in kind with the
+  //   declaration to which the name in theelaborated-type-specifier
+  //   refers. This rule also applies to the form of
+  //   elaborated-type-specifier that declares a class-name or
+  //   friend class since it can be construed as referring to the
+  //   definition of the class. Thus, in any
+  //   elaborated-type-specifier, the enum keyword shall be used to
+  //   refer to an enumeration (7.2), the union class-keyshall be
+  //   used to refer to a union (clause 9), and either the class or
+  //   struct class-key shall be used to refer to a class (clause 9)
+  //   declared using the class or struct class-key.
+  TagDecl::TagKind OldTag = Previous->getTagKind();
+  if (OldTag == NewTag)
+    return true;
+
+  if ((OldTag == TagDecl::TK_struct || OldTag == TagDecl::TK_class) &&
+      (NewTag == TagDecl::TK_struct || NewTag == TagDecl::TK_class)) {
+    // Warn about the struct/class tag mismatch.
+    bool isTemplate = false;
+    if (const CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(Previous))
+      isTemplate = Record->getDescribedClassTemplate();
+
+    Diag(NewTagLoc, diag::warn_struct_class_tag_mismatch)
+      << (NewTag == TagDecl::TK_class)
+      << isTemplate << &Name
+      << CodeModificationHint::CreateReplacement(SourceRange(NewTagLoc),
+                              OldTag == TagDecl::TK_class? "class" : "struct");
+    Diag(Previous->getLocation(), diag::note_previous_use);
+    return true;
+  }
+  return false;
+}
+
+/// ActOnTag - 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.
+/// TagSpec indicates what kind of tag this is. TUK indicates whether this is a
+/// reference/declaration/definition of a tag.
+Sema::DeclPtrTy Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
+                               SourceLocation KWLoc, const CXXScopeSpec &SS,
+                               IdentifierInfo *Name, SourceLocation NameLoc,
+                               AttributeList *Attr, AccessSpecifier AS,
+                               MultiTemplateParamsArg TemplateParameterLists,
+                               bool &OwnedDecl, bool &IsDependent) {
+  // If this is not a definition, it must have a name.
+  assert((Name != 0 || TUK == TUK_Definition) &&
+         "Nameless record must be a definition!");
+
+  OwnedDecl = false;
+  TagDecl::TagKind Kind = TagDecl::getTagKindForTypeSpec(TagSpec);
+
+  // FIXME: Check explicit specializations more carefully.
+  bool isExplicitSpecialization = false;
+  if (TUK != TUK_Reference) {
+    if (TemplateParameterList *TemplateParams
+          = MatchTemplateParametersToScopeSpecifier(KWLoc, SS,
+                        (TemplateParameterList**)TemplateParameterLists.get(),
+                                              TemplateParameterLists.size(),
+                                                    isExplicitSpecialization)) {
+      if (TemplateParams->size() > 0) {
+        // This is a declaration or definition of a class template (which may
+        // be a member of another template).
+        OwnedDecl = false;
+        DeclResult Result = CheckClassTemplate(S, TagSpec, TUK, KWLoc,
+                                               SS, Name, NameLoc, Attr,
+                                               TemplateParams,
+                                               AS);
+        TemplateParameterLists.release();
+        return Result.get();
+      } else {
+        // The "template<>" header is extraneous.
+        Diag(TemplateParams->getTemplateLoc(), diag::err_template_tag_noparams)
+          << ElaboratedType::getNameForTagKind(Kind) << Name;
+        isExplicitSpecialization = true;
+      }
+    }
+             
+    TemplateParameterLists.release();
+  }
+
+  DeclContext *SearchDC = CurContext;
+  DeclContext *DC = CurContext;
+  bool isStdBadAlloc = false;
+  bool Invalid = false;
+
+  RedeclarationKind Redecl = (TUK != TUK_Reference ? ForRedeclaration
+                                                   : NotForRedeclaration);
+
+  LookupResult Previous(*this, Name, NameLoc, LookupTagName, Redecl);
+
+  if (Name && SS.isNotEmpty()) {
+    // We have a nested-name tag ('struct foo::bar').
+
+    // Check for invalid 'foo::'.
+    if (SS.isInvalid()) {
+      Name = 0;
+      goto CreateNewDecl;
+    }
+
+    // If this is a friend or a reference to a class in a dependent
+    // context, don't try to make a decl for it.
+    if (TUK == TUK_Friend || TUK == TUK_Reference) {
+      DC = computeDeclContext(SS, false);
+      if (!DC) {
+        IsDependent = true;
+        return DeclPtrTy();
+      }
+    }
+
+    if (RequireCompleteDeclContext(SS))
+      return DeclPtrTy::make((Decl *)0);
+
+    DC = computeDeclContext(SS, true);
+    SearchDC = DC;
+    // Look-up name inside 'foo::'.
+    LookupQualifiedName(Previous, DC);
+
+    if (Previous.isAmbiguous())
+      return DeclPtrTy();
+
+    if (Previous.empty()) {
+      // Name lookup did not find anything. However, if the
+      // nested-name-specifier refers to the current instantiation,
+      // and that current instantiation has any dependent base
+      // classes, we might find something at instantiation time: treat
+      // this as a dependent elaborated-type-specifier.
+      if (Previous.wasNotFoundInCurrentInstantiation()) {
+        IsDependent = true;
+        return DeclPtrTy();
+      }
+
+      // A tag 'foo::bar' must already exist.
+      Diag(NameLoc, diag::err_not_tag_in_scope) << Name << SS.getRange();
+      Name = 0;
+      Invalid = true;
+      goto CreateNewDecl;
+    }
+  } else if (Name) {
+    // If this is a named struct, check to see if there was a previous forward
+    // declaration or definition.
+    // FIXME: We're looking into outer scopes here, even when we
+    // shouldn't be. Doing so can result in ambiguities that we
+    // shouldn't be diagnosing.
+    LookupName(Previous, S);
+
+    // Note:  there used to be some attempt at recovery here.
+    if (Previous.isAmbiguous())
+      return DeclPtrTy();
+
+    if (!getLangOptions().CPlusPlus && TUK != TUK_Reference) {
+      // FIXME: This makes sure that we ignore the contexts associated
+      // with C structs, unions, and enums when looking for a matching
+      // tag declaration or definition. See the similar lookup tweak
+      // in Sema::LookupName; is there a better way to deal with this?
+      while (isa<RecordDecl>(SearchDC) || isa<EnumDecl>(SearchDC))
+        SearchDC = SearchDC->getParent();
+    }
+  }
+
+  if (Previous.isSingleResult() &&
+      Previous.getFoundDecl()->isTemplateParameter()) {
+    // Maybe we will complain about the shadowed template parameter.
+    DiagnoseTemplateParameterShadow(NameLoc, Previous.getFoundDecl());
+    // Just pretend that we didn't see the previous declaration.
+    Previous.clear();
+  }
+
+  if (getLangOptions().CPlusPlus && Name && DC && StdNamespace &&
+      DC->Equals(StdNamespace) && Name->isStr("bad_alloc")) {
+    // This is a declaration of or a reference to "std::bad_alloc".
+    isStdBadAlloc = true;
+    
+    if (Previous.empty() && StdBadAlloc) {
+      // std::bad_alloc has been implicitly declared (but made invisible to
+      // name lookup). Fill in this implicit declaration as the previous 
+      // declaration, so that the declarations get chained appropriately.
+      Previous.addDecl(StdBadAlloc);
+    }
+  }
+
+  if (!Previous.empty()) {
+    assert(Previous.isSingleResult());
+    NamedDecl *PrevDecl = Previous.getFoundDecl();
+    if (TagDecl *PrevTagDecl = dyn_cast<TagDecl>(PrevDecl)) {
+      // 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 (TUK == TUK_Reference || TUK == TUK_Friend ||
+          isDeclInScope(PrevDecl, SearchDC, S)) {
+        // Make sure that this wasn't declared as an enum and now used as a
+        // struct or something similar.
+        if (!isAcceptableTagRedeclaration(PrevTagDecl, Kind, KWLoc, *Name)) {
+          bool SafeToContinue
+            = (PrevTagDecl->getTagKind() != TagDecl::TK_enum &&
+               Kind != TagDecl::TK_enum);
+          if (SafeToContinue)
+            Diag(KWLoc, diag::err_use_with_wrong_tag)
+              << Name
+              << CodeModificationHint::CreateReplacement(SourceRange(KWLoc),
+                                                  PrevTagDecl->getKindName());
+          else
+            Diag(KWLoc, diag::err_use_with_wrong_tag) << Name;
+          Diag(PrevTagDecl->getLocation(), diag::note_previous_use);
+
+          if (SafeToContinue)
+            Kind = PrevTagDecl->getTagKind();
+          else {
+            // Recover by making this an anonymous redefinition.
+            Name = 0;
+            Previous.clear();
+            Invalid = true;
+          }
+        }
+
+        if (!Invalid) {
+          // If this is a use, just return the declaration we found.
+
+          // FIXME: In the future, return a variant or some other clue
+          // for the consumer of this Decl to know it doesn't own it.
+          // For our current ASTs this shouldn't be a problem, but will
+          // need to be changed with DeclGroups.
+          if (TUK == TUK_Reference || TUK == TUK_Friend)
+            return DeclPtrTy::make(PrevTagDecl);
+
+          // Diagnose attempts to redefine a tag.
+          if (TUK == TUK_Definition) {
+            if (TagDecl *Def = PrevTagDecl->getDefinition(Context)) {
+              // If we're defining a specialization and the previous definition
+              // is from an implicit instantiation, don't emit an error
+              // here; we'll catch this in the general case below.
+              if (!isExplicitSpecialization ||
+                  !isa<CXXRecordDecl>(Def) ||
+                  cast<CXXRecordDecl>(Def)->getTemplateSpecializationKind() 
+                                               == TSK_ExplicitSpecialization) {
+                Diag(NameLoc, diag::err_redefinition) << Name;
+                Diag(Def->getLocation(), diag::note_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;
+                Previous.clear();
+                Invalid = true;
+              }
+            } else {
+              // If the type is currently being defined, complain
+              // about a nested redefinition.
+              TagType *Tag = cast<TagType>(Context.getTagDeclType(PrevTagDecl));
+              if (Tag->isBeingDefined()) {
+                Diag(NameLoc, diag::err_nested_redefinition) << Name;
+                Diag(PrevTagDecl->getLocation(),
+                     diag::note_previous_definition);
+                Name = 0;
+                Previous.clear();
+                Invalid = true;
+              }
+            }
+
+            // Okay, this is definition of a previously declared or referenced
+            // tag PrevDecl. We're going to create a new Decl for it.
+          }
+        }
+        // If we get here we have (another) forward declaration or we
+        // have a definition.  Just create a new decl.
+
+      } else {
+        // If we get here, this is a definition of a new tag type in a nested
+        // scope, e.g. "struct foo; void bar() { struct foo; }", just create a
+        // new decl/type.  We set PrevDecl to NULL so that the entities
+        // have distinct types.
+        Previous.clear();
+      }
+      // If we get here, we're going to create a new Decl. If PrevDecl
+      // is non-NULL, it's a definition of the tag declared by
+      // PrevDecl. If it's NULL, we have a new definition.
+    } else {
+      // PrevDecl is a namespace, template, or anything else
+      // that lives in the IDNS_Tag identifier namespace.
+      if (isDeclInScope(PrevDecl, SearchDC, S)) {
+        // The tag name clashes with a namespace name, issue an error and
+        // recover by making this tag be anonymous.
+        Diag(NameLoc, diag::err_redefinition_different_kind) << Name;
+        Diag(PrevDecl->getLocation(), diag::note_previous_definition);
+        Name = 0;
+        Previous.clear();
+        Invalid = true;
+      } else {
+        // The existing declaration isn't relevant to us; we're in a
+        // new scope, so clear out the previous declaration.
+        Previous.clear();
+      }
+    }
+  } else if (TUK == TUK_Reference && SS.isEmpty() && Name) {
+    // C++ [basic.scope.pdecl]p5:
+    //   -- for an elaborated-type-specifier of the form
+    //
+    //          class-key identifier
+    //
+    //      if the elaborated-type-specifier is used in the
+    //      decl-specifier-seq or parameter-declaration-clause of a
+    //      function defined in namespace scope, the identifier is
+    //      declared as a class-name in the namespace that contains
+    //      the declaration; otherwise, except as a friend
+    //      declaration, the identifier is declared in the smallest
+    //      non-class, non-function-prototype scope that contains the
+    //      declaration.
+    //
+    // C99 6.7.2.3p8 has a similar (but not identical!) provision for
+    // C structs and unions.
+    //
+    // It is an error in C++ to declare (rather than define) an enum
+    // type, including via an elaborated type specifier.  We'll
+    // diagnose that later; for now, declare the enum in the same
+    // scope as we would have picked for any other tag type.
+    //
+    // GNU C also supports this behavior as part of its incomplete
+    // enum types extension, while GNU C++ does not.
+    //
+    // Find the context where we'll be declaring the tag.
+    // FIXME: We would like to maintain the current DeclContext as the
+    // lexical context,
+    while (SearchDC->isRecord())
+      SearchDC = SearchDC->getParent();
+
+    // Find the scope where we'll be declaring the tag.
+    while (S->isClassScope() ||
+           (getLangOptions().CPlusPlus && S->isFunctionPrototypeScope()) ||
+           ((S->getFlags() & Scope::DeclScope) == 0) ||
+           (S->getEntity() &&
+            ((DeclContext *)S->getEntity())->isTransparentContext()))
+      S = S->getParent();
+
+  } else if (TUK == TUK_Friend && SS.isEmpty() && Name) {
+    // C++ [namespace.memdef]p3:
+    //   If a friend declaration in a non-local class first declares a
+    //   class or function, the friend class or function is a member of
+    //   the innermost enclosing namespace.
+    while (!SearchDC->isFileContext())
+      SearchDC = SearchDC->getParent();
+
+    // The entity of a decl scope is a DeclContext; see PushDeclContext.
+    while (S->getEntity() != SearchDC)
+      S = S->getParent();
+  }
+
+CreateNewDecl:
+
+  TagDecl *PrevDecl = 0;
+  if (Previous.isSingleResult())
+    PrevDecl = cast<TagDecl>(Previous.getFoundDecl());
+
+  // 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, create a new declaration. If there is a previous
+  // declaration of the same entity, the two will be linked via
+  // PrevDecl.
+  TagDecl *New;
+
+  if (Kind == TagDecl::TK_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 = EnumDecl::Create(Context, SearchDC, Loc, Name, KWLoc,
+                           cast_or_null<EnumDecl>(PrevDecl));
+    // If this is an undefined enum, warn.
+    if (TUK != TUK_Definition && !Invalid)  {
+      unsigned DK = getLangOptions().CPlusPlus? diag::err_forward_ref_enum
+                                              : diag::ext_forward_ref_enum;
+      Diag(Loc, DK);
+    }
+  } else {
+    // struct/union/class
+
+    // FIXME: Tag decls should be chained to any simultaneous vardecls, e.g.:
+    // struct X { int A; } D;    D should chain to X.
+    if (getLangOptions().CPlusPlus) {
+      // FIXME: Look for a way to use RecordDecl for simple structs.
+      New = CXXRecordDecl::Create(Context, Kind, SearchDC, Loc, Name, KWLoc,
+                                  cast_or_null<CXXRecordDecl>(PrevDecl));
+      
+      if (isStdBadAlloc && (!StdBadAlloc || StdBadAlloc->isImplicit()))
+        StdBadAlloc = cast<CXXRecordDecl>(New);
+    } else
+      New = RecordDecl::Create(Context, Kind, SearchDC, Loc, Name, KWLoc,
+                               cast_or_null<RecordDecl>(PrevDecl));
+  }
+
+  if (Kind != TagDecl::TK_enum) {
+    // Handle #pragma pack: if the #pragma pack stack has non-default
+    // alignment, make up a packed attribute for this decl. These
+    // attributes are checked when the ASTContext lays out the
+    // structure.
+    //
+    // It is important for implementing the correct semantics that this
+    // happen here (in act on tag decl). The #pragma pack stack is
+    // maintained as a result of parser callbacks which can occur at
+    // many points during the parsing of a struct declaration (because
+    // the #pragma tokens are effectively skipped over during the
+    // parsing of the struct).
+    if (unsigned Alignment = getPragmaPackAlignment())
+      New->addAttr(::new (Context) PragmaPackAttr(Alignment * 8));
+  }
+
+  if (getLangOptions().CPlusPlus && SS.isEmpty() && Name && !Invalid) {
+    // C++ [dcl.typedef]p3:
+    //   [...] Similarly, in a given scope, a class or enumeration
+    //   shall not be declared with the same name as a typedef-name
+    //   that is declared in that scope and refers to a type other
+    //   than the class or enumeration itself.
+    LookupResult Lookup(*this, Name, NameLoc, LookupOrdinaryName,
+                        ForRedeclaration);
+    LookupName(Lookup, S);
+    TypedefDecl *PrevTypedef = Lookup.getAsSingle<TypedefDecl>();
+    NamedDecl *PrevTypedefNamed = PrevTypedef;
+    if (PrevTypedef && isDeclInScope(PrevTypedefNamed, SearchDC, S) &&
+        Context.getCanonicalType(Context.getTypeDeclType(PrevTypedef)) !=
+          Context.getCanonicalType(Context.getTypeDeclType(New))) {
+      Diag(Loc, diag::err_tag_definition_of_typedef)
+        << Context.getTypeDeclType(New)
+        << PrevTypedef->getUnderlyingType();
+      Diag(PrevTypedef->getLocation(), diag::note_previous_definition);
+      Invalid = true;
+    }
+  }
+
+  // If this is a specialization of a member class (of a class template),
+  // check the specialization.
+  if (isExplicitSpecialization && CheckMemberSpecialization(New, Previous))
+    Invalid = true;
+      
+  if (Invalid)
+    New->setInvalidDecl();
+
+  if (Attr)
+    ProcessDeclAttributeList(S, New, Attr);
+
+  // If we're declaring or defining a tag in function prototype scope
+  // in C, note that this type can only be used within the function.
+  if (Name && S->isFunctionPrototypeScope() && !getLangOptions().CPlusPlus)
+    Diag(Loc, diag::warn_decl_in_param_list) << Context.getTagDeclType(New);
+
+  // Set the lexical context. If the tag has a C++ scope specifier, the
+  // lexical context will be different from the semantic context.
+  New->setLexicalDeclContext(CurContext);
+
+  // Mark this as a friend decl if applicable.
+  if (TUK == TUK_Friend)
+    New->setObjectOfFriendDecl(/* PreviouslyDeclared = */ !Previous.empty());
+
+  // Set the access specifier.
+  if (!Invalid && TUK != TUK_Friend)
+    SetMemberAccessSpecifier(New, PrevDecl, AS);
+
+  if (TUK == TUK_Definition)
+    New->startDefinition();
+
+  // If this has an identifier, add it to the scope stack.
+  if (TUK == TUK_Friend) {
+    // We might be replacing an existing declaration in the lookup tables;
+    // if so, borrow its access specifier.
+    if (PrevDecl)
+      New->setAccess(PrevDecl->getAccess());
+
+    // Friend tag decls are visible in fairly strange ways.
+    if (!CurContext->isDependentContext()) {
+      DeclContext *DC = New->getDeclContext()->getLookupContext();
+      DC->makeDeclVisibleInContext(New, /* Recoverable = */ false);
+      if (Scope *EnclosingScope = getScopeForDeclContext(S, DC))
+        PushOnScopeChains(New, EnclosingScope, /* AddToContext = */ false);
+    }
+  } else if (Name) {
+    S = getNonFieldDeclScope(S);
+    PushOnScopeChains(New, S);
+  } else {
+    CurContext->addDecl(New);
+  }
+
+  // If this is the C FILE type, notify the AST context.
+  if (IdentifierInfo *II = New->getIdentifier())
+    if (!New->isInvalidDecl() &&
+        New->getDeclContext()->getLookupContext()->isTranslationUnit() &&
+        II->isStr("FILE"))
+      Context.setFILEDecl(New);
+
+  OwnedDecl = true;
+  return DeclPtrTy::make(New);
+}
+
+void Sema::ActOnTagStartDefinition(Scope *S, DeclPtrTy TagD) {
+  AdjustDeclIfTemplate(TagD);
+  TagDecl *Tag = cast<TagDecl>(TagD.getAs<Decl>());
+
+  // Enter the tag context.
+  PushDeclContext(S, Tag);
+}
+
+void Sema::ActOnStartCXXMemberDeclarations(Scope *S, DeclPtrTy TagD,
+                                           SourceLocation LBraceLoc) {
+  AdjustDeclIfTemplate(TagD);
+  CXXRecordDecl *Record = cast<CXXRecordDecl>(TagD.getAs<Decl>());
+
+  FieldCollector->StartClass();
+
+  if (!Record->getIdentifier())
+    return;
+
+  // C++ [class]p2:
+  //   [...] The class-name is also inserted into the scope of the
+  //   class itself; this is known as the injected-class-name. For
+  //   purposes of access checking, the injected-class-name is treated
+  //   as if it were a public member name.
+  CXXRecordDecl *InjectedClassName
+    = CXXRecordDecl::Create(Context, Record->getTagKind(),
+                            CurContext, Record->getLocation(),
+                            Record->getIdentifier(),
+                            Record->getTagKeywordLoc(),
+                            Record);
+  InjectedClassName->setImplicit();
+  InjectedClassName->setAccess(AS_public);
+  if (ClassTemplateDecl *Template = Record->getDescribedClassTemplate())
+      InjectedClassName->setDescribedClassTemplate(Template);
+  PushOnScopeChains(InjectedClassName, S);
+  assert(InjectedClassName->isInjectedClassName() &&
+         "Broken injected-class-name");
+}
+
+// Traverses the class and any nested classes, making a note of any 
+// dynamic classes that have no key function so that we can mark all of
+// their virtual member functions as "used" at the end of the translation
+// unit. This ensures that all functions needed by the vtable will get
+// instantiated/synthesized.
+static void 
+RecordDynamicClassesWithNoKeyFunction(Sema &S, CXXRecordDecl *Record,
+                                      SourceLocation Loc) {
+  // We don't look at dependent or undefined classes.
+  if (Record->isDependentContext() || !Record->isDefinition())
+    return;
+  
+  if (Record->isDynamicClass()) {
+    const CXXMethodDecl *KeyFunction = S.Context.getKeyFunction(Record);
+  
+    if (!KeyFunction)
+      S.ClassesWithUnmarkedVirtualMembers.push_back(std::make_pair(Record,
+                                                                   Loc));
+
+    if ((!KeyFunction || (KeyFunction->getBody() && KeyFunction->isInlined()))
+        && Record->getLinkage() == ExternalLinkage)
+      S.Diag(Record->getLocation(), diag::warn_weak_vtable) << Record;
+  }
+  for (DeclContext::decl_iterator D = Record->decls_begin(), 
+                               DEnd = Record->decls_end();
+       D != DEnd; ++D) {
+    if (CXXRecordDecl *Nested = dyn_cast<CXXRecordDecl>(*D))
+      RecordDynamicClassesWithNoKeyFunction(S, Nested, Loc);
+  }
+}
+
+void Sema::ActOnTagFinishDefinition(Scope *S, DeclPtrTy TagD,
+                                    SourceLocation RBraceLoc) {
+  AdjustDeclIfTemplate(TagD);
+  TagDecl *Tag = cast<TagDecl>(TagD.getAs<Decl>());
+  Tag->setRBraceLoc(RBraceLoc);
+
+  if (isa<CXXRecordDecl>(Tag))
+    FieldCollector->FinishClass();
+
+  // Exit this scope of this tag's definition.
+  PopDeclContext();
+
+  if (isa<CXXRecordDecl>(Tag) && !Tag->getDeclContext()->isRecord())
+    RecordDynamicClassesWithNoKeyFunction(*this, cast<CXXRecordDecl>(Tag),
+                                          RBraceLoc);
+                                          
+  // Notify the consumer that we've defined a tag.
+  Consumer.HandleTagDeclDefinition(Tag);
+}
+
+// Note that FieldName may be null for anonymous bitfields.
+bool Sema::VerifyBitField(SourceLocation FieldLoc, IdentifierInfo *FieldName,
+                          QualType FieldTy, const Expr *BitWidth,
+                          bool *ZeroWidth) {
+  // Default to true; that shouldn't confuse checks for emptiness
+  if (ZeroWidth)
+    *ZeroWidth = true;
+
+  // C99 6.7.2.1p4 - verify the field type.
+  // C++ 9.6p3: A bit-field shall have integral or enumeration type.
+  if (!FieldTy->isDependentType() && !FieldTy->isIntegralType()) {
+    // Handle incomplete types with specific error.
+    if (RequireCompleteType(FieldLoc, FieldTy, diag::err_field_incomplete))
+      return true;
+    if (FieldName)
+      return Diag(FieldLoc, diag::err_not_integral_type_bitfield)
+        << FieldName << FieldTy << BitWidth->getSourceRange();
+    return Diag(FieldLoc, diag::err_not_integral_type_anon_bitfield)
+      << FieldTy << BitWidth->getSourceRange();
+  }
+
+  // If the bit-width is type- or value-dependent, don't try to check
+  // it now.
+  if (BitWidth->isValueDependent() || BitWidth->isTypeDependent())
+    return false;
+
+  llvm::APSInt Value;
+  if (VerifyIntegerConstantExpression(BitWidth, &Value))
+    return true;
+
+  if (Value != 0 && ZeroWidth)
+    *ZeroWidth = false;
+
+  // Zero-width bitfield is ok for anonymous field.
+  if (Value == 0 && FieldName)
+    return Diag(FieldLoc, diag::err_bitfield_has_zero_width) << FieldName;
+
+  if (Value.isSigned() && Value.isNegative()) {
+    if (FieldName)
+      return Diag(FieldLoc, diag::err_bitfield_has_negative_width)
+               << FieldName << Value.toString(10);
+    return Diag(FieldLoc, diag::err_anon_bitfield_has_negative_width)
+      << Value.toString(10);
+  }
+
+  if (!FieldTy->isDependentType()) {
+    uint64_t TypeSize = Context.getTypeSize(FieldTy);
+    if (Value.getZExtValue() > TypeSize) {
+      if (FieldName)
+        return Diag(FieldLoc, diag::err_bitfield_width_exceeds_type_size)
+          << FieldName << (unsigned)TypeSize;
+      return Diag(FieldLoc, diag::err_anon_bitfield_width_exceeds_type_size)
+        << (unsigned)TypeSize;
+    }
+  }
+
+  return false;
+}
+
+/// ActOnField - Each field of a struct/union/class is passed into this in order
+/// to create a FieldDecl object for it.
+Sema::DeclPtrTy Sema::ActOnField(Scope *S, DeclPtrTy TagD,
+                                 SourceLocation DeclStart,
+                                 Declarator &D, ExprTy *BitfieldWidth) {
+  FieldDecl *Res = HandleField(S, cast_or_null<RecordDecl>(TagD.getAs<Decl>()),
+                               DeclStart, D, static_cast<Expr*>(BitfieldWidth),
+                               AS_public);
+  return DeclPtrTy::make(Res);
+}
+
+/// HandleField - Analyze a field of a C struct or a C++ data member.
+///
+FieldDecl *Sema::HandleField(Scope *S, RecordDecl *Record,
+                             SourceLocation DeclStart,
+                             Declarator &D, Expr *BitWidth,
+                             AccessSpecifier AS) {
+  IdentifierInfo *II = D.getIdentifier();
+  SourceLocation Loc = DeclStart;
+  if (II) Loc = D.getIdentifierLoc();
+
+  TypeSourceInfo *TInfo = 0;
+  QualType T = GetTypeForDeclarator(D, S, &TInfo);
+  if (getLangOptions().CPlusPlus)
+    CheckExtraCXXDefaultArguments(D);
+
+  DiagnoseFunctionSpecifiers(D);
+
+  if (D.getDeclSpec().isThreadSpecified())
+    Diag(D.getDeclSpec().getThreadSpecLoc(), diag::err_invalid_thread);
+
+  NamedDecl *PrevDecl = LookupSingleName(S, II, LookupMemberName,
+                                         ForRedeclaration);
+
+  if (PrevDecl && PrevDecl->isTemplateParameter()) {
+    // Maybe we will complain about the shadowed template parameter.
+    DiagnoseTemplateParameterShadow(D.getIdentifierLoc(), PrevDecl);
+    // Just pretend that we didn't see the previous declaration.
+    PrevDecl = 0;
+  }
+
+  if (PrevDecl && !isDeclInScope(PrevDecl, Record, S))
+    PrevDecl = 0;
+
+  bool Mutable
+    = (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_mutable);
+  SourceLocation TSSL = D.getSourceRange().getBegin();
+  FieldDecl *NewFD
+    = CheckFieldDecl(II, T, TInfo, Record, Loc, Mutable, BitWidth, TSSL,
+                     AS, PrevDecl, &D);
+  if (NewFD->isInvalidDecl() && PrevDecl) {
+    // Don't introduce NewFD into scope; there's already something
+    // with the same name in the same scope.
+  } else if (II) {
+    PushOnScopeChains(NewFD, S);
+  } else
+    Record->addDecl(NewFD);
+
+  return NewFD;
+}
+
+/// \brief Build a new FieldDecl and check its well-formedness.
+///
+/// This routine builds a new FieldDecl given the fields name, type,
+/// record, etc. \p PrevDecl should refer to any previous declaration
+/// with the same name and in the same scope as the field to be
+/// created.
+///
+/// \returns a new FieldDecl.
+///
+/// \todo The Declarator argument is a hack. It will be removed once
+FieldDecl *Sema::CheckFieldDecl(DeclarationName Name, QualType T,
+                                TypeSourceInfo *TInfo,
+                                RecordDecl *Record, SourceLocation Loc,
+                                bool Mutable, Expr *BitWidth,
+                                SourceLocation TSSL,
+                                AccessSpecifier AS, NamedDecl *PrevDecl,
+                                Declarator *D) {
+  IdentifierInfo *II = Name.getAsIdentifierInfo();
+  bool InvalidDecl = false;
+  if (D) InvalidDecl = D->isInvalidType();
+
+  // If we receive a broken type, recover by assuming 'int' and
+  // marking this declaration as invalid.
+  if (T.isNull()) {
+    InvalidDecl = true;
+    T = Context.IntTy;
+  }
+
+  QualType EltTy = Context.getBaseElementType(T);
+  if (!EltTy->isDependentType() &&
+      RequireCompleteType(Loc, EltTy, diag::err_field_incomplete))
+    InvalidDecl = true;
+
+  // C99 6.7.2.1p8: A member of a structure or union may have any type other
+  // than a variably modified type.
+  if (!InvalidDecl && T->isVariablyModifiedType()) {
+    bool SizeIsNegative;
+    QualType FixedTy = TryToFixInvalidVariablyModifiedType(T, Context,
+                                                           SizeIsNegative);
+    if (!FixedTy.isNull()) {
+      Diag(Loc, diag::warn_illegal_constant_array_size);
+      T = FixedTy;
+    } else {
+      if (SizeIsNegative)
+        Diag(Loc, diag::err_typecheck_negative_array_size);
+      else
+        Diag(Loc, diag::err_typecheck_field_variable_size);
+      InvalidDecl = true;
+    }
+  }
+
+  // Fields can not have abstract class types
+  if (!InvalidDecl && RequireNonAbstractType(Loc, T,
+                                             diag::err_abstract_type_in_decl,
+                                             AbstractFieldType))
+    InvalidDecl = true;
+
+  bool ZeroWidth = false;
+  // If this is declared as a bit-field, check the bit-field.
+  if (!InvalidDecl && BitWidth &&
+      VerifyBitField(Loc, II, T, BitWidth, &ZeroWidth)) {
+    InvalidDecl = true;
+    DeleteExpr(BitWidth);
+    BitWidth = 0;
+    ZeroWidth = false;
+  }
+
+  FieldDecl *NewFD = FieldDecl::Create(Context, Record, Loc, II, T, TInfo,
+                                       BitWidth, Mutable);
+  if (InvalidDecl)
+    NewFD->setInvalidDecl();
+
+  if (PrevDecl && !isa<TagDecl>(PrevDecl)) {
+    Diag(Loc, diag::err_duplicate_member) << II;
+    Diag(PrevDecl->getLocation(), diag::note_previous_declaration);
+    NewFD->setInvalidDecl();
+  }
+
+  if (!InvalidDecl && getLangOptions().CPlusPlus) {
+    CXXRecordDecl* CXXRecord = cast<CXXRecordDecl>(Record);
+
+    if (!T->isPODType())
+      CXXRecord->setPOD(false);
+    if (!ZeroWidth)
+      CXXRecord->setEmpty(false);
+
+    if (const RecordType *RT = EltTy->getAs<RecordType>()) {
+      CXXRecordDecl* RDecl = cast<CXXRecordDecl>(RT->getDecl());
+
+      if (!RDecl->hasTrivialConstructor())
+        CXXRecord->setHasTrivialConstructor(false);
+      if (!RDecl->hasTrivialCopyConstructor())
+        CXXRecord->setHasTrivialCopyConstructor(false);
+      if (!RDecl->hasTrivialCopyAssignment())
+        CXXRecord->setHasTrivialCopyAssignment(false);
+      if (!RDecl->hasTrivialDestructor())
+        CXXRecord->setHasTrivialDestructor(false);
+
+      // C++ 9.5p1: An object of a class with a non-trivial
+      // constructor, a non-trivial copy constructor, a non-trivial
+      // destructor, or a non-trivial copy assignment operator
+      // cannot be a member of a union, nor can an array of such
+      // objects.
+      // TODO: C++0x alters this restriction significantly.
+      if (Record->isUnion()) {
+        // We check for copy constructors before constructors
+        // because otherwise we'll never get complaints about
+        // copy constructors.
+
+        const CXXSpecialMember invalid = (CXXSpecialMember) -1;
+
+        CXXSpecialMember member;
+        if (!RDecl->hasTrivialCopyConstructor())
+          member = CXXCopyConstructor;
+        else if (!RDecl->hasTrivialConstructor())
+          member = CXXDefaultConstructor;
+        else if (!RDecl->hasTrivialCopyAssignment())
+          member = CXXCopyAssignment;
+        else if (!RDecl->hasTrivialDestructor())
+          member = CXXDestructor;
+        else
+          member = invalid;
+
+        if (member != invalid) {
+          Diag(Loc, diag::err_illegal_union_member) << Name << member;
+          DiagnoseNontrivial(RT, member);
+          NewFD->setInvalidDecl();
+        }
+      }
+    }
+  }
+
+  // FIXME: We need to pass in the attributes given an AST
+  // representation, not a parser representation.
+  if (D)
+    // FIXME: What to pass instead of TUScope?
+    ProcessDeclAttributes(TUScope, NewFD, *D);
+
+  if (T.isObjCGCWeak())
+    Diag(Loc, diag::warn_attribute_weak_on_field);
+
+  NewFD->setAccess(AS);
+
+  // C++ [dcl.init.aggr]p1:
+  //   An aggregate is an array or a class (clause 9) with [...] no
+  //   private or protected non-static data members (clause 11).
+  // A POD must be an aggregate.
+  if (getLangOptions().CPlusPlus &&
+      (AS == AS_private || AS == AS_protected)) {
+    CXXRecordDecl *CXXRecord = cast<CXXRecordDecl>(Record);
+    CXXRecord->setAggregate(false);
+    CXXRecord->setPOD(false);
+  }
+
+  return NewFD;
+}
+
+/// DiagnoseNontrivial - Given that a class has a non-trivial
+/// special member, figure out why.
+void Sema::DiagnoseNontrivial(const RecordType* T, CXXSpecialMember member) {
+  QualType QT(T, 0U);
+  CXXRecordDecl* RD = cast<CXXRecordDecl>(T->getDecl());
+
+  // Check whether the member was user-declared.
+  switch (member) {
+  case CXXDefaultConstructor:
+    if (RD->hasUserDeclaredConstructor()) {
+      typedef CXXRecordDecl::ctor_iterator ctor_iter;
+      for (ctor_iter ci = RD->ctor_begin(), ce = RD->ctor_end(); ci != ce;++ci){
+        const FunctionDecl *body = 0;
+        ci->getBody(body);
+        if (!body ||
+            !cast<CXXConstructorDecl>(body)->isImplicitlyDefined(Context)) {
+          SourceLocation CtorLoc = ci->getLocation();
+          Diag(CtorLoc, diag::note_nontrivial_user_defined) << QT << member;
+          return;
+        }
+      }
+
+      assert(0 && "found no user-declared constructors");
+      return;
+    }
+    break;
+
+  case CXXCopyConstructor:
+    if (RD->hasUserDeclaredCopyConstructor()) {
+      SourceLocation CtorLoc =
+        RD->getCopyConstructor(Context, 0)->getLocation();
+      Diag(CtorLoc, diag::note_nontrivial_user_defined) << QT << member;
+      return;
+    }
+    break;
+
+  case CXXCopyAssignment:
+    if (RD->hasUserDeclaredCopyAssignment()) {
+      // FIXME: this should use the location of the copy
+      // assignment, not the type.
+      SourceLocation TyLoc = RD->getSourceRange().getBegin();
+      Diag(TyLoc, diag::note_nontrivial_user_defined) << QT << member;
+      return;
+    }
+    break;
+
+  case CXXDestructor:
+    if (RD->hasUserDeclaredDestructor()) {
+      SourceLocation DtorLoc = RD->getDestructor(Context)->getLocation();
+      Diag(DtorLoc, diag::note_nontrivial_user_defined) << QT << member;
+      return;
+    }
+    break;
+  }
+
+  typedef CXXRecordDecl::base_class_iterator base_iter;
+
+  // Virtual bases and members inhibit trivial copying/construction,
+  // but not trivial destruction.
+  if (member != CXXDestructor) {
+    // Check for virtual bases.  vbases includes indirect virtual bases,
+    // so we just iterate through the direct bases.
+    for (base_iter bi = RD->bases_begin(), be = RD->bases_end(); bi != be; ++bi)
+      if (bi->isVirtual()) {
+        SourceLocation BaseLoc = bi->getSourceRange().getBegin();
+        Diag(BaseLoc, diag::note_nontrivial_has_virtual) << QT << 1;
+        return;
+      }
+
+    // Check for virtual methods.
+    typedef CXXRecordDecl::method_iterator meth_iter;
+    for (meth_iter mi = RD->method_begin(), me = RD->method_end(); mi != me;
+         ++mi) {
+      if (mi->isVirtual()) {
+        SourceLocation MLoc = mi->getSourceRange().getBegin();
+        Diag(MLoc, diag::note_nontrivial_has_virtual) << QT << 0;
+        return;
+      }
+    }
+  }
+
+  bool (CXXRecordDecl::*hasTrivial)() const;
+  switch (member) {
+  case CXXDefaultConstructor:
+    hasTrivial = &CXXRecordDecl::hasTrivialConstructor; break;
+  case CXXCopyConstructor:
+    hasTrivial = &CXXRecordDecl::hasTrivialCopyConstructor; break;
+  case CXXCopyAssignment:
+    hasTrivial = &CXXRecordDecl::hasTrivialCopyAssignment; break;
+  case CXXDestructor:
+    hasTrivial = &CXXRecordDecl::hasTrivialDestructor; break;
+  default:
+    assert(0 && "unexpected special member"); return;
+  }
+
+  // Check for nontrivial bases (and recurse).
+  for (base_iter bi = RD->bases_begin(), be = RD->bases_end(); bi != be; ++bi) {
+    const RecordType *BaseRT = bi->getType()->getAs<RecordType>();
+    assert(BaseRT && "Don't know how to handle dependent bases");
+    CXXRecordDecl *BaseRecTy = cast<CXXRecordDecl>(BaseRT->getDecl());
+    if (!(BaseRecTy->*hasTrivial)()) {
+      SourceLocation BaseLoc = bi->getSourceRange().getBegin();
+      Diag(BaseLoc, diag::note_nontrivial_has_nontrivial) << QT << 1 << member;
+      DiagnoseNontrivial(BaseRT, member);
+      return;
+    }
+  }
+
+  // Check for nontrivial members (and recurse).
+  typedef RecordDecl::field_iterator field_iter;
+  for (field_iter fi = RD->field_begin(), fe = RD->field_end(); fi != fe;
+       ++fi) {
+    QualType EltTy = Context.getBaseElementType((*fi)->getType());
+    if (const RecordType *EltRT = EltTy->getAs<RecordType>()) {
+      CXXRecordDecl* EltRD = cast<CXXRecordDecl>(EltRT->getDecl());
+
+      if (!(EltRD->*hasTrivial)()) {
+        SourceLocation FLoc = (*fi)->getLocation();
+        Diag(FLoc, diag::note_nontrivial_has_nontrivial) << QT << 0 << member;
+        DiagnoseNontrivial(EltRT, member);
+        return;
+      }
+    }
+  }
+
+  assert(0 && "found no explanation for non-trivial member");
+}
+
+/// TranslateIvarVisibility - Translate visibility from a token ID to an
+///  AST enum value.
+static ObjCIvarDecl::AccessControl
+TranslateIvarVisibility(tok::ObjCKeywordKind ivarVisibility) {
+  switch (ivarVisibility) {
+  default: assert(0 && "Unknown visitibility kind");
+  case tok::objc_private: return ObjCIvarDecl::Private;
+  case tok::objc_public: return ObjCIvarDecl::Public;
+  case tok::objc_protected: return ObjCIvarDecl::Protected;
+  case tok::objc_package: return ObjCIvarDecl::Package;
+  }
+}
+
+/// ActOnIvar - Each ivar field of an objective-c class is passed into this
+/// in order to create an IvarDecl object for it.
+Sema::DeclPtrTy Sema::ActOnIvar(Scope *S,
+                                SourceLocation DeclStart,
+                                DeclPtrTy IntfDecl,
+                                Declarator &D, ExprTy *BitfieldWidth,
+                                tok::ObjCKeywordKind Visibility) {
+
+  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!
+
+  TypeSourceInfo *TInfo = 0;
+  QualType T = GetTypeForDeclarator(D, S, &TInfo);
+
+  if (BitWidth) {
+    // 6.7.2.1p3, 6.7.2.1p4
+    if (VerifyBitField(Loc, II, T, BitWidth)) {
+      D.setInvalidType();
+      DeleteExpr(BitWidth);
+      BitWidth = 0;
+    }
+  } else {
+    // Not a bitfield.
+
+    // validate II.
+
+  }
+
+  // C99 6.7.2.1p8: A member of a structure or union may have any type other
+  // than a variably modified type.
+  if (T->isVariablyModifiedType()) {
+    Diag(Loc, diag::err_typecheck_ivar_variable_size);
+    D.setInvalidType();
+  }
+
+  // Get the visibility (access control) for this ivar.
+  ObjCIvarDecl::AccessControl ac =
+    Visibility != tok::objc_not_keyword ? TranslateIvarVisibility(Visibility)
+                                        : ObjCIvarDecl::None;
+  // Must set ivar's DeclContext to its enclosing interface.
+  Decl *EnclosingDecl = IntfDecl.getAs<Decl>();
+  DeclContext *EnclosingContext;
+  if (ObjCImplementationDecl *IMPDecl =
+      dyn_cast<ObjCImplementationDecl>(EnclosingDecl)) {
+    // Case of ivar declared in an implementation. Context is that of its class.
+    ObjCInterfaceDecl* IDecl = IMPDecl->getClassInterface();
+    assert(IDecl && "No class- ActOnIvar");
+    EnclosingContext = cast_or_null<DeclContext>(IDecl);
+  } else
+    EnclosingContext = dyn_cast<DeclContext>(EnclosingDecl);
+  assert(EnclosingContext && "null DeclContext for ivar - ActOnIvar");
+
+  // Construct the decl.
+  ObjCIvarDecl *NewID = ObjCIvarDecl::Create(Context,
+                                             EnclosingContext, Loc, II, T,
+                                             TInfo, ac, (Expr *)BitfieldWidth);
+
+  if (II) {
+    NamedDecl *PrevDecl = LookupSingleName(S, II, LookupMemberName,
+                                           ForRedeclaration);
+    if (PrevDecl && isDeclInScope(PrevDecl, EnclosingContext, S)
+        && !isa<TagDecl>(PrevDecl)) {
+      Diag(Loc, diag::err_duplicate_member) << II;
+      Diag(PrevDecl->getLocation(), diag::note_previous_declaration);
+      NewID->setInvalidDecl();
+    }
+  }
+
+  // Process attributes attached to the ivar.
+  ProcessDeclAttributes(S, NewID, D);
+
+  if (D.isInvalidType())
+    NewID->setInvalidDecl();
+
+  if (II) {
+    // FIXME: When interfaces are DeclContexts, we'll need to add
+    // these to the interface.
+    S->AddDecl(DeclPtrTy::make(NewID));
+    IdResolver.AddDecl(NewID);
+  }
+
+  return DeclPtrTy::make(NewID);
+}
+
+void Sema::ActOnFields(Scope* S,
+                       SourceLocation RecLoc, DeclPtrTy RecDecl,
+                       DeclPtrTy *Fields, unsigned NumFields,
+                       SourceLocation LBrac, SourceLocation RBrac,
+                       AttributeList *Attr) {
+  Decl *EnclosingDecl = RecDecl.getAs<Decl>();
+  assert(EnclosingDecl && "missing record or interface decl");
+
+  // If the decl this is being inserted into is invalid, then it may be a
+  // redeclaration or some other bogus case.  Don't try to add fields to it.
+  if (EnclosingDecl->isInvalidDecl()) {
+    // FIXME: Deallocate fields?
+    return;
+  }
+
+
+  // Verify that all the fields are okay.
+  unsigned NumNamedMembers = 0;
+  llvm::SmallVector<FieldDecl*, 32> RecFields;
+
+  RecordDecl *Record = dyn_cast<RecordDecl>(EnclosingDecl);
+  for (unsigned i = 0; i != NumFields; ++i) {
+    FieldDecl *FD = cast<FieldDecl>(Fields[i].getAs<Decl>());
+
+    // Get the type for the field.
+    Type *FDTy = FD->getType().getTypePtr();
+
+    if (!FD->isAnonymousStructOrUnion()) {
+      // Remember all fields written by the user.
+      RecFields.push_back(FD);
+    }
+
+    // If the field is already invalid for some reason, don't emit more
+    // diagnostics about it.
+    if (FD->isInvalidDecl()) {
+      EnclosingDecl->setInvalidDecl();
+      continue;
+    }
+
+    // C99 6.7.2.1p2:
+    //   A structure or union shall not contain a member with
+    //   incomplete or function type (hence, a structure shall not
+    //   contain an instance of itself, but may contain a pointer to
+    //   an instance of itself), except that the last member of a
+    //   structure with more than one named member may have incomplete
+    //   array type; such a structure (and any union containing,
+    //   possibly recursively, a member that is such a structure)
+    //   shall not be a member of a structure or an element of an
+    //   array.
+    if (FDTy->isFunctionType()) {
+      // Field declared as a function.
+      Diag(FD->getLocation(), diag::err_field_declared_as_function)
+        << FD->getDeclName();
+      FD->setInvalidDecl();
+      EnclosingDecl->setInvalidDecl();
+      continue;
+    } else if (FDTy->isIncompleteArrayType() && i == NumFields - 1 &&
+               Record && Record->isStruct()) {
+      // Flexible array member.
+      if (NumNamedMembers < 1) {
+        Diag(FD->getLocation(), diag::err_flexible_array_empty_struct)
+          << FD->getDeclName();
+        FD->setInvalidDecl();
+        EnclosingDecl->setInvalidDecl();
+        continue;
+      }
+      // Okay, we have a legal flexible array member at the end of the struct.
+      if (Record)
+        Record->setHasFlexibleArrayMember(true);
+    } else if (!FDTy->isDependentType() &&
+               RequireCompleteType(FD->getLocation(), FD->getType(),
+                                   diag::err_field_incomplete)) {
+      // Incomplete type
+      FD->setInvalidDecl();
+      EnclosingDecl->setInvalidDecl();
+      continue;
+    } else if (const RecordType *FDTTy = FDTy->getAs<RecordType>()) {
+      if (FDTTy->getDecl()->hasFlexibleArrayMember()) {
+        // If this is a member of a union, then entire union becomes "flexible".
+        if (Record && Record->isUnion()) {
+          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::ext_variable_sized_type_in_struct)
+              << FD->getDeclName() << FD->getType();
+          else {
+            // 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->getDeclName();
+            if (Record)
+              Record->setHasFlexibleArrayMember(true);
+          }
+        }
+      }
+      if (Record && FDTTy->getDecl()->hasObjectMember())
+        Record->setHasObjectMember(true);
+    } else if (FDTy->isObjCInterfaceType()) {
+      /// A field cannot be an Objective-c object
+      Diag(FD->getLocation(), diag::err_statically_allocated_object);
+      FD->setInvalidDecl();
+      EnclosingDecl->setInvalidDecl();
+      continue;
+    } else if (getLangOptions().ObjC1 &&
+               getLangOptions().getGCMode() != LangOptions::NonGC &&
+               Record &&
+               (FD->getType()->isObjCObjectPointerType() ||
+                FD->getType().isObjCGCStrong()))
+      Record->setHasObjectMember(true);
+    // Keep track of the number of named members.
+    if (FD->getIdentifier())
+      ++NumNamedMembers;
+  }
+
+  // Okay, we successfully defined 'Record'.
+  if (Record) {
+    Record->completeDefinition(Context);
+  } else {
+    ObjCIvarDecl **ClsFields =
+      reinterpret_cast<ObjCIvarDecl**>(RecFields.data());
+    if (ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(EnclosingDecl)) {
+      ID->setIVarList(ClsFields, RecFields.size(), Context);
+      ID->setLocEnd(RBrac);
+      // Add ivar's to class's DeclContext.
+      for (unsigned i = 0, e = RecFields.size(); i != e; ++i) {
+        ClsFields[i]->setLexicalDeclContext(ID);
+        ID->addDecl(ClsFields[i]);
+      }
+      // Must enforce the rule that ivars in the base classes may not be
+      // duplicates.
+      if (ID->getSuperClass()) {
+        for (ObjCInterfaceDecl::ivar_iterator IVI = ID->ivar_begin(),
+             IVE = ID->ivar_end(); IVI != IVE; ++IVI) {
+          ObjCIvarDecl* Ivar = (*IVI);
+
+          if (IdentifierInfo *II = Ivar->getIdentifier()) {
+            ObjCIvarDecl* prevIvar =
+              ID->getSuperClass()->lookupInstanceVariable(II);
+            if (prevIvar) {
+              Diag(Ivar->getLocation(), diag::err_duplicate_member) << II;
+              Diag(prevIvar->getLocation(), diag::note_previous_declaration);
+            }
+          }
+        }
+      }
+    } else if (ObjCImplementationDecl *IMPDecl =
+                  dyn_cast<ObjCImplementationDecl>(EnclosingDecl)) {
+      assert(IMPDecl && "ActOnFields - missing ObjCImplementationDecl");
+      for (unsigned I = 0, N = RecFields.size(); I != N; ++I)
+        // Ivar declared in @implementation never belongs to the implementation.
+        // Only it is in implementation's lexical context.
+        ClsFields[I]->setLexicalDeclContext(IMPDecl);
+      CheckImplementationIvars(IMPDecl, ClsFields, RecFields.size(), RBrac);
+    }
+  }
+
+  if (Attr)
+    ProcessDeclAttributeList(S, Record, Attr);
+}
+
+/// \brief Determine whether the given integral value is representable within
+/// the given type T.
+static bool isRepresentableIntegerValue(ASTContext &Context,
+                                        llvm::APSInt &Value,
+                                        QualType T) {
+  assert(T->isIntegralType() && "Integral type required!");
+  unsigned BitWidth = Context.getTypeSize(T);
+  
+  if (Value.isUnsigned() || Value.isNonNegative())
+    return Value.getActiveBits() < BitWidth;
+  
+  return Value.getMinSignedBits() <= BitWidth;
+}
+
+// \brief Given an integral type, return the next larger integral type
+// (or a NULL type of no such type exists).
+static QualType getNextLargerIntegralType(ASTContext &Context, QualType T) {
+  // FIXME: Int128/UInt128 support, which also needs to be introduced into 
+  // enum checking below.
+  assert(T->isIntegralType() && "Integral type required!");
+  const unsigned NumTypes = 4;
+  QualType SignedIntegralTypes[NumTypes] = { 
+    Context.ShortTy, Context.IntTy, Context.LongTy, Context.LongLongTy
+  };
+  QualType UnsignedIntegralTypes[NumTypes] = { 
+    Context.UnsignedShortTy, Context.UnsignedIntTy, Context.UnsignedLongTy, 
+    Context.UnsignedLongLongTy
+  };
+  
+  unsigned BitWidth = Context.getTypeSize(T);
+  QualType *Types = T->isSignedIntegerType()? SignedIntegralTypes
+                                            : UnsignedIntegralTypes;
+  for (unsigned I = 0; I != NumTypes; ++I)
+    if (Context.getTypeSize(Types[I]) > BitWidth)
+      return Types[I];
+  
+  return QualType();
+}
+
+EnumConstantDecl *Sema::CheckEnumConstant(EnumDecl *Enum,
+                                          EnumConstantDecl *LastEnumConst,
+                                          SourceLocation IdLoc,
+                                          IdentifierInfo *Id,
+                                          ExprArg val) {
+  Expr *Val = (Expr *)val.get();
+
+  unsigned IntWidth = Context.Target.getIntWidth();
+  llvm::APSInt EnumVal(IntWidth);
+  QualType EltTy;
+  if (Val) {
+    if (Enum->isDependentType())
+      EltTy = Context.DependentTy;
+    else {
+      // C99 6.7.2.2p2: Make sure we have an integer constant expression.
+      SourceLocation ExpLoc;
+      if (VerifyIntegerConstantExpression(Val, &EnumVal)) {
+        Val = 0;
+      } else {        
+        if (!getLangOptions().CPlusPlus) {
+          // C99 6.7.2.2p2:
+          //   The expression that defines the value of an enumeration constant
+          //   shall be an integer constant expression that has a value 
+          //   representable as an int.
+          
+          // Complain if the value is not representable in an int.
+          if (!isRepresentableIntegerValue(Context, EnumVal, Context.IntTy))
+            Diag(IdLoc, diag::ext_enum_value_not_int)
+              << EnumVal.toString(10) << Val->getSourceRange()
+              << EnumVal.isNonNegative();
+          else if (!Context.hasSameType(Val->getType(), Context.IntTy)) {
+            // Force the type of the expression to 'int'.
+            ImpCastExprToType(Val, Context.IntTy, CastExpr::CK_IntegralCast);
+            
+            if (Val != val.get()) {
+              val.release();
+              val = Val;
+            }
+          }
+        }
+        
+        // C++0x [dcl.enum]p5:
+        //   If the underlying type is not fixed, the type of each enumerator
+        //   is the type of its initializing value:
+        //     - If an initializer is specified for an enumerator, the 
+        //       initializing value has the same type as the expression.
+        EltTy = Val->getType();
+      }
+    }
+  }
+
+  if (!Val) {
+    if (Enum->isDependentType())
+      EltTy = Context.DependentTy;
+    else if (!LastEnumConst) {
+      // C++0x [dcl.enum]p5:
+      //   If the underlying type is not fixed, the type of each enumerator
+      //   is the type of its initializing value:
+      //     - If no initializer is specified for the first enumerator, the 
+      //       initializing value has an unspecified integral type.
+      //
+      // GCC uses 'int' for its unspecified integral type, as does 
+      // C99 6.7.2.2p3.
+      EltTy = Context.IntTy;
+    } else {
+      // Assign the last value + 1.
+      EnumVal = LastEnumConst->getInitVal();
+      ++EnumVal;
+      EltTy = LastEnumConst->getType();
+
+      // Check for overflow on increment.
+      if (EnumVal < LastEnumConst->getInitVal()) {
+        // C++0x [dcl.enum]p5:
+        //   If the underlying type is not fixed, the type of each enumerator
+        //   is the type of its initializing value:
+        //
+        //     - Otherwise the type of the initializing value is the same as
+        //       the type of the initializing value of the preceding enumerator
+        //       unless the incremented value is not representable in that type,
+        //       in which case the type is an unspecified integral type 
+        //       sufficient to contain the incremented value. If no such type
+        //       exists, the program is ill-formed.
+        QualType T = getNextLargerIntegralType(Context, EltTy);
+        if (T.isNull()) {
+          // There is no integral type larger enough to represent this 
+          // value. Complain, then allow the value to wrap around.
+          EnumVal = LastEnumConst->getInitVal();
+          EnumVal.zext(EnumVal.getBitWidth() * 2);
+          Diag(IdLoc, diag::warn_enumerator_too_large)
+            << EnumVal.toString(10);
+        } else {
+          EltTy = T;
+        }
+        
+        // Retrieve the last enumerator's value, extent that type to the
+        // type that is supposed to be large enough to represent the incremented
+        // value, then increment.
+        EnumVal = LastEnumConst->getInitVal();
+        EnumVal.setIsSigned(EltTy->isSignedIntegerType());
+        EnumVal.zextOrTrunc(Context.getTypeSize(EltTy));
+        ++EnumVal;        
+        
+        // If we're not in C++, diagnose the overflow of enumerator values,
+        // which in C99 means that the enumerator value is not representable in
+        // an int (C99 6.7.2.2p2). However, we support GCC's extension that
+        // permits enumerator values that are representable in some larger
+        // integral type.
+        if (!getLangOptions().CPlusPlus && !T.isNull())
+          Diag(IdLoc, diag::warn_enum_value_overflow);
+      } else if (!getLangOptions().CPlusPlus &&
+                 !isRepresentableIntegerValue(Context, EnumVal, EltTy)) {
+        // Enforce C99 6.7.2.2p2 even when we compute the next value.
+        Diag(IdLoc, diag::ext_enum_value_not_int)
+          << EnumVal.toString(10) << 1;
+      }
+    }
+  }
+
+  if (!Enum->isDependentType()) {
+    // Make the enumerator value match the signedness and size of the 
+    // enumerator's type.
+    EnumVal.zextOrTrunc(Context.getTypeSize(EltTy));
+    EnumVal.setIsSigned(EltTy->isSignedIntegerType());
+  }
+  
+  val.release();
+  return EnumConstantDecl::Create(Context, Enum, IdLoc, Id, EltTy,
+                                  Val, EnumVal);
+}
+
+
+Sema::DeclPtrTy Sema::ActOnEnumConstant(Scope *S, DeclPtrTy theEnumDecl,
+                                        DeclPtrTy lastEnumConst,
+                                        SourceLocation IdLoc,
+                                        IdentifierInfo *Id,
+                                        SourceLocation EqualLoc, ExprTy *val) {
+  EnumDecl *TheEnumDecl = cast<EnumDecl>(theEnumDecl.getAs<Decl>());
+  EnumConstantDecl *LastEnumConst =
+    cast_or_null<EnumConstantDecl>(lastEnumConst.getAs<Decl>());
+  Expr *Val = static_cast<Expr*>(val);
+
+  // The scope passed in may not be a decl scope.  Zip up the scope tree until
+  // we find one that is.
+  S = getNonFieldDeclScope(S);
+
+  // Verify that there isn't already something declared with this name in this
+  // scope.
+  NamedDecl *PrevDecl = LookupSingleName(S, Id, LookupOrdinaryName,
+                                         ForRedeclaration);
+  if (PrevDecl && PrevDecl->isTemplateParameter()) {
+    // Maybe we will complain about the shadowed template parameter.
+    DiagnoseTemplateParameterShadow(IdLoc, PrevDecl);
+    // Just pretend that we didn't see the previous declaration.
+    PrevDecl = 0;
+  }
+
+  if (PrevDecl) {
+    // When in C++, we may get a TagDecl with the same name; in this case the
+    // enum constant will 'hide' the tag.
+    assert((getLangOptions().CPlusPlus || !isa<TagDecl>(PrevDecl)) &&
+           "Received TagDecl when not in C++!");
+    if (!isa<TagDecl>(PrevDecl) && isDeclInScope(PrevDecl, CurContext, S)) {
+      if (isa<EnumConstantDecl>(PrevDecl))
+        Diag(IdLoc, diag::err_redefinition_of_enumerator) << Id;
+      else
+        Diag(IdLoc, diag::err_redefinition) << Id;
+      Diag(PrevDecl->getLocation(), diag::note_previous_definition);
+      if (Val) Val->Destroy(Context);
+      return DeclPtrTy();
+    }
+  }
+
+  EnumConstantDecl *New = CheckEnumConstant(TheEnumDecl, LastEnumConst,
+                                            IdLoc, Id, Owned(Val));
+
+  // Register this decl in the current scope stack.
+  if (New) {
+    New->setAccess(TheEnumDecl->getAccess());
+    PushOnScopeChains(New, S);
+  }
+
+  return DeclPtrTy::make(New);
+}
+
+void Sema::ActOnEnumBody(SourceLocation EnumLoc, SourceLocation LBraceLoc,
+                         SourceLocation RBraceLoc, DeclPtrTy EnumDeclX,
+                         DeclPtrTy *Elements, unsigned NumElements,
+                         Scope *S, AttributeList *Attr) {
+  EnumDecl *Enum = cast<EnumDecl>(EnumDeclX.getAs<Decl>());
+  QualType EnumType = Context.getTypeDeclType(Enum);
+
+  if (Attr)
+    ProcessDeclAttributeList(S, Enum, Attr);
+
+  if (Enum->isDependentType()) {
+    for (unsigned i = 0; i != NumElements; ++i) {
+      EnumConstantDecl *ECD =
+        cast_or_null<EnumConstantDecl>(Elements[i].getAs<Decl>());
+      if (!ECD) continue;
+
+      ECD->setType(EnumType);
+    }
+
+    Enum->completeDefinition(Context, Context.DependentTy, Context.DependentTy);
+    return;
+  }
+
+  // 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.
+  unsigned IntWidth = Context.Target.getIntWidth();
+  unsigned CharWidth = Context.Target.getCharWidth();
+  unsigned ShortWidth = Context.Target.getShortWidth();
+
+  // Verify that all the values are okay, compute the size of the values, and
+  // reverse the list.
+  unsigned NumNegativeBits = 0;
+  unsigned NumPositiveBits = 0;
+
+  // Keep track of whether all elements have type int.
+  bool AllElementsInt = true;
+
+  for (unsigned i = 0; i != NumElements; ++i) {
+    EnumConstantDecl *ECD =
+      cast_or_null<EnumConstantDecl>(Elements[i].getAs<Decl>());
+    if (!ECD) continue;  // Already issued a diagnostic.
+
+    const llvm::APSInt &InitVal = ECD->getInitVal();
+
+    // Keep track of the size of positive and negative values.
+    if (InitVal.isUnsigned() || InitVal.isNonNegative())
+      NumPositiveBits = std::max(NumPositiveBits,
+                                 (unsigned)InitVal.getActiveBits());
+    else
+      NumNegativeBits = std::max(NumNegativeBits,
+                                 (unsigned)InitVal.getMinSignedBits());
+
+    // Keep track of whether every enum element has type int (very commmon).
+    if (AllElementsInt)
+      AllElementsInt = ECD->getType() == Context.IntTy;
+  }
+
+  // Figure out the type that should be used for this enum.
+  // FIXME: Support -fshort-enums.
+  QualType BestType;
+  unsigned BestWidth;
+
+  // C++0x N3000 [conv.prom]p3:
+  //   An rvalue of an unscoped enumeration type whose underlying
+  //   type is not fixed can be converted to an rvalue of the first
+  //   of the following types that can represent all the values of
+  //   the enumeration: int, unsigned int, long int, unsigned long
+  //   int, long long int, or unsigned long long int.
+  // C99 6.4.4.3p2:
+  //   An identifier declared as an enumeration constant has type int.
+  // The C99 rule is modified by a gcc extension 
+  QualType BestPromotionType;
+
+  bool Packed = Enum->getAttr<PackedAttr>() ? true : false;
+
+  if (NumNegativeBits) {
+    // If there is a negative value, figure out the smallest integer type (of
+    // int/long/longlong) that fits.
+    // If it's packed, check also if it fits a char or a short.
+    if (Packed && NumNegativeBits <= CharWidth && NumPositiveBits < CharWidth) {
+      BestType = Context.SignedCharTy;
+      BestWidth = CharWidth;
+    } else if (Packed && NumNegativeBits <= ShortWidth &&
+               NumPositiveBits < ShortWidth) {
+      BestType = Context.ShortTy;
+      BestWidth = ShortWidth;
+    } else if (NumNegativeBits <= IntWidth && NumPositiveBits < IntWidth) {
+      BestType = Context.IntTy;
+      BestWidth = IntWidth;
+    } else {
+      BestWidth = Context.Target.getLongWidth();
+
+      if (NumNegativeBits <= BestWidth && NumPositiveBits < BestWidth) {
+        BestType = Context.LongTy;
+      } else {
+        BestWidth = Context.Target.getLongLongWidth();
+
+        if (NumNegativeBits > BestWidth || NumPositiveBits >= BestWidth)
+          Diag(Enum->getLocation(), diag::warn_enum_too_large);
+        BestType = Context.LongLongTy;
+      }
+    }
+    BestPromotionType = (BestWidth <= IntWidth ? Context.IntTy : BestType);
+  } else {
+    // If there is no negative value, figure out the smallest type that fits
+    // all of the enumerator values.
+    // If it's packed, check also if it fits a char or a short.
+    if (Packed && NumPositiveBits <= CharWidth) {
+      BestType = Context.UnsignedCharTy;
+      BestPromotionType = Context.IntTy;
+      BestWidth = CharWidth;
+    } else if (Packed && NumPositiveBits <= ShortWidth) {
+      BestType = Context.UnsignedShortTy;
+      BestPromotionType = Context.IntTy;
+      BestWidth = ShortWidth;
+    } else if (NumPositiveBits <= IntWidth) {
+      BestType = Context.UnsignedIntTy;
+      BestWidth = IntWidth;
+      BestPromotionType
+        = (NumPositiveBits == BestWidth || !getLangOptions().CPlusPlus)
+                           ? Context.UnsignedIntTy : Context.IntTy;
+    } else if (NumPositiveBits <=
+               (BestWidth = Context.Target.getLongWidth())) {
+      BestType = Context.UnsignedLongTy;
+      BestPromotionType
+        = (NumPositiveBits == BestWidth || !getLangOptions().CPlusPlus)
+                           ? Context.UnsignedLongTy : Context.LongTy;
+    } else {
+      BestWidth = Context.Target.getLongLongWidth();
+      assert(NumPositiveBits <= BestWidth &&
+             "How could an initializer get larger than ULL?");
+      BestType = Context.UnsignedLongLongTy;
+      BestPromotionType
+        = (NumPositiveBits == BestWidth || !getLangOptions().CPlusPlus)
+                           ? Context.UnsignedLongLongTy : Context.LongLongTy;
+    }
+  }
+
+  // Loop over all of the enumerator constants, changing their types to match
+  // the type of the enum if needed.
+  for (unsigned i = 0; i != NumElements; ++i) {
+    EnumConstantDecl *ECD =
+      cast_or_null<EnumConstantDecl>(Elements[i].getAs<Decl>());
+    if (!ECD) continue;  // Already issued a diagnostic.
+
+    // Standard C says the enumerators have int type, but we allow, as an
+    // extension, the enumerators to be larger than int size.  If each
+    // enumerator value fits in an int, type it as an int, otherwise type it the
+    // same as the enumerator decl itself.  This means that in "enum { X = 1U }"
+    // that X has type 'int', not 'unsigned'.
+
+    // Determine whether the value fits into an int.
+    llvm::APSInt InitVal = ECD->getInitVal();
+
+    // If it fits into an integer type, force it.  Otherwise force it to match
+    // the enum decl type.
+    QualType NewTy;
+    unsigned NewWidth;
+    bool NewSign;
+    if (!getLangOptions().CPlusPlus &&
+        isRepresentableIntegerValue(Context, InitVal, Context.IntTy)) {
+      NewTy = Context.IntTy;
+      NewWidth = IntWidth;
+      NewSign = true;
+    } else if (ECD->getType() == BestType) {
+      // Already the right type!
+      if (getLangOptions().CPlusPlus)
+        // C++ [dcl.enum]p4: Following the closing brace of an
+        // enum-specifier, each enumerator has the type of its
+        // enumeration.
+        ECD->setType(EnumType);
+      continue;
+    } else {
+      NewTy = BestType;
+      NewWidth = BestWidth;
+      NewSign = BestType->isSignedIntegerType();
+    }
+
+    // Adjust the APSInt value.
+    InitVal.extOrTrunc(NewWidth);
+    InitVal.setIsSigned(NewSign);
+    ECD->setInitVal(InitVal);
+
+    // Adjust the Expr initializer and type.
+    if (ECD->getInitExpr())
+      ECD->setInitExpr(new (Context) ImplicitCastExpr(NewTy,
+                                                      CastExpr::CK_IntegralCast,
+                                                      ECD->getInitExpr(),
+                                                      /*isLvalue=*/false));
+    if (getLangOptions().CPlusPlus)
+      // C++ [dcl.enum]p4: Following the closing brace of an
+      // enum-specifier, each enumerator has the type of its
+      // enumeration.
+      ECD->setType(EnumType);
+    else
+      ECD->setType(NewTy);
+  }
+
+  Enum->completeDefinition(Context, BestType, BestPromotionType);
+}
+
+Sema::DeclPtrTy Sema::ActOnFileScopeAsmDecl(SourceLocation Loc,
+                                            ExprArg expr) {
+  StringLiteral *AsmString = cast<StringLiteral>(expr.takeAs<Expr>());
+
+  FileScopeAsmDecl *New = FileScopeAsmDecl::Create(Context, CurContext,
+                                                   Loc, AsmString);
+  CurContext->addDecl(New);
+  return DeclPtrTy::make(New);
+}
+
+void Sema::ActOnPragmaWeakID(IdentifierInfo* Name,
+                             SourceLocation PragmaLoc,
+                             SourceLocation NameLoc) {
+  Decl *PrevDecl = LookupSingleName(TUScope, Name, LookupOrdinaryName);
+
+  if (PrevDecl) {
+    PrevDecl->addAttr(::new (Context) WeakAttr());
+  } else {
+    (void)WeakUndeclaredIdentifiers.insert(
+      std::pair<IdentifierInfo*,WeakInfo>
+        (Name, WeakInfo((IdentifierInfo*)0, NameLoc)));
+  }
+}
+
+void Sema::ActOnPragmaWeakAlias(IdentifierInfo* Name,
+                                IdentifierInfo* AliasName,
+                                SourceLocation PragmaLoc,
+                                SourceLocation NameLoc,
+                                SourceLocation AliasNameLoc) {
+  Decl *PrevDecl = LookupSingleName(TUScope, AliasName, LookupOrdinaryName);
+  WeakInfo W = WeakInfo(Name, NameLoc);
+
+  if (PrevDecl) {
+    if (!PrevDecl->hasAttr<AliasAttr>())
+      if (NamedDecl *ND = dyn_cast<NamedDecl>(PrevDecl))
+        DeclApplyPragmaWeak(TUScope, ND, W);
+  } else {
+    (void)WeakUndeclaredIdentifiers.insert(
+      std::pair<IdentifierInfo*,WeakInfo>(AliasName, W));
+  }
+}
diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp
new file mode 100644
index 0000000..01e8fda
--- /dev/null
+++ b/lib/Sema/SemaDeclAttr.cpp
@@ -0,0 +1,2054 @@
+//===--- SemaDeclAttr.cpp - Declaration Attribute Handling ----------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+//  This file implements decl-related attribute processing.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Sema.h"
+#include "TargetAttributesSema.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/AST/Expr.h"
+#include "clang/Basic/TargetInfo.h"
+#include "clang/Parse/DeclSpec.h"
+#include "llvm/ADT/StringExtras.h"
+using namespace clang;
+
+//===----------------------------------------------------------------------===//
+//  Helper functions
+//===----------------------------------------------------------------------===//
+
+static const FunctionType *getFunctionType(const Decl *d,
+                                           bool blocksToo = true) {
+  QualType Ty;
+  if (const ValueDecl *decl = dyn_cast<ValueDecl>(d))
+    Ty = decl->getType();
+  else if (const FieldDecl *decl = dyn_cast<FieldDecl>(d))
+    Ty = decl->getType();
+  else if (const TypedefDecl* decl = dyn_cast<TypedefDecl>(d))
+    Ty = decl->getUnderlyingType();
+  else
+    return 0;
+
+  if (Ty->isFunctionPointerType())
+    Ty = Ty->getAs<PointerType>()->getPointeeType();
+  else if (blocksToo && Ty->isBlockPointerType())
+    Ty = Ty->getAs<BlockPointerType>()->getPointeeType();
+
+  return Ty->getAs<FunctionType>();
+}
+
+// FIXME: We should provide an abstraction around a method or function
+// to provide the following bits of information.
+
+/// isFunction - Return true if the given decl has function
+/// type (function or function-typed variable).
+static bool isFunction(const Decl *d) {
+  return getFunctionType(d, false) != NULL;
+}
+
+/// isFunctionOrMethod - Return true if the given decl has function
+/// type (function or function-typed variable) or an Objective-C
+/// method.
+static bool isFunctionOrMethod(const Decl *d) {
+  return isFunction(d)|| isa<ObjCMethodDecl>(d);
+}
+
+/// isFunctionOrMethodOrBlock - Return true if the given decl has function
+/// type (function or function-typed variable) or an Objective-C
+/// method or a block.
+static bool isFunctionOrMethodOrBlock(const Decl *d) {
+  if (isFunctionOrMethod(d))
+    return true;
+  // check for block is more involved.
+  if (const VarDecl *V = dyn_cast<VarDecl>(d)) {
+    QualType Ty = V->getType();
+    return Ty->isBlockPointerType();
+  }
+  return isa<BlockDecl>(d);
+}
+
+/// hasFunctionProto - Return true if the given decl has a argument
+/// information. This decl should have already passed
+/// isFunctionOrMethod or isFunctionOrMethodOrBlock.
+static bool hasFunctionProto(const Decl *d) {
+  if (const FunctionType *FnTy = getFunctionType(d))
+    return isa<FunctionProtoType>(FnTy);
+  else {
+    assert(isa<ObjCMethodDecl>(d) || isa<BlockDecl>(d));
+    return true;
+  }
+}
+
+/// getFunctionOrMethodNumArgs - Return number of function or method
+/// arguments. It is an error to call this on a K&R function (use
+/// hasFunctionProto first).
+static unsigned getFunctionOrMethodNumArgs(const Decl *d) {
+  if (const FunctionType *FnTy = getFunctionType(d))
+    return cast<FunctionProtoType>(FnTy)->getNumArgs();
+  if (const BlockDecl *BD = dyn_cast<BlockDecl>(d))
+    return BD->getNumParams();
+  return cast<ObjCMethodDecl>(d)->param_size();
+}
+
+static QualType getFunctionOrMethodArgType(const Decl *d, unsigned Idx) {
+  if (const FunctionType *FnTy = getFunctionType(d))
+    return cast<FunctionProtoType>(FnTy)->getArgType(Idx);
+  if (const BlockDecl *BD = dyn_cast<BlockDecl>(d))
+    return BD->getParamDecl(Idx)->getType();
+
+  return cast<ObjCMethodDecl>(d)->param_begin()[Idx]->getType();
+}
+
+static QualType getFunctionOrMethodResultType(const Decl *d) {
+  if (const FunctionType *FnTy = getFunctionType(d))
+    return cast<FunctionProtoType>(FnTy)->getResultType();
+  return cast<ObjCMethodDecl>(d)->getResultType();
+}
+
+static bool isFunctionOrMethodVariadic(const Decl *d) {
+  if (const FunctionType *FnTy = getFunctionType(d)) {
+    const FunctionProtoType *proto = cast<FunctionProtoType>(FnTy);
+    return proto->isVariadic();
+  } else if (const BlockDecl *BD = dyn_cast<BlockDecl>(d))
+    return BD->IsVariadic();
+  else {
+    return cast<ObjCMethodDecl>(d)->isVariadic();
+  }
+}
+
+static inline bool isNSStringType(QualType T, ASTContext &Ctx) {
+  const ObjCObjectPointerType *PT = T->getAs<ObjCObjectPointerType>();
+  if (!PT)
+    return false;
+
+  const ObjCInterfaceType *ClsT =PT->getPointeeType()->getAs<ObjCInterfaceType>();
+  if (!ClsT)
+    return false;
+
+  IdentifierInfo* ClsName = ClsT->getDecl()->getIdentifier();
+
+  // FIXME: Should we walk the chain of classes?
+  return ClsName == &Ctx.Idents.get("NSString") ||
+         ClsName == &Ctx.Idents.get("NSMutableString");
+}
+
+static inline bool isCFStringType(QualType T, ASTContext &Ctx) {
+  const PointerType *PT = T->getAs<PointerType>();
+  if (!PT)
+    return false;
+
+  const RecordType *RT = PT->getPointeeType()->getAs<RecordType>();
+  if (!RT)
+    return false;
+
+  const RecordDecl *RD = RT->getDecl();
+  if (RD->getTagKind() != TagDecl::TK_struct)
+    return false;
+
+  return RD->getIdentifier() == &Ctx.Idents.get("__CFString");
+}
+
+//===----------------------------------------------------------------------===//
+// Attribute Implementations
+//===----------------------------------------------------------------------===//
+
+// FIXME: All this manual attribute parsing code is gross. At the
+// least add some helper functions to check most argument patterns (#
+// and types of args).
+
+static void HandleExtVectorTypeAttr(Scope *scope, Decl *d,
+                                    const AttributeList &Attr, Sema &S) {
+  TypedefDecl *tDecl = dyn_cast<TypedefDecl>(d);
+  if (tDecl == 0) {
+    S.Diag(Attr.getLoc(), diag::err_typecheck_ext_vector_not_typedef);
+    return;
+  }
+
+  QualType curType = tDecl->getUnderlyingType();
+
+  Expr *sizeExpr;
+
+  // Special case where the argument is a template id.
+  if (Attr.getParameterName()) {
+    CXXScopeSpec SS;
+    UnqualifiedId id;
+    id.setIdentifier(Attr.getParameterName(), Attr.getLoc());
+    sizeExpr = S.ActOnIdExpression(scope, SS, id, false, false).takeAs<Expr>();
+  } else {
+    // check the attribute arguments.
+    if (Attr.getNumArgs() != 1) {
+      S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
+      return;
+    }
+    sizeExpr = static_cast<Expr *>(Attr.getArg(0));
+  }
+
+  // Instantiate/Install the vector type, and let Sema build the type for us.
+  // This will run the reguired checks.
+  QualType T = S.BuildExtVectorType(curType, S.Owned(sizeExpr), Attr.getLoc());
+  if (!T.isNull()) {
+    // FIXME: preserve the old source info.
+    tDecl->setTypeSourceInfo(S.Context.getTrivialTypeSourceInfo(T));
+
+    // Remember this typedef decl, we will need it later for diagnostics.
+    S.ExtVectorDecls.push_back(tDecl);
+  }
+}
+
+static void HandlePackedAttr(Decl *d, const AttributeList &Attr, Sema &S) {
+  // check the attribute arguments.
+  if (Attr.getNumArgs() > 0) {
+    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
+    return;
+  }
+
+  if (TagDecl *TD = dyn_cast<TagDecl>(d))
+    TD->addAttr(::new (S.Context) PackedAttr);
+  else if (FieldDecl *FD = dyn_cast<FieldDecl>(d)) {
+    // If the alignment is less than or equal to 8 bits, the packed attribute
+    // has no effect.
+    if (!FD->getType()->isIncompleteType() &&
+        S.Context.getTypeAlign(FD->getType()) <= 8)
+      S.Diag(Attr.getLoc(), diag::warn_attribute_ignored_for_field_of_type)
+        << Attr.getName() << FD->getType();
+    else
+      FD->addAttr(::new (S.Context) PackedAttr);
+  } else
+    S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName();
+}
+
+static void HandleIBOutletAttr(Decl *d, const AttributeList &Attr, Sema &S) {
+  // check the attribute arguments.
+  if (Attr.getNumArgs() > 0) {
+    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
+    return;
+  }
+
+  // The IBOutlet attribute only applies to instance variables of Objective-C
+  // classes.
+  if (isa<ObjCIvarDecl>(d) || isa<ObjCPropertyDecl>(d))
+    d->addAttr(::new (S.Context) IBOutletAttr());
+  else
+    S.Diag(Attr.getLoc(), diag::err_attribute_iboutlet);
+}
+
+static void HandleNonNullAttr(Decl *d, const AttributeList &Attr, Sema &S) {
+  // GCC ignores the nonnull attribute on K&R style function prototypes, so we
+  // ignore it as well
+  if (!isFunctionOrMethod(d) || !hasFunctionProto(d)) {
+    S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
+      << Attr.getName() << 0 /*function*/;
+    return;
+  }
+
+  unsigned NumArgs = getFunctionOrMethodNumArgs(d);
+
+  // The nonnull attribute only applies to pointers.
+  llvm::SmallVector<unsigned, 10> NonNullArgs;
+
+  for (AttributeList::arg_iterator I=Attr.arg_begin(),
+                                   E=Attr.arg_end(); I!=E; ++I) {
+
+
+    // The argument must be an integer constant expression.
+    Expr *Ex = static_cast<Expr *>(*I);
+    llvm::APSInt ArgNum(32);
+    if (!Ex->isIntegerConstantExpr(ArgNum, S.Context)) {
+      S.Diag(Attr.getLoc(), diag::err_attribute_argument_not_int)
+        << "nonnull" << Ex->getSourceRange();
+      return;
+    }
+
+    unsigned x = (unsigned) ArgNum.getZExtValue();
+
+    if (x < 1 || x > NumArgs) {
+      S.Diag(Attr.getLoc(), diag::err_attribute_argument_out_of_bounds)
+       << "nonnull" << I.getArgNum() << Ex->getSourceRange();
+      return;
+    }
+
+    --x;
+
+    // Is the function argument a pointer type?
+    QualType T = getFunctionOrMethodArgType(d, x);
+    if (!T->isAnyPointerType() && !T->isBlockPointerType()) {
+      // FIXME: Should also highlight argument in decl.
+      S.Diag(Attr.getLoc(), diag::err_nonnull_pointers_only)
+        << "nonnull" << Ex->getSourceRange();
+      continue;
+    }
+
+    NonNullArgs.push_back(x);
+  }
+
+  // If no arguments were specified to __attribute__((nonnull)) then all pointer
+  // arguments have a nonnull attribute.
+  if (NonNullArgs.empty()) {
+    for (unsigned I = 0, E = getFunctionOrMethodNumArgs(d); I != E; ++I) {
+      QualType T = getFunctionOrMethodArgType(d, I);
+      if (T->isAnyPointerType() || T->isBlockPointerType())
+        NonNullArgs.push_back(I);
+    }
+
+    if (NonNullArgs.empty()) {
+      S.Diag(Attr.getLoc(), diag::warn_attribute_nonnull_no_pointers);
+      return;
+    }
+  }
+
+  unsigned* start = &NonNullArgs[0];
+  unsigned size = NonNullArgs.size();
+  std::sort(start, start + size);
+  d->addAttr(::new (S.Context) NonNullAttr(start, size));
+}
+
+static void HandleAliasAttr(Decl *d, const AttributeList &Attr, Sema &S) {
+  // check the attribute arguments.
+  if (Attr.getNumArgs() != 1) {
+    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
+    return;
+  }
+
+  Expr *Arg = static_cast<Expr*>(Attr.getArg(0));
+  Arg = Arg->IgnoreParenCasts();
+  StringLiteral *Str = dyn_cast<StringLiteral>(Arg);
+
+  if (Str == 0 || Str->isWide()) {
+    S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_string)
+      << "alias" << 1;
+    return;
+  }
+
+  // FIXME: check if target symbol exists in current file
+
+  d->addAttr(::new (S.Context) AliasAttr(Str->getString()));
+}
+
+static void HandleAlwaysInlineAttr(Decl *d, const AttributeList &Attr,
+                                   Sema &S) {
+  // check the attribute arguments.
+  if (Attr.getNumArgs() != 0) {
+    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
+    return;
+  }
+
+  if (!isa<FunctionDecl>(d)) {
+    S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
+    << Attr.getName() << 0 /*function*/;
+    return;
+  }
+
+  d->addAttr(::new (S.Context) AlwaysInlineAttr());
+}
+
+static void HandleMallocAttr(Decl *d, const AttributeList &Attr, Sema &S) {
+  // check the attribute arguments.
+  if (Attr.getNumArgs() != 0) {
+    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
+    return;
+  }
+
+  if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(d)) {
+    QualType RetTy = FD->getResultType();
+    if (RetTy->isAnyPointerType() || RetTy->isBlockPointerType()) {
+      d->addAttr(::new (S.Context) MallocAttr());
+      return;
+    }
+  }
+
+  S.Diag(Attr.getLoc(), diag::warn_attribute_malloc_pointer_only);
+}
+
+static bool HandleCommonNoReturnAttr(Decl *d, const AttributeList &Attr,
+                                     Sema &S) {
+  // check the attribute arguments.
+  if (Attr.getNumArgs() != 0) {
+    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
+    return false;
+  }
+
+  if (!isFunctionOrMethod(d) && !isa<BlockDecl>(d)) {
+    ValueDecl *VD = dyn_cast<ValueDecl>(d);
+    if (VD == 0 || (!VD->getType()->isBlockPointerType()
+                    && !VD->getType()->isFunctionPointerType())) {
+      S.Diag(Attr.getLoc(),
+             Attr.isCXX0XAttribute() ? diag::err_attribute_wrong_decl_type
+                                     : diag::warn_attribute_wrong_decl_type)
+        << Attr.getName() << 0 /*function*/;
+      return false;
+    }
+  }
+
+  return true;
+}
+
+static void HandleNoReturnAttr(Decl *d, const AttributeList &Attr, Sema &S) {
+  // Don't apply as a decl attribute to ValueDecl.
+  // FIXME: probably ought to diagnose this.
+  if (isa<ValueDecl>(d))
+    return;
+
+  if (HandleCommonNoReturnAttr(d, Attr, S))
+    d->addAttr(::new (S.Context) NoReturnAttr());
+}
+
+static void HandleAnalyzerNoReturnAttr(Decl *d, const AttributeList &Attr,
+                                       Sema &S) {
+  if (HandleCommonNoReturnAttr(d, Attr, S))
+    d->addAttr(::new (S.Context) AnalyzerNoReturnAttr());
+}
+
+static void HandleDependencyAttr(Decl *d, const AttributeList &Attr, Sema &S) {
+  if (!isFunctionOrMethod(d) && !isa<ParmVarDecl>(d)) {
+    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type)
+      << Attr.getName() << 8 /*function, method, or parameter*/;
+    return;
+  }
+  // FIXME: Actually store the attribute on the declaration
+}
+
+static void HandleUnusedAttr(Decl *d, const AttributeList &Attr, Sema &S) {
+  // check the attribute arguments.
+  if (Attr.getNumArgs() != 0) {
+    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
+    return;
+  }
+
+  if (!isa<VarDecl>(d) && !isFunctionOrMethod(d)) {
+    S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
+      << Attr.getName() << 2 /*variable and function*/;
+    return;
+  }
+
+  d->addAttr(::new (S.Context) UnusedAttr());
+}
+
+static void HandleUsedAttr(Decl *d, const AttributeList &Attr, Sema &S) {
+  // check the attribute arguments.
+  if (Attr.getNumArgs() != 0) {
+    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
+    return;
+  }
+
+  if (const VarDecl *VD = dyn_cast<VarDecl>(d)) {
+    if (VD->hasLocalStorage() || VD->hasExternalStorage()) {
+      S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "used";
+      return;
+    }
+  } else if (!isFunctionOrMethod(d)) {
+    S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
+      << Attr.getName() << 2 /*variable and function*/;
+    return;
+  }
+
+  d->addAttr(::new (S.Context) UsedAttr());
+}
+
+static void HandleConstructorAttr(Decl *d, const AttributeList &Attr, Sema &S) {
+  // check the attribute arguments.
+  if (Attr.getNumArgs() != 0 && Attr.getNumArgs() != 1) {
+    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments)
+      << "0 or 1";
+    return;
+  }
+
+  int priority = 65535; // FIXME: Do not hardcode such constants.
+  if (Attr.getNumArgs() > 0) {
+    Expr *E = static_cast<Expr *>(Attr.getArg(0));
+    llvm::APSInt Idx(32);
+    if (!E->isIntegerConstantExpr(Idx, S.Context)) {
+      S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_int)
+        << "constructor" << 1 << E->getSourceRange();
+      return;
+    }
+    priority = Idx.getZExtValue();
+  }
+
+  if (!isa<FunctionDecl>(d)) {
+    S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
+      << Attr.getName() << 0 /*function*/;
+    return;
+  }
+
+  d->addAttr(::new (S.Context) ConstructorAttr(priority));
+}
+
+static void HandleDestructorAttr(Decl *d, const AttributeList &Attr, Sema &S) {
+  // check the attribute arguments.
+  if (Attr.getNumArgs() != 0 && Attr.getNumArgs() != 1) {
+    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments)
+       << "0 or 1";
+    return;
+  }
+
+  int priority = 65535; // FIXME: Do not hardcode such constants.
+  if (Attr.getNumArgs() > 0) {
+    Expr *E = static_cast<Expr *>(Attr.getArg(0));
+    llvm::APSInt Idx(32);
+    if (!E->isIntegerConstantExpr(Idx, S.Context)) {
+      S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_int)
+        << "destructor" << 1 << E->getSourceRange();
+      return;
+    }
+    priority = Idx.getZExtValue();
+  }
+
+  if (!isa<FunctionDecl>(d)) {
+    S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
+      << Attr.getName() << 0 /*function*/;
+    return;
+  }
+
+  d->addAttr(::new (S.Context) DestructorAttr(priority));
+}
+
+static void HandleDeprecatedAttr(Decl *d, const AttributeList &Attr, Sema &S) {
+  // check the attribute arguments.
+  if (Attr.getNumArgs() != 0) {
+    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
+    return;
+  }
+
+  d->addAttr(::new (S.Context) DeprecatedAttr());
+}
+
+static void HandleUnavailableAttr(Decl *d, const AttributeList &Attr, Sema &S) {
+  // check the attribute arguments.
+  if (Attr.getNumArgs() != 0) {
+    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
+    return;
+  }
+
+  d->addAttr(::new (S.Context) UnavailableAttr());
+}
+
+static void HandleVisibilityAttr(Decl *d, const AttributeList &Attr, Sema &S) {
+  // check the attribute arguments.
+  if (Attr.getNumArgs() != 1) {
+    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
+    return;
+  }
+
+  Expr *Arg = static_cast<Expr*>(Attr.getArg(0));
+  Arg = Arg->IgnoreParenCasts();
+  StringLiteral *Str = dyn_cast<StringLiteral>(Arg);
+
+  if (Str == 0 || Str->isWide()) {
+    S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_string)
+      << "visibility" << 1;
+    return;
+  }
+
+  llvm::StringRef TypeStr = Str->getString();
+  VisibilityAttr::VisibilityTypes type;
+
+  if (TypeStr == "default")
+    type = VisibilityAttr::DefaultVisibility;
+  else if (TypeStr == "hidden")
+    type = VisibilityAttr::HiddenVisibility;
+  else if (TypeStr == "internal")
+    type = VisibilityAttr::HiddenVisibility; // FIXME
+  else if (TypeStr == "protected")
+    type = VisibilityAttr::ProtectedVisibility;
+  else {
+    S.Diag(Attr.getLoc(), diag::warn_attribute_unknown_visibility) << TypeStr;
+    return;
+  }
+
+  d->addAttr(::new (S.Context) VisibilityAttr(type));
+}
+
+static void HandleObjCExceptionAttr(Decl *D, const AttributeList &Attr,
+                                    Sema &S) {
+  if (Attr.getNumArgs() != 0) {
+    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
+    return;
+  }
+
+  ObjCInterfaceDecl *OCI = dyn_cast<ObjCInterfaceDecl>(D);
+  if (OCI == 0) {
+    S.Diag(Attr.getLoc(), diag::err_attribute_requires_objc_interface);
+    return;
+  }
+
+  D->addAttr(::new (S.Context) ObjCExceptionAttr());
+}
+
+static void HandleObjCNSObject(Decl *D, const AttributeList &Attr, Sema &S) {
+  if (Attr.getNumArgs() != 0) {
+    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
+    return;
+  }
+  if (TypedefDecl *TD = dyn_cast<TypedefDecl>(D)) {
+    QualType T = TD->getUnderlyingType();
+    if (!T->isPointerType() ||
+        !T->getAs<PointerType>()->getPointeeType()->isRecordType()) {
+      S.Diag(TD->getLocation(), diag::err_nsobject_attribute);
+      return;
+    }
+  }
+  D->addAttr(::new (S.Context) ObjCNSObjectAttr());
+}
+
+static void
+HandleOverloadableAttr(Decl *D, const AttributeList &Attr, Sema &S) {
+  if (Attr.getNumArgs() != 0) {
+    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
+    return;
+  }
+
+  if (!isa<FunctionDecl>(D)) {
+    S.Diag(Attr.getLoc(), diag::err_attribute_overloadable_not_function);
+    return;
+  }
+
+  D->addAttr(::new (S.Context) OverloadableAttr());
+}
+
+static void HandleBlocksAttr(Decl *d, const AttributeList &Attr, Sema &S) {
+  if (!Attr.getParameterName()) {
+    S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_string)
+      << "blocks" << 1;
+    return;
+  }
+
+  if (Attr.getNumArgs() != 0) {
+    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
+    return;
+  }
+
+  BlocksAttr::BlocksAttrTypes type;
+  if (Attr.getParameterName()->isStr("byref"))
+    type = BlocksAttr::ByRef;
+  else {
+    S.Diag(Attr.getLoc(), diag::warn_attribute_type_not_supported)
+      << "blocks" << Attr.getParameterName();
+    return;
+  }
+
+  d->addAttr(::new (S.Context) BlocksAttr(type));
+}
+
+static void HandleSentinelAttr(Decl *d, const AttributeList &Attr, Sema &S) {
+  // check the attribute arguments.
+  if (Attr.getNumArgs() > 2) {
+    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments)
+      << "0, 1 or 2";
+    return;
+  }
+
+  int sentinel = 0;
+  if (Attr.getNumArgs() > 0) {
+    Expr *E = static_cast<Expr *>(Attr.getArg(0));
+    llvm::APSInt Idx(32);
+    if (!E->isIntegerConstantExpr(Idx, S.Context)) {
+      S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_int)
+       << "sentinel" << 1 << E->getSourceRange();
+      return;
+    }
+    sentinel = Idx.getZExtValue();
+
+    if (sentinel < 0) {
+      S.Diag(Attr.getLoc(), diag::err_attribute_sentinel_less_than_zero)
+        << E->getSourceRange();
+      return;
+    }
+  }
+
+  int nullPos = 0;
+  if (Attr.getNumArgs() > 1) {
+    Expr *E = static_cast<Expr *>(Attr.getArg(1));
+    llvm::APSInt Idx(32);
+    if (!E->isIntegerConstantExpr(Idx, S.Context)) {
+      S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_int)
+        << "sentinel" << 2 << E->getSourceRange();
+      return;
+    }
+    nullPos = Idx.getZExtValue();
+
+    if (nullPos > 1 || nullPos < 0) {
+      // FIXME: This error message could be improved, it would be nice
+      // to say what the bounds actually are.
+      S.Diag(Attr.getLoc(), diag::err_attribute_sentinel_not_zero_or_one)
+        << E->getSourceRange();
+      return;
+    }
+  }
+
+  if (FunctionDecl *FD = dyn_cast<FunctionDecl>(d)) {
+    const FunctionType *FT = FD->getType()->getAs<FunctionType>();
+    assert(FT && "FunctionDecl has non-function type?");
+
+    if (isa<FunctionNoProtoType>(FT)) {
+      S.Diag(Attr.getLoc(), diag::warn_attribute_sentinel_named_arguments);
+      return;
+    }
+
+    if (!cast<FunctionProtoType>(FT)->isVariadic()) {
+      S.Diag(Attr.getLoc(), diag::warn_attribute_sentinel_not_variadic) << 0;
+      return;
+    }
+  } else if (ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(d)) {
+    if (!MD->isVariadic()) {
+      S.Diag(Attr.getLoc(), diag::warn_attribute_sentinel_not_variadic) << 0;
+      return;
+    }
+  } else if (isa<BlockDecl>(d)) {
+    // Note! BlockDecl is typeless. Variadic diagnostics will be issued by the
+    // caller.
+    ;
+  } else if (const VarDecl *V = dyn_cast<VarDecl>(d)) {
+    QualType Ty = V->getType();
+    if (Ty->isBlockPointerType() || Ty->isFunctionPointerType()) {
+      const FunctionType *FT = Ty->isFunctionPointerType() ? getFunctionType(d)
+        : Ty->getAs<BlockPointerType>()->getPointeeType()->getAs<FunctionType>();
+      if (!cast<FunctionProtoType>(FT)->isVariadic()) {
+        int m = Ty->isFunctionPointerType() ? 0 : 1;
+        S.Diag(Attr.getLoc(), diag::warn_attribute_sentinel_not_variadic) << m;
+        return;
+      }
+    } else {
+      S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
+      << Attr.getName() << 6 /*function, method or block */;
+      return;
+    }
+  } else {
+    S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
+      << Attr.getName() << 6 /*function, method or block */;
+    return;
+  }
+  d->addAttr(::new (S.Context) SentinelAttr(sentinel, nullPos));
+}
+
+static void HandleWarnUnusedResult(Decl *D, const AttributeList &Attr, Sema &S) {
+  // check the attribute arguments.
+  if (Attr.getNumArgs() != 0) {
+    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
+    return;
+  }
+
+  if (!isFunctionOrMethod(D)) {
+    S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
+      << Attr.getName() << 0 /*function*/;
+    return;
+  }
+
+  if (getFunctionType(D)->getResultType()->isVoidType()) {
+    S.Diag(Attr.getLoc(), diag::warn_attribute_void_function)
+      << Attr.getName();
+    return;
+  }
+
+  D->addAttr(::new (S.Context) WarnUnusedResultAttr());
+}
+
+static void HandleWeakAttr(Decl *D, const AttributeList &Attr, Sema &S) {
+  // check the attribute arguments.
+  if (Attr.getNumArgs() != 0) {
+    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
+    return;
+  }
+
+  /* weak only applies to non-static declarations */
+  bool isStatic = false;
+  if (VarDecl *VD = dyn_cast<VarDecl>(D)) {
+    isStatic = VD->getStorageClass() == VarDecl::Static;
+  } else if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
+    isStatic = FD->getStorageClass() == FunctionDecl::Static;
+  }
+  if (isStatic) {
+    S.Diag(Attr.getLoc(), diag::err_attribute_weak_static) <<
+      dyn_cast<NamedDecl>(D)->getNameAsString();
+    return;
+  }
+
+  // TODO: could also be applied to methods?
+  if (!isa<FunctionDecl>(D) && !isa<VarDecl>(D)) {
+    S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
+      << Attr.getName() << 2 /*variable and function*/;
+    return;
+  }
+
+  D->addAttr(::new (S.Context) WeakAttr());
+}
+
+static void HandleWeakImportAttr(Decl *D, const AttributeList &Attr, Sema &S) {
+  // check the attribute arguments.
+  if (Attr.getNumArgs() != 0) {
+    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
+    return;
+  }
+
+  // weak_import only applies to variable & function declarations.
+  bool isDef = false;
+  if (VarDecl *VD = dyn_cast<VarDecl>(D)) {
+    isDef = (!VD->hasExternalStorage() || VD->getInit());
+  } else if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
+    isDef = FD->getBody();
+  } else if (isa<ObjCPropertyDecl>(D) || isa<ObjCMethodDecl>(D)) {
+    // We ignore weak import on properties and methods
+    return;
+  } else if (!(S.LangOpts.ObjCNonFragileABI && isa<ObjCInterfaceDecl>(D))) {
+    S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
+    << Attr.getName() << 2 /*variable and function*/;
+    return;
+  }
+
+  // Merge should handle any subsequent violations.
+  if (isDef) {
+    S.Diag(Attr.getLoc(),
+           diag::warn_attribute_weak_import_invalid_on_definition)
+      << "weak_import" << 2 /*variable and function*/;
+    return;
+  }
+
+  D->addAttr(::new (S.Context) WeakImportAttr());
+}
+
+static void HandleDLLImportAttr(Decl *D, const AttributeList &Attr, Sema &S) {
+  // check the attribute arguments.
+  if (Attr.getNumArgs() != 0) {
+    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
+    return;
+  }
+
+  // Attribute can be applied only to functions or variables.
+  if (isa<VarDecl>(D)) {
+    D->addAttr(::new (S.Context) DLLImportAttr());
+    return;
+  }
+
+  FunctionDecl *FD = dyn_cast<FunctionDecl>(D);
+  if (!FD) {
+    S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
+      << Attr.getName() << 2 /*variable and function*/;
+    return;
+  }
+
+  // Currently, the dllimport attribute is ignored for inlined functions.
+  // Warning is emitted.
+  if (FD->isInlineSpecified()) {
+    S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "dllimport";
+    return;
+  }
+
+  // The attribute is also overridden by a subsequent declaration as dllexport.
+  // Warning is emitted.
+  for (AttributeList *nextAttr = Attr.getNext(); nextAttr;
+       nextAttr = nextAttr->getNext()) {
+    if (nextAttr->getKind() == AttributeList::AT_dllexport) {
+      S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "dllimport";
+      return;
+    }
+  }
+
+  if (D->getAttr<DLLExportAttr>()) {
+    S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "dllimport";
+    return;
+  }
+
+  D->addAttr(::new (S.Context) DLLImportAttr());
+}
+
+static void HandleDLLExportAttr(Decl *D, const AttributeList &Attr, Sema &S) {
+  // check the attribute arguments.
+  if (Attr.getNumArgs() != 0) {
+    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
+    return;
+  }
+
+  // Attribute can be applied only to functions or variables.
+  if (isa<VarDecl>(D)) {
+    D->addAttr(::new (S.Context) DLLExportAttr());
+    return;
+  }
+
+  FunctionDecl *FD = dyn_cast<FunctionDecl>(D);
+  if (!FD) {
+    S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
+      << Attr.getName() << 2 /*variable and function*/;
+    return;
+  }
+
+  // Currently, the dllexport attribute is ignored for inlined functions, unless
+  // the -fkeep-inline-functions flag has been used. Warning is emitted;
+  if (FD->isInlineSpecified()) {
+    // FIXME: ... unless the -fkeep-inline-functions flag has been used.
+    S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "dllexport";
+    return;
+  }
+
+  D->addAttr(::new (S.Context) DLLExportAttr());
+}
+
+static void HandleReqdWorkGroupSize(Decl *D, const AttributeList &Attr,
+                                    Sema &S) {
+  // Attribute has 3 arguments.
+  if (Attr.getNumArgs() != 3) {
+    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
+    return;
+  }
+
+  unsigned WGSize[3];
+  for (unsigned i = 0; i < 3; ++i) {
+    Expr *E = static_cast<Expr *>(Attr.getArg(i));
+    llvm::APSInt ArgNum(32);
+    if (!E->isIntegerConstantExpr(ArgNum, S.Context)) {
+      S.Diag(Attr.getLoc(), diag::err_attribute_argument_not_int)
+        << "reqd_work_group_size" << E->getSourceRange();
+      return;
+    }
+    WGSize[i] = (unsigned) ArgNum.getZExtValue();
+  }
+  D->addAttr(::new (S.Context) ReqdWorkGroupSizeAttr(WGSize[0], WGSize[1],
+                                                     WGSize[2]));
+}
+
+static void HandleSectionAttr(Decl *D, const AttributeList &Attr, Sema &S) {
+  // Attribute has no arguments.
+  if (Attr.getNumArgs() != 1) {
+    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
+    return;
+  }
+
+  // Make sure that there is a string literal as the sections's single
+  // argument.
+  Expr *ArgExpr = static_cast<Expr *>(Attr.getArg(0));
+  StringLiteral *SE = dyn_cast<StringLiteral>(ArgExpr);
+  if (!SE) {
+    S.Diag(ArgExpr->getLocStart(), diag::err_attribute_not_string) << "section";
+    return;
+  }
+
+  // If the target wants to validate the section specifier, make it happen.
+  std::string Error = S.Context.Target.isValidSectionSpecifier(SE->getString());
+  if (!Error.empty()) {
+    S.Diag(SE->getLocStart(), diag::err_attribute_section_invalid_for_target)
+    << Error;
+    return;
+  }
+
+  // This attribute cannot be applied to local variables.
+  if (isa<VarDecl>(D) && cast<VarDecl>(D)->hasLocalStorage()) {
+    S.Diag(SE->getLocStart(), diag::err_attribute_section_local_variable);
+    return;
+  }
+  
+  D->addAttr(::new (S.Context) SectionAttr(SE->getString()));
+}
+
+
+static void HandleNothrowAttr(Decl *d, const AttributeList &Attr, Sema &S) {
+  // check the attribute arguments.
+  if (Attr.getNumArgs() != 0) {
+    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
+    return;
+  }
+
+  d->addAttr(::new (S.Context) NoThrowAttr());
+}
+
+static void HandleConstAttr(Decl *d, const AttributeList &Attr, Sema &S) {
+  // check the attribute arguments.
+  if (Attr.getNumArgs() != 0) {
+    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
+    return;
+  }
+
+  d->addAttr(::new (S.Context) ConstAttr());
+}
+
+static void HandlePureAttr(Decl *d, const AttributeList &Attr, Sema &S) {
+  // check the attribute arguments.
+  if (Attr.getNumArgs() != 0) {
+    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
+    return;
+  }
+
+  d->addAttr(::new (S.Context) PureAttr());
+}
+
+static void HandleCleanupAttr(Decl *d, const AttributeList &Attr, Sema &S) {
+  if (!Attr.getParameterName()) {
+    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
+    return;
+  }
+
+  if (Attr.getNumArgs() != 0) {
+    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
+    return;
+  }
+
+  VarDecl *VD = dyn_cast<VarDecl>(d);
+
+  if (!VD || !VD->hasLocalStorage()) {
+    S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "cleanup";
+    return;
+  }
+
+  // Look up the function
+  NamedDecl *CleanupDecl
+    = S.LookupSingleName(S.TUScope, Attr.getParameterName(),
+                         Sema::LookupOrdinaryName);
+  if (!CleanupDecl) {
+    S.Diag(Attr.getLoc(), diag::err_attribute_cleanup_arg_not_found) <<
+      Attr.getParameterName();
+    return;
+  }
+
+  FunctionDecl *FD = dyn_cast<FunctionDecl>(CleanupDecl);
+  if (!FD) {
+    S.Diag(Attr.getLoc(), diag::err_attribute_cleanup_arg_not_function) <<
+      Attr.getParameterName();
+    return;
+  }
+
+  if (FD->getNumParams() != 1) {
+    S.Diag(Attr.getLoc(), diag::err_attribute_cleanup_func_must_take_one_arg) <<
+      Attr.getParameterName();
+    return;
+  }
+
+  // We're currently more strict than GCC about what function types we accept.
+  // If this ever proves to be a problem it should be easy to fix.
+  QualType Ty = S.Context.getPointerType(VD->getType());
+  QualType ParamTy = FD->getParamDecl(0)->getType();
+  if (S.CheckAssignmentConstraints(ParamTy, Ty) != Sema::Compatible) {
+    S.Diag(Attr.getLoc(),
+           diag::err_attribute_cleanup_func_arg_incompatible_type) <<
+      Attr.getParameterName() << ParamTy << Ty;
+    return;
+  }
+
+  d->addAttr(::new (S.Context) CleanupAttr(FD));
+}
+
+/// Handle __attribute__((format_arg((idx)))) attribute based on
+/// http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html
+static void HandleFormatArgAttr(Decl *d, const AttributeList &Attr, Sema &S) {
+  if (Attr.getNumArgs() != 1) {
+    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
+    return;
+  }
+  if (!isFunctionOrMethod(d) || !hasFunctionProto(d)) {
+    S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
+    << Attr.getName() << 0 /*function*/;
+    return;
+  }
+  // FIXME: in C++ the implicit 'this' function parameter also counts.  this is
+  // needed in order to be compatible with GCC the index must start with 1.
+  unsigned NumArgs  = getFunctionOrMethodNumArgs(d);
+  unsigned FirstIdx = 1;
+  // checks for the 2nd argument
+  Expr *IdxExpr = static_cast<Expr *>(Attr.getArg(0));
+  llvm::APSInt Idx(32);
+  if (!IdxExpr->isIntegerConstantExpr(Idx, S.Context)) {
+    S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_int)
+    << "format" << 2 << IdxExpr->getSourceRange();
+    return;
+  }
+
+  if (Idx.getZExtValue() < FirstIdx || Idx.getZExtValue() > NumArgs) {
+    S.Diag(Attr.getLoc(), diag::err_attribute_argument_out_of_bounds)
+    << "format" << 2 << IdxExpr->getSourceRange();
+    return;
+  }
+
+  unsigned ArgIdx = Idx.getZExtValue() - 1;
+
+  // make sure the format string is really a string
+  QualType Ty = getFunctionOrMethodArgType(d, ArgIdx);
+
+  bool not_nsstring_type = !isNSStringType(Ty, S.Context);
+  if (not_nsstring_type &&
+      !isCFStringType(Ty, S.Context) &&
+      (!Ty->isPointerType() ||
+       !Ty->getAs<PointerType>()->getPointeeType()->isCharType())) {
+    // FIXME: Should highlight the actual expression that has the wrong type.
+    S.Diag(Attr.getLoc(), diag::err_format_attribute_not)
+    << (not_nsstring_type ? "a string type" : "an NSString")
+       << IdxExpr->getSourceRange();
+    return;
+  }
+  Ty = getFunctionOrMethodResultType(d);
+  if (!isNSStringType(Ty, S.Context) &&
+      !isCFStringType(Ty, S.Context) &&
+      (!Ty->isPointerType() ||
+       !Ty->getAs<PointerType>()->getPointeeType()->isCharType())) {
+    // FIXME: Should highlight the actual expression that has the wrong type.
+    S.Diag(Attr.getLoc(), diag::err_format_attribute_result_not)
+    << (not_nsstring_type ? "string type" : "NSString")
+       << IdxExpr->getSourceRange();
+    return;
+  }
+
+  d->addAttr(::new (S.Context) FormatArgAttr(Idx.getZExtValue()));
+}
+
+enum FormatAttrKind {
+  CFStringFormat,
+  NSStringFormat,
+  StrftimeFormat,
+  SupportedFormat,
+  InvalidFormat
+};
+
+/// getFormatAttrKind - Map from format attribute names to supported format
+/// types.
+static FormatAttrKind getFormatAttrKind(llvm::StringRef Format) {
+  // Check for formats that get handled specially.
+  if (Format == "NSString")
+    return NSStringFormat;
+  if (Format == "CFString")
+    return CFStringFormat;
+  if (Format == "strftime")
+    return StrftimeFormat;
+
+  // Otherwise, check for supported formats.
+  if (Format == "scanf" || Format == "printf" || Format == "printf0" ||
+      Format == "strfmon" || Format == "cmn_err" || Format == "strftime" ||
+      Format == "NSString" || Format == "CFString" || Format == "vcmn_err" ||
+      Format == "zcmn_err")
+    return SupportedFormat;
+
+  return InvalidFormat;
+}
+
+/// Handle __attribute__((format(type,idx,firstarg))) attributes based on
+/// http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html
+static void HandleFormatAttr(Decl *d, const AttributeList &Attr, Sema &S) {
+
+  if (!Attr.getParameterName()) {
+    S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_string)
+      << "format" << 1;
+    return;
+  }
+
+  if (Attr.getNumArgs() != 2) {
+    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 3;
+    return;
+  }
+
+  if (!isFunctionOrMethodOrBlock(d) || !hasFunctionProto(d)) {
+    S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
+      << Attr.getName() << 0 /*function*/;
+    return;
+  }
+
+  unsigned NumArgs  = getFunctionOrMethodNumArgs(d);
+  unsigned FirstIdx = 1;
+
+  llvm::StringRef Format = Attr.getParameterName()->getName();
+
+  // Normalize the argument, __foo__ becomes foo.
+  if (Format.startswith("__") && Format.endswith("__"))
+    Format = Format.substr(2, Format.size() - 4);
+
+  // Check for supported formats.
+  FormatAttrKind Kind = getFormatAttrKind(Format);
+  if (Kind == InvalidFormat) {
+    S.Diag(Attr.getLoc(), diag::warn_attribute_type_not_supported)
+      << "format" << Attr.getParameterName()->getName();
+    return;
+  }
+
+  // checks for the 2nd argument
+  Expr *IdxExpr = static_cast<Expr *>(Attr.getArg(0));
+  llvm::APSInt Idx(32);
+  if (!IdxExpr->isIntegerConstantExpr(Idx, S.Context)) {
+    S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_int)
+      << "format" << 2 << IdxExpr->getSourceRange();
+    return;
+  }
+
+  // FIXME: We should handle the implicit 'this' parameter in a more generic
+  // way that can be used for other arguments.
+  bool HasImplicitThisParam = false;
+  if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(d)) {
+    if (MD->isInstance()) {
+      HasImplicitThisParam = true;
+      NumArgs++;
+    }
+  }
+
+  if (Idx.getZExtValue() < FirstIdx || Idx.getZExtValue() > NumArgs) {
+    S.Diag(Attr.getLoc(), diag::err_attribute_argument_out_of_bounds)
+      << "format" << 2 << IdxExpr->getSourceRange();
+    return;
+  }
+
+  // FIXME: Do we need to bounds check?
+  unsigned ArgIdx = Idx.getZExtValue() - 1;
+
+  if (HasImplicitThisParam) {
+    if (ArgIdx == 0) {
+      S.Diag(Attr.getLoc(), diag::err_format_attribute_not)
+        << "a string type" << IdxExpr->getSourceRange();
+      return;
+    }
+    ArgIdx--;
+  }
+
+  // make sure the format string is really a string
+  QualType Ty = getFunctionOrMethodArgType(d, ArgIdx);
+
+  if (Kind == CFStringFormat) {
+    if (!isCFStringType(Ty, S.Context)) {
+      S.Diag(Attr.getLoc(), diag::err_format_attribute_not)
+        << "a CFString" << IdxExpr->getSourceRange();
+      return;
+    }
+  } else if (Kind == NSStringFormat) {
+    // FIXME: do we need to check if the type is NSString*?  What are the
+    // semantics?
+    if (!isNSStringType(Ty, S.Context)) {
+      // FIXME: Should highlight the actual expression that has the wrong type.
+      S.Diag(Attr.getLoc(), diag::err_format_attribute_not)
+        << "an NSString" << IdxExpr->getSourceRange();
+      return;
+    }
+  } else if (!Ty->isPointerType() ||
+             !Ty->getAs<PointerType>()->getPointeeType()->isCharType()) {
+    // FIXME: Should highlight the actual expression that has the wrong type.
+    S.Diag(Attr.getLoc(), diag::err_format_attribute_not)
+      << "a string type" << IdxExpr->getSourceRange();
+    return;
+  }
+
+  // check the 3rd argument
+  Expr *FirstArgExpr = static_cast<Expr *>(Attr.getArg(1));
+  llvm::APSInt FirstArg(32);
+  if (!FirstArgExpr->isIntegerConstantExpr(FirstArg, S.Context)) {
+    S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_int)
+      << "format" << 3 << FirstArgExpr->getSourceRange();
+    return;
+  }
+
+  // check if the function is variadic if the 3rd argument non-zero
+  if (FirstArg != 0) {
+    if (isFunctionOrMethodVariadic(d)) {
+      ++NumArgs; // +1 for ...
+    } else {
+      S.Diag(d->getLocation(), diag::err_format_attribute_requires_variadic);
+      return;
+    }
+  }
+
+  // strftime requires FirstArg to be 0 because it doesn't read from any
+  // variable the input is just the current time + the format string.
+  if (Kind == StrftimeFormat) {
+    if (FirstArg != 0) {
+      S.Diag(Attr.getLoc(), diag::err_format_strftime_third_parameter)
+        << FirstArgExpr->getSourceRange();
+      return;
+    }
+  // if 0 it disables parameter checking (to use with e.g. va_list)
+  } else if (FirstArg != 0 && FirstArg != NumArgs) {
+    S.Diag(Attr.getLoc(), diag::err_attribute_argument_out_of_bounds)
+      << "format" << 3 << FirstArgExpr->getSourceRange();
+    return;
+  }
+
+  d->addAttr(::new (S.Context) FormatAttr(Format, Idx.getZExtValue(),
+                                          FirstArg.getZExtValue()));
+}
+
+static void HandleTransparentUnionAttr(Decl *d, const AttributeList &Attr,
+                                       Sema &S) {
+  // check the attribute arguments.
+  if (Attr.getNumArgs() != 0) {
+    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
+    return;
+  }
+
+  // Try to find the underlying union declaration.
+  RecordDecl *RD = 0;
+  TypedefDecl *TD = dyn_cast<TypedefDecl>(d);
+  if (TD && TD->getUnderlyingType()->isUnionType())
+    RD = TD->getUnderlyingType()->getAsUnionType()->getDecl();
+  else
+    RD = dyn_cast<RecordDecl>(d);
+
+  if (!RD || !RD->isUnion()) {
+    S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
+      << Attr.getName() << 1 /*union*/;
+    return;
+  }
+
+  if (!RD->isDefinition()) {
+    S.Diag(Attr.getLoc(),
+        diag::warn_transparent_union_attribute_not_definition);
+    return;
+  }
+
+  RecordDecl::field_iterator Field = RD->field_begin(),
+                          FieldEnd = RD->field_end();
+  if (Field == FieldEnd) {
+    S.Diag(Attr.getLoc(), diag::warn_transparent_union_attribute_zero_fields);
+    return;
+  }
+
+  FieldDecl *FirstField = *Field;
+  QualType FirstType = FirstField->getType();
+  if (FirstType->isFloatingType() || FirstType->isVectorType()) {
+    S.Diag(FirstField->getLocation(),
+           diag::warn_transparent_union_attribute_floating);
+    return;
+  }
+
+  uint64_t FirstSize = S.Context.getTypeSize(FirstType);
+  uint64_t FirstAlign = S.Context.getTypeAlign(FirstType);
+  for (; Field != FieldEnd; ++Field) {
+    QualType FieldType = Field->getType();
+    if (S.Context.getTypeSize(FieldType) != FirstSize ||
+        S.Context.getTypeAlign(FieldType) != FirstAlign) {
+      // Warn if we drop the attribute.
+      bool isSize = S.Context.getTypeSize(FieldType) != FirstSize;
+      unsigned FieldBits = isSize? S.Context.getTypeSize(FieldType)
+                                 : S.Context.getTypeAlign(FieldType);
+      S.Diag(Field->getLocation(),
+          diag::warn_transparent_union_attribute_field_size_align)
+        << isSize << Field->getDeclName() << FieldBits;
+      unsigned FirstBits = isSize? FirstSize : FirstAlign;
+      S.Diag(FirstField->getLocation(),
+             diag::note_transparent_union_first_field_size_align)
+        << isSize << FirstBits;
+      return;
+    }
+  }
+
+  RD->addAttr(::new (S.Context) TransparentUnionAttr());
+}
+
+static void HandleAnnotateAttr(Decl *d, const AttributeList &Attr, Sema &S) {
+  // check the attribute arguments.
+  if (Attr.getNumArgs() != 1) {
+    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
+    return;
+  }
+  Expr *ArgExpr = static_cast<Expr *>(Attr.getArg(0));
+  StringLiteral *SE = dyn_cast<StringLiteral>(ArgExpr);
+
+  // Make sure that there is a string literal as the annotation's single
+  // argument.
+  if (!SE) {
+    S.Diag(ArgExpr->getLocStart(), diag::err_attribute_not_string) <<"annotate";
+    return;
+  }
+  d->addAttr(::new (S.Context) AnnotateAttr(SE->getString()));
+}
+
+static void HandleAlignedAttr(Decl *d, const AttributeList &Attr, Sema &S) {
+  // check the attribute arguments.
+  if (Attr.getNumArgs() > 1) {
+    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
+    return;
+  }
+  
+  //FIXME: The C++0x version of this attribute has more limited applicabilty
+  //       than GNU's, and should error out when it is used to specify a
+  //       weaker alignment, rather than being silently ignored.
+
+  unsigned Align = 0;
+  if (Attr.getNumArgs() == 0) {
+    // FIXME: This should be the target specific maximum alignment.
+    // (For now we just use 128 bits which is the maximum on X86).
+    Align = 128;
+    d->addAttr(::new (S.Context) AlignedAttr(Align));
+    return;
+  }
+
+  Expr *alignmentExpr = static_cast<Expr *>(Attr.getArg(0));
+  llvm::APSInt Alignment(32);
+  if (!alignmentExpr->isIntegerConstantExpr(Alignment, S.Context)) {
+    S.Diag(Attr.getLoc(), diag::err_attribute_argument_not_int)
+      << "aligned" << alignmentExpr->getSourceRange();
+    return;
+  }
+  if (!llvm::isPowerOf2_64(Alignment.getZExtValue())) {
+    S.Diag(Attr.getLoc(), diag::err_attribute_aligned_not_power_of_two)
+      << alignmentExpr->getSourceRange();
+    return;
+  }
+
+  d->addAttr(::new (S.Context) AlignedAttr(Alignment.getZExtValue() * 8));
+}
+
+/// HandleModeAttr - This attribute modifies the width of a decl with primitive
+/// type.
+///
+/// Despite what would be logical, the mode attribute is a decl attribute, not a
+/// type attribute: 'int ** __attribute((mode(HI))) *G;' tries to make 'G' be
+/// HImode, not an intermediate pointer.
+static void HandleModeAttr(Decl *D, const AttributeList &Attr, Sema &S) {
+  // This attribute isn't documented, but glibc uses it.  It changes
+  // the width of an int or unsigned int to the specified size.
+
+  // Check that there aren't any arguments
+  if (Attr.getNumArgs() != 0) {
+    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
+    return;
+  }
+
+  IdentifierInfo *Name = Attr.getParameterName();
+  if (!Name) {
+    S.Diag(Attr.getLoc(), diag::err_attribute_missing_parameter_name);
+    return;
+  }
+
+  llvm::StringRef Str = Attr.getParameterName()->getName();
+
+  // Normalize the attribute name, __foo__ becomes foo.
+  if (Str.startswith("__") && Str.endswith("__"))
+    Str = Str.substr(2, Str.size() - 4);
+
+  unsigned DestWidth = 0;
+  bool IntegerMode = true;
+  bool ComplexMode = false;
+  switch (Str.size()) {
+  case 2:
+    switch (Str[0]) {
+    case 'Q': DestWidth = 8; break;
+    case 'H': DestWidth = 16; break;
+    case 'S': DestWidth = 32; break;
+    case 'D': DestWidth = 64; break;
+    case 'X': DestWidth = 96; break;
+    case 'T': DestWidth = 128; break;
+    }
+    if (Str[1] == 'F') {
+      IntegerMode = false;
+    } else if (Str[1] == 'C') {
+      IntegerMode = false;
+      ComplexMode = true;
+    } else if (Str[1] != 'I') {
+      DestWidth = 0;
+    }
+    break;
+  case 4:
+    // FIXME: glibc uses 'word' to define register_t; this is narrower than a
+    // pointer on PIC16 and other embedded platforms.
+    if (Str == "word")
+      DestWidth = S.Context.Target.getPointerWidth(0);
+    else if (Str == "byte")
+      DestWidth = S.Context.Target.getCharWidth();
+    break;
+  case 7:
+    if (Str == "pointer")
+      DestWidth = S.Context.Target.getPointerWidth(0);
+    break;
+  }
+
+  QualType OldTy;
+  if (TypedefDecl *TD = dyn_cast<TypedefDecl>(D))
+    OldTy = TD->getUnderlyingType();
+  else if (ValueDecl *VD = dyn_cast<ValueDecl>(D))
+    OldTy = VD->getType();
+  else {
+    S.Diag(D->getLocation(), diag::err_attr_wrong_decl)
+      << "mode" << SourceRange(Attr.getLoc(), Attr.getLoc());
+    return;
+  }
+
+  if (!OldTy->getAs<BuiltinType>() && !OldTy->isComplexType())
+    S.Diag(Attr.getLoc(), diag::err_mode_not_primitive);
+  else if (IntegerMode) {
+    if (!OldTy->isIntegralType())
+      S.Diag(Attr.getLoc(), diag::err_mode_wrong_type);
+  } else if (ComplexMode) {
+    if (!OldTy->isComplexType())
+      S.Diag(Attr.getLoc(), diag::err_mode_wrong_type);
+  } else {
+    if (!OldTy->isFloatingType())
+      S.Diag(Attr.getLoc(), diag::err_mode_wrong_type);
+  }
+
+  // FIXME: Sync this with InitializePredefinedMacros; we need to match int8_t
+  // and friends, at least with glibc.
+  // FIXME: Make sure 32/64-bit integers don't get defined to types of the wrong
+  // width on unusual platforms.
+  // FIXME: Make sure floating-point mappings are accurate
+  // FIXME: Support XF and TF types
+  QualType NewTy;
+  switch (DestWidth) {
+  case 0:
+    S.Diag(Attr.getLoc(), diag::err_unknown_machine_mode) << Name;
+    return;
+  default:
+    S.Diag(Attr.getLoc(), diag::err_unsupported_machine_mode) << Name;
+    return;
+  case 8:
+    if (!IntegerMode) {
+      S.Diag(Attr.getLoc(), diag::err_unsupported_machine_mode) << Name;
+      return;
+    }
+    if (OldTy->isSignedIntegerType())
+      NewTy = S.Context.SignedCharTy;
+    else
+      NewTy = S.Context.UnsignedCharTy;
+    break;
+  case 16:
+    if (!IntegerMode) {
+      S.Diag(Attr.getLoc(), diag::err_unsupported_machine_mode) << Name;
+      return;
+    }
+    if (OldTy->isSignedIntegerType())
+      NewTy = S.Context.ShortTy;
+    else
+      NewTy = S.Context.UnsignedShortTy;
+    break;
+  case 32:
+    if (!IntegerMode)
+      NewTy = S.Context.FloatTy;
+    else if (OldTy->isSignedIntegerType())
+      NewTy = S.Context.IntTy;
+    else
+      NewTy = S.Context.UnsignedIntTy;
+    break;
+  case 64:
+    if (!IntegerMode)
+      NewTy = S.Context.DoubleTy;
+    else if (OldTy->isSignedIntegerType())
+      if (S.Context.Target.getLongWidth() == 64)
+        NewTy = S.Context.LongTy;
+      else
+        NewTy = S.Context.LongLongTy;
+    else
+      if (S.Context.Target.getLongWidth() == 64)
+        NewTy = S.Context.UnsignedLongTy;
+      else
+        NewTy = S.Context.UnsignedLongLongTy;
+    break;
+  case 96:
+    NewTy = S.Context.LongDoubleTy;
+    break;
+  case 128:
+    if (!IntegerMode) {
+      S.Diag(Attr.getLoc(), diag::err_unsupported_machine_mode) << Name;
+      return;
+    }
+    if (OldTy->isSignedIntegerType())
+      NewTy = S.Context.Int128Ty;
+    else
+      NewTy = S.Context.UnsignedInt128Ty;
+    break;
+  }
+
+  if (ComplexMode) {
+    NewTy = S.Context.getComplexType(NewTy);
+  }
+
+  // Install the new type.
+  if (TypedefDecl *TD = dyn_cast<TypedefDecl>(D)) {
+    // FIXME: preserve existing source info.
+    TD->setTypeSourceInfo(S.Context.getTrivialTypeSourceInfo(NewTy));
+  } else
+    cast<ValueDecl>(D)->setType(NewTy);
+}
+
+static void HandleNoDebugAttr(Decl *d, const AttributeList &Attr, Sema &S) {
+  // check the attribute arguments.
+  if (Attr.getNumArgs() > 0) {
+    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
+    return;
+  }
+
+  if (!isFunctionOrMethod(d)) {
+    S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
+      << Attr.getName() << 0 /*function*/;
+    return;
+  }
+
+  d->addAttr(::new (S.Context) NoDebugAttr());
+}
+
+static void HandleNoInlineAttr(Decl *d, const AttributeList &Attr, Sema &S) {
+  // check the attribute arguments.
+  if (Attr.getNumArgs() != 0) {
+    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
+    return;
+  }
+
+  if (!isa<FunctionDecl>(d)) {
+    S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
+    << Attr.getName() << 0 /*function*/;
+    return;
+  }
+
+  d->addAttr(::new (S.Context) NoInlineAttr());
+}
+
+static void HandleGNUInlineAttr(Decl *d, const AttributeList &Attr, Sema &S) {
+  // check the attribute arguments.
+  if (Attr.getNumArgs() != 0) {
+    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
+    return;
+  }
+
+  FunctionDecl *Fn = dyn_cast<FunctionDecl>(d);
+  if (Fn == 0) {
+    S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
+      << Attr.getName() << 0 /*function*/;
+    return;
+  }
+
+  if (!Fn->isInlineSpecified()) {
+    S.Diag(Attr.getLoc(), diag::warn_gnu_inline_attribute_requires_inline);
+    return;
+  }
+
+  d->addAttr(::new (S.Context) GNUInlineAttr());
+}
+
+static void HandleRegparmAttr(Decl *d, const AttributeList &Attr, Sema &S) {
+  // check the attribute arguments.
+  if (Attr.getNumArgs() != 1) {
+    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
+    return;
+  }
+
+  if (!isFunctionOrMethod(d)) {
+    S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
+    << Attr.getName() << 0 /*function*/;
+    return;
+  }
+
+  Expr *NumParamsExpr = static_cast<Expr *>(Attr.getArg(0));
+  llvm::APSInt NumParams(32);
+  if (!NumParamsExpr->isIntegerConstantExpr(NumParams, S.Context)) {
+    S.Diag(Attr.getLoc(), diag::err_attribute_argument_not_int)
+      << "regparm" << NumParamsExpr->getSourceRange();
+    return;
+  }
+
+  if (S.Context.Target.getRegParmMax() == 0) {
+    S.Diag(Attr.getLoc(), diag::err_attribute_regparm_wrong_platform)
+      << NumParamsExpr->getSourceRange();
+    return;
+  }
+
+  if (NumParams.getLimitedValue(255) > S.Context.Target.getRegParmMax()) {
+    S.Diag(Attr.getLoc(), diag::err_attribute_regparm_invalid_number)
+      << S.Context.Target.getRegParmMax() << NumParamsExpr->getSourceRange();
+    return;
+  }
+
+  d->addAttr(::new (S.Context) RegparmAttr(NumParams.getZExtValue()));
+}
+
+static void HandleFinalAttr(Decl *d, const AttributeList &Attr, Sema &S) {
+  // check the attribute arguments.
+  if (Attr.getNumArgs() != 0) {
+    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
+    return;
+  }
+
+  if (!isa<CXXRecordDecl>(d)
+   && (!isa<CXXMethodDecl>(d) || !cast<CXXMethodDecl>(d)->isVirtual())) {
+    S.Diag(Attr.getLoc(),
+           Attr.isCXX0XAttribute() ? diag::err_attribute_wrong_decl_type
+                                   : diag::warn_attribute_wrong_decl_type)
+      << Attr.getName() << 7 /*virtual method or class*/;
+    return;
+  }
+  
+  // FIXME: Conform to C++0x redeclaration rules.
+  
+  if (d->getAttr<FinalAttr>()) {
+    S.Diag(Attr.getLoc(), diag::err_repeat_attribute) << "final";
+    return;
+  }
+
+  d->addAttr(::new (S.Context) FinalAttr());
+}
+
+//===----------------------------------------------------------------------===//
+// C++0x member checking attributes
+//===----------------------------------------------------------------------===//
+
+static void HandleBaseCheckAttr(Decl *d, const AttributeList &Attr, Sema &S) {
+  if (Attr.getNumArgs() != 0) {
+    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
+    return;
+  }
+  
+  if (!isa<CXXRecordDecl>(d)) {
+    S.Diag(Attr.getLoc(),
+           Attr.isCXX0XAttribute() ? diag::err_attribute_wrong_decl_type
+                                   : diag::warn_attribute_wrong_decl_type)
+      << Attr.getName() << 9 /*class*/;
+    return;
+  }
+  
+  if (d->getAttr<BaseCheckAttr>()) {
+    S.Diag(Attr.getLoc(), diag::err_repeat_attribute) << "base_check";
+    return;
+  }
+  
+  d->addAttr(::new (S.Context) BaseCheckAttr());
+}
+
+static void HandleHidingAttr(Decl *d, const AttributeList &Attr, Sema &S) {
+  if (Attr.getNumArgs() != 0) {
+    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
+    return;
+  }
+
+  if (!isa<RecordDecl>(d->getDeclContext())) {
+    // FIXME: It's not the type that's the problem
+    S.Diag(Attr.getLoc(),
+           Attr.isCXX0XAttribute() ? diag::err_attribute_wrong_decl_type
+                                   : diag::warn_attribute_wrong_decl_type)
+      << Attr.getName() << 11 /*member*/;
+    return;
+  }
+
+  // FIXME: Conform to C++0x redeclaration rules.
+
+  if (d->getAttr<HidingAttr>()) {
+    S.Diag(Attr.getLoc(), diag::err_repeat_attribute) << "hiding";
+    return;
+  }
+
+  d->addAttr(::new (S.Context) HidingAttr());
+}
+
+static void HandleOverrideAttr(Decl *d, const AttributeList &Attr, Sema &S) {
+  if (Attr.getNumArgs() != 0) {
+    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
+    return;
+  }
+
+  if (!isa<CXXMethodDecl>(d) || !cast<CXXMethodDecl>(d)->isVirtual()) {
+    // FIXME: It's not the type that's the problem
+    S.Diag(Attr.getLoc(),
+           Attr.isCXX0XAttribute() ? diag::err_attribute_wrong_decl_type
+                                   : diag::warn_attribute_wrong_decl_type)
+      << Attr.getName() << 10 /*virtual method*/;
+    return;
+  }
+
+  // FIXME: Conform to C++0x redeclaration rules.
+
+  if (d->getAttr<OverrideAttr>()) {
+    S.Diag(Attr.getLoc(), diag::err_repeat_attribute) << "override";
+    return;
+  }
+
+  d->addAttr(::new (S.Context) OverrideAttr());
+}
+
+//===----------------------------------------------------------------------===//
+// Checker-specific attribute handlers.
+//===----------------------------------------------------------------------===//
+
+static void HandleNSReturnsRetainedAttr(Decl *d, const AttributeList &Attr,
+                                        Sema &S) {
+
+  QualType RetTy;
+
+  if (ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(d))
+    RetTy = MD->getResultType();
+  else if (FunctionDecl *FD = dyn_cast<FunctionDecl>(d))
+    RetTy = FD->getResultType();
+  else {
+    SourceLocation L = Attr.getLoc();
+    S.Diag(d->getLocStart(), diag::warn_attribute_wrong_decl_type)
+        << SourceRange(L, L) << Attr.getName() << 3 /* function or method */;
+    return;
+  }
+
+  if (!(S.Context.isObjCNSObjectType(RetTy) || RetTy->getAs<PointerType>()
+        || RetTy->getAs<ObjCObjectPointerType>())) {
+    SourceLocation L = Attr.getLoc();
+    S.Diag(d->getLocStart(), diag::warn_ns_attribute_wrong_return_type)
+      << SourceRange(L, L) << Attr.getName();
+    return;
+  }
+
+  switch (Attr.getKind()) {
+    default:
+      assert(0 && "invalid ownership attribute");
+      return;
+    case AttributeList::AT_cf_returns_retained:
+      d->addAttr(::new (S.Context) CFReturnsRetainedAttr());
+      return;
+    case AttributeList::AT_ns_returns_retained:
+      d->addAttr(::new (S.Context) NSReturnsRetainedAttr());
+      return;
+  };
+}
+
+//===----------------------------------------------------------------------===//
+// Top Level Sema Entry Points
+//===----------------------------------------------------------------------===//
+
+/// ProcessDeclAttribute - Apply the specific attribute to the specified decl if
+/// the attribute applies to decls.  If the attribute is a type attribute, just
+/// silently ignore it if a GNU attribute. FIXME: Applying a C++0x attribute to
+/// the wrong thing is illegal (C++0x [dcl.attr.grammar]/4).
+static void ProcessDeclAttribute(Scope *scope, Decl *D,
+                                 const AttributeList &Attr, Sema &S) {
+  if (Attr.isDeclspecAttribute())
+    // FIXME: Try to deal with __declspec attributes!
+    return;
+  switch (Attr.getKind()) {
+  case AttributeList::AT_IBOutlet:    HandleIBOutletAttr  (D, Attr, S); break;
+  case AttributeList::AT_address_space:
+  case AttributeList::AT_objc_gc:
+  case AttributeList::AT_vector_size:
+    // Ignore these, these are type attributes, handled by
+    // ProcessTypeAttributes.
+    break;
+  case AttributeList::AT_alias:       HandleAliasAttr       (D, Attr, S); break;
+  case AttributeList::AT_aligned:     HandleAlignedAttr     (D, Attr, S); break;
+  case AttributeList::AT_always_inline:
+    HandleAlwaysInlineAttr  (D, Attr, S); break;
+  case AttributeList::AT_analyzer_noreturn:
+    HandleAnalyzerNoReturnAttr  (D, Attr, S); break;
+  case AttributeList::AT_annotate:    HandleAnnotateAttr    (D, Attr, S); break;
+  case AttributeList::AT_base_check:  HandleBaseCheckAttr   (D, Attr, S); break;
+  case AttributeList::AT_carries_dependency:
+                                      HandleDependencyAttr  (D, Attr, S); break;
+  case AttributeList::AT_constructor: HandleConstructorAttr (D, Attr, S); break;
+  case AttributeList::AT_deprecated:  HandleDeprecatedAttr  (D, Attr, S); break;
+  case AttributeList::AT_destructor:  HandleDestructorAttr  (D, Attr, S); break;
+  case AttributeList::AT_dllexport:   HandleDLLExportAttr   (D, Attr, S); break;
+  case AttributeList::AT_dllimport:   HandleDLLImportAttr   (D, Attr, S); break;
+  case AttributeList::AT_ext_vector_type:
+    HandleExtVectorTypeAttr(scope, D, Attr, S);
+    break;
+  case AttributeList::AT_final:       HandleFinalAttr       (D, Attr, S); break;
+  case AttributeList::AT_format:      HandleFormatAttr      (D, Attr, S); break;
+  case AttributeList::AT_format_arg:  HandleFormatArgAttr   (D, Attr, S); break;
+  case AttributeList::AT_gnu_inline:  HandleGNUInlineAttr   (D, Attr, S); break;
+  case AttributeList::AT_hiding:      HandleHidingAttr      (D, Attr, S); break;
+  case AttributeList::AT_mode:        HandleModeAttr        (D, Attr, S); break;
+  case AttributeList::AT_malloc:      HandleMallocAttr      (D, Attr, S); break;
+  case AttributeList::AT_nonnull:     HandleNonNullAttr     (D, Attr, S); break;
+  case AttributeList::AT_noreturn:    HandleNoReturnAttr    (D, Attr, S); break;
+  case AttributeList::AT_nothrow:     HandleNothrowAttr     (D, Attr, S); break;
+  case AttributeList::AT_override:    HandleOverrideAttr    (D, Attr, S); break;
+
+  // Checker-specific.
+  case AttributeList::AT_ns_returns_retained:
+  case AttributeList::AT_cf_returns_retained:
+    HandleNSReturnsRetainedAttr(D, Attr, S); break;
+
+  case AttributeList::AT_reqd_wg_size:
+    HandleReqdWorkGroupSize(D, Attr, S); break;
+
+  case AttributeList::AT_packed:      HandlePackedAttr      (D, Attr, S); break;
+  case AttributeList::AT_section:     HandleSectionAttr     (D, Attr, S); break;
+  case AttributeList::AT_unavailable: HandleUnavailableAttr (D, Attr, S); break;
+  case AttributeList::AT_unused:      HandleUnusedAttr      (D, Attr, S); break;
+  case AttributeList::AT_used:        HandleUsedAttr        (D, Attr, S); break;
+  case AttributeList::AT_visibility:  HandleVisibilityAttr  (D, Attr, S); break;
+  case AttributeList::AT_warn_unused_result: HandleWarnUnusedResult(D,Attr,S);
+    break;
+  case AttributeList::AT_weak:        HandleWeakAttr        (D, Attr, S); break;
+  case AttributeList::AT_weak_import: HandleWeakImportAttr  (D, Attr, S); break;
+  case AttributeList::AT_transparent_union:
+    HandleTransparentUnionAttr(D, Attr, S);
+    break;
+  case AttributeList::AT_objc_exception:
+    HandleObjCExceptionAttr(D, Attr, S);
+    break;
+  case AttributeList::AT_overloadable:HandleOverloadableAttr(D, Attr, S); break;
+  case AttributeList::AT_nsobject:    HandleObjCNSObject    (D, Attr, S); break;
+  case AttributeList::AT_blocks:      HandleBlocksAttr      (D, Attr, S); break;
+  case AttributeList::AT_sentinel:    HandleSentinelAttr    (D, Attr, S); break;
+  case AttributeList::AT_const:       HandleConstAttr       (D, Attr, S); break;
+  case AttributeList::AT_pure:        HandlePureAttr        (D, Attr, S); break;
+  case AttributeList::AT_cleanup:     HandleCleanupAttr     (D, Attr, S); break;
+  case AttributeList::AT_nodebug:     HandleNoDebugAttr     (D, Attr, S); break;
+  case AttributeList::AT_noinline:    HandleNoInlineAttr    (D, Attr, S); break;
+  case AttributeList::AT_regparm:     HandleRegparmAttr     (D, Attr, S); break;
+  case AttributeList::IgnoredAttribute:
+  case AttributeList::AT_no_instrument_function:  // Interacts with -pg.
+    // Just ignore
+    break;
+  case AttributeList::AT_stdcall:
+  case AttributeList::AT_cdecl:
+  case AttributeList::AT_fastcall:
+    // These are all treated as type attributes.
+    break;
+  default:
+    // Ask target about the attribute.
+    const TargetAttributesSema &TargetAttrs = S.getTargetAttributesSema();
+    if (!TargetAttrs.ProcessDeclAttribute(scope, D, Attr, S))
+      S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName();
+    break;
+  }
+}
+
+/// ProcessDeclAttributeList - Apply all the decl attributes in the specified
+/// attribute list to the specified decl, ignoring any type attributes.
+void Sema::ProcessDeclAttributeList(Scope *S, Decl *D, const AttributeList *AttrList) {
+  while (AttrList) {
+    ProcessDeclAttribute(S, D, *AttrList, *this);
+    AttrList = AttrList->getNext();
+  }
+}
+
+/// DeclClonePragmaWeak - clone existing decl (maybe definition),
+/// #pragma weak needs a non-definition decl and source may not have one
+NamedDecl * Sema::DeclClonePragmaWeak(NamedDecl *ND, IdentifierInfo *II) {
+  assert(isa<FunctionDecl>(ND) || isa<VarDecl>(ND));
+  NamedDecl *NewD = 0;
+  if (FunctionDecl *FD = dyn_cast<FunctionDecl>(ND)) {
+    NewD = FunctionDecl::Create(FD->getASTContext(), FD->getDeclContext(),
+                                FD->getLocation(), DeclarationName(II),
+                                FD->getType(), FD->getTypeSourceInfo());
+  } else if (VarDecl *VD = dyn_cast<VarDecl>(ND)) {
+    NewD = VarDecl::Create(VD->getASTContext(), VD->getDeclContext(),
+                           VD->getLocation(), II,
+                           VD->getType(), VD->getTypeSourceInfo(),
+                           VD->getStorageClass());
+  }
+  return NewD;
+}
+
+/// DeclApplyPragmaWeak - A declaration (maybe definition) needs #pragma weak
+/// applied to it, possibly with an alias.
+void Sema::DeclApplyPragmaWeak(Scope *S, NamedDecl *ND, WeakInfo &W) {
+  if (W.getUsed()) return; // only do this once
+  W.setUsed(true);
+  if (W.getAlias()) { // clone decl, impersonate __attribute(weak,alias(...))
+    IdentifierInfo *NDId = ND->getIdentifier();
+    NamedDecl *NewD = DeclClonePragmaWeak(ND, W.getAlias());
+    NewD->addAttr(::new (Context) AliasAttr(NDId->getName()));
+    NewD->addAttr(::new (Context) WeakAttr());
+    WeakTopLevelDecl.push_back(NewD);
+    // FIXME: "hideous" code from Sema::LazilyCreateBuiltin
+    // to insert Decl at TU scope, sorry.
+    DeclContext *SavedContext = CurContext;
+    CurContext = Context.getTranslationUnitDecl();
+    PushOnScopeChains(NewD, S);
+    CurContext = SavedContext;
+  } else { // just add weak to existing
+    ND->addAttr(::new (Context) WeakAttr());
+  }
+}
+
+/// ProcessDeclAttributes - Given a declarator (PD) with attributes indicated in
+/// it, apply them to D.  This is a bit tricky because PD can have attributes
+/// specified in many different places, and we need to find and apply them all.
+void Sema::ProcessDeclAttributes(Scope *S, Decl *D, const Declarator &PD) {
+  // Handle #pragma weak
+  if (NamedDecl *ND = dyn_cast<NamedDecl>(D)) {
+    if (ND->hasLinkage()) {
+      WeakInfo W = WeakUndeclaredIdentifiers.lookup(ND->getIdentifier());
+      if (W != WeakInfo()) {
+        // Identifier referenced by #pragma weak before it was declared
+        DeclApplyPragmaWeak(S, ND, W);
+        WeakUndeclaredIdentifiers[ND->getIdentifier()] = W;
+      }
+    }
+  }
+
+  // Apply decl attributes from the DeclSpec if present.
+  if (const AttributeList *Attrs = PD.getDeclSpec().getAttributes())
+    ProcessDeclAttributeList(S, D, Attrs);
+
+  // Walk the declarator structure, applying decl attributes that were in a type
+  // position to the decl itself.  This handles cases like:
+  //   int *__attr__(x)** D;
+  // when X is a decl attribute.
+  for (unsigned i = 0, e = PD.getNumTypeObjects(); i != e; ++i)
+    if (const AttributeList *Attrs = PD.getTypeObject(i).getAttrs())
+      ProcessDeclAttributeList(S, D, Attrs);
+
+  // Finally, apply any attributes on the decl itself.
+  if (const AttributeList *Attrs = PD.getAttributes())
+    ProcessDeclAttributeList(S, D, Attrs);
+}
+
+/// PushParsingDeclaration - Enter a new "scope" of deprecation
+/// warnings.
+///
+/// The state token we use is the start index of this scope
+/// on the warning stack.
+Action::ParsingDeclStackState Sema::PushParsingDeclaration() {
+  ParsingDeclDepth++;
+  return (ParsingDeclStackState) DelayedDiagnostics.size();
+}
+
+void Sema::PopParsingDeclaration(ParsingDeclStackState S, DeclPtrTy Ctx) {
+  assert(ParsingDeclDepth > 0 && "empty ParsingDeclaration stack");
+  ParsingDeclDepth--;
+
+  if (DelayedDiagnostics.empty())
+    return;
+
+  unsigned SavedIndex = (unsigned) S;
+  assert(SavedIndex <= DelayedDiagnostics.size() &&
+         "saved index is out of bounds");
+
+  // We only want to actually emit delayed diagnostics when we
+  // successfully parsed a decl.
+  Decl *D = Ctx ? Ctx.getAs<Decl>() : 0;
+  if (D) {
+    // We really do want to start with 0 here.  We get one push for a
+    // decl spec and another for each declarator;  in a decl group like:
+    //   deprecated_typedef foo, *bar, baz();
+    // only the declarator pops will be passed decls.  This is correct;
+    // we really do need to consider delayed diagnostics from the decl spec
+    // for each of the different declarations.
+    for (unsigned I = 0, E = DelayedDiagnostics.size(); I != E; ++I) {
+      if (DelayedDiagnostics[I].Triggered)
+        continue;
+
+      switch (DelayedDiagnostics[I].Kind) {
+      case DelayedDiagnostic::Deprecation:
+        HandleDelayedDeprecationCheck(DelayedDiagnostics[I], D);
+        break;
+
+      case DelayedDiagnostic::Access:
+        HandleDelayedAccessCheck(DelayedDiagnostics[I], D);
+        break;
+      }
+    }
+  }
+
+  DelayedDiagnostics.set_size(SavedIndex);
+}
+
+static bool isDeclDeprecated(Decl *D) {
+  do {
+    if (D->hasAttr<DeprecatedAttr>())
+      return true;
+  } while ((D = cast_or_null<Decl>(D->getDeclContext())));
+  return false;
+}
+
+void Sema::HandleDelayedDeprecationCheck(Sema::DelayedDiagnostic &DD,
+                                         Decl *Ctx) {
+  if (isDeclDeprecated(Ctx))
+    return;
+
+  DD.Triggered = true;
+  Diag(DD.Loc, diag::warn_deprecated)
+    << DD.DeprecationData.Decl->getDeclName();
+}
+
+void Sema::EmitDeprecationWarning(NamedDecl *D, SourceLocation Loc) {
+  // Delay if we're currently parsing a declaration.
+  if (ParsingDeclDepth) {
+    DelayedDiagnostics.push_back(DelayedDiagnostic::makeDeprecation(Loc, D));
+    return;
+  }
+
+  // Otherwise, don't warn if our current context is deprecated.
+  if (isDeclDeprecated(cast<Decl>(CurContext)))
+    return;
+
+  Diag(Loc, diag::warn_deprecated) << D->getDeclName();
+}
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
new file mode 100644
index 0000000..b42a27c
--- /dev/null
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -0,0 +1,5842 @@
+//===------ SemaDeclCXX.cpp - Semantic Analysis for C++ Declarations ------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+//  This file implements semantic analysis for C++ declarations.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Sema.h"
+#include "SemaInit.h"
+#include "Lookup.h"
+#include "clang/AST/ASTConsumer.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/RecordLayout.h"
+#include "clang/AST/CXXInheritance.h"
+#include "clang/AST/DeclVisitor.h"
+#include "clang/AST/TypeLoc.h"
+#include "clang/AST/TypeOrdering.h"
+#include "clang/AST/StmtVisitor.h"
+#include "clang/Parse/DeclSpec.h"
+#include "clang/Parse/Template.h"
+#include "clang/Basic/PartialDiagnostic.h"
+#include "clang/Lex/Preprocessor.h"
+#include "llvm/ADT/STLExtras.h"
+#include <map>
+#include <set>
+
+using namespace clang;
+
+//===----------------------------------------------------------------------===//
+// CheckDefaultArgumentVisitor
+//===----------------------------------------------------------------------===//
+
+namespace {
+  /// CheckDefaultArgumentVisitor - C++ [dcl.fct.default] Traverses
+  /// the default argument of a parameter to determine whether it
+  /// contains any ill-formed subexpressions. For example, this will
+  /// diagnose the use of local variables or parameters within the
+  /// default argument expression.
+  class CheckDefaultArgumentVisitor
+    : public StmtVisitor<CheckDefaultArgumentVisitor, bool> {
+    Expr *DefaultArg;
+    Sema *S;
+
+  public:
+    CheckDefaultArgumentVisitor(Expr *defarg, Sema *s)
+      : DefaultArg(defarg), S(s) {}
+
+    bool VisitExpr(Expr *Node);
+    bool VisitDeclRefExpr(DeclRefExpr *DRE);
+    bool VisitCXXThisExpr(CXXThisExpr *ThisE);
+  };
+
+  /// VisitExpr - Visit all of the children of this expression.
+  bool CheckDefaultArgumentVisitor::VisitExpr(Expr *Node) {
+    bool IsInvalid = false;
+    for (Stmt::child_iterator I = Node->child_begin(),
+         E = Node->child_end(); I != E; ++I)
+      IsInvalid |= Visit(*I);
+    return IsInvalid;
+  }
+
+  /// VisitDeclRefExpr - Visit a reference to a declaration, to
+  /// determine whether this declaration can be used in the default
+  /// argument expression.
+  bool CheckDefaultArgumentVisitor::VisitDeclRefExpr(DeclRefExpr *DRE) {
+    NamedDecl *Decl = DRE->getDecl();
+    if (ParmVarDecl *Param = dyn_cast<ParmVarDecl>(Decl)) {
+      // C++ [dcl.fct.default]p9
+      //   Default arguments are evaluated each time the function is
+      //   called. The order of evaluation of function arguments is
+      //   unspecified. Consequently, parameters of a function shall not
+      //   be used in default argument expressions, even if they are not
+      //   evaluated. Parameters of a function declared before a default
+      //   argument expression are in scope and can hide namespace and
+      //   class member names.
+      return S->Diag(DRE->getSourceRange().getBegin(),
+                     diag::err_param_default_argument_references_param)
+         << Param->getDeclName() << DefaultArg->getSourceRange();
+    } else if (VarDecl *VDecl = dyn_cast<VarDecl>(Decl)) {
+      // C++ [dcl.fct.default]p7
+      //   Local variables shall not be used in default argument
+      //   expressions.
+      if (VDecl->isBlockVarDecl())
+        return S->Diag(DRE->getSourceRange().getBegin(),
+                       diag::err_param_default_argument_references_local)
+          << VDecl->getDeclName() << DefaultArg->getSourceRange();
+    }
+
+    return false;
+  }
+
+  /// VisitCXXThisExpr - Visit a C++ "this" expression.
+  bool CheckDefaultArgumentVisitor::VisitCXXThisExpr(CXXThisExpr *ThisE) {
+    // C++ [dcl.fct.default]p8:
+    //   The keyword this shall not be used in a default argument of a
+    //   member function.
+    return S->Diag(ThisE->getSourceRange().getBegin(),
+                   diag::err_param_default_argument_references_this)
+               << ThisE->getSourceRange();
+  }
+}
+
+bool
+Sema::SetParamDefaultArgument(ParmVarDecl *Param, ExprArg DefaultArg,
+                              SourceLocation EqualLoc) {
+  if (RequireCompleteType(Param->getLocation(), Param->getType(),
+                          diag::err_typecheck_decl_incomplete_type)) {
+    Param->setInvalidDecl();
+    return true;
+  }
+
+  Expr *Arg = (Expr *)DefaultArg.get();
+
+  // C++ [dcl.fct.default]p5
+  //   A default argument expression is implicitly converted (clause
+  //   4) to the parameter type. The default argument expression has
+  //   the same semantic constraints as the initializer expression in
+  //   a declaration of a variable of the parameter type, using the
+  //   copy-initialization semantics (8.5).
+  InitializedEntity Entity = InitializedEntity::InitializeParameter(Param);
+  InitializationKind Kind = InitializationKind::CreateCopy(Param->getLocation(),
+                                                           EqualLoc);
+  InitializationSequence InitSeq(*this, Entity, Kind, &Arg, 1);
+  OwningExprResult Result = InitSeq.Perform(*this, Entity, Kind,
+                                          MultiExprArg(*this, (void**)&Arg, 1));
+  if (Result.isInvalid())
+    return true;
+  Arg = Result.takeAs<Expr>();
+
+  Arg = MaybeCreateCXXExprWithTemporaries(Arg);
+
+  // Okay: add the default argument to the parameter
+  Param->setDefaultArg(Arg);
+
+  DefaultArg.release();
+
+  return false;
+}
+
+/// ActOnParamDefaultArgument - Check whether the default argument
+/// provided for a function parameter is well-formed. If so, attach it
+/// to the parameter declaration.
+void
+Sema::ActOnParamDefaultArgument(DeclPtrTy param, SourceLocation EqualLoc,
+                                ExprArg defarg) {
+  if (!param || !defarg.get())
+    return;
+
+  ParmVarDecl *Param = cast<ParmVarDecl>(param.getAs<Decl>());
+  UnparsedDefaultArgLocs.erase(Param);
+
+  ExprOwningPtr<Expr> DefaultArg(this, defarg.takeAs<Expr>());
+
+  // Default arguments are only permitted in C++
+  if (!getLangOptions().CPlusPlus) {
+    Diag(EqualLoc, diag::err_param_default_argument)
+      << DefaultArg->getSourceRange();
+    Param->setInvalidDecl();
+    return;
+  }
+
+  // Check that the default argument is well-formed
+  CheckDefaultArgumentVisitor DefaultArgChecker(DefaultArg.get(), this);
+  if (DefaultArgChecker.Visit(DefaultArg.get())) {
+    Param->setInvalidDecl();
+    return;
+  }
+
+  SetParamDefaultArgument(Param, move(DefaultArg), EqualLoc);
+}
+
+/// ActOnParamUnparsedDefaultArgument - We've seen a default
+/// argument for a function parameter, but we can't parse it yet
+/// because we're inside a class definition. Note that this default
+/// argument will be parsed later.
+void Sema::ActOnParamUnparsedDefaultArgument(DeclPtrTy param,
+                                             SourceLocation EqualLoc,
+                                             SourceLocation ArgLoc) {
+  if (!param)
+    return;
+
+  ParmVarDecl *Param = cast<ParmVarDecl>(param.getAs<Decl>());
+  if (Param)
+    Param->setUnparsedDefaultArg();
+
+  UnparsedDefaultArgLocs[Param] = ArgLoc;
+}
+
+/// ActOnParamDefaultArgumentError - Parsing or semantic analysis of
+/// the default argument for the parameter param failed.
+void Sema::ActOnParamDefaultArgumentError(DeclPtrTy param) {
+  if (!param)
+    return;
+
+  ParmVarDecl *Param = cast<ParmVarDecl>(param.getAs<Decl>());
+
+  Param->setInvalidDecl();
+
+  UnparsedDefaultArgLocs.erase(Param);
+}
+
+/// CheckExtraCXXDefaultArguments - Check for any extra default
+/// arguments in the declarator, which is not a function declaration
+/// or definition and therefore is not permitted to have default
+/// arguments. This routine should be invoked for every declarator
+/// that is not a function declaration or definition.
+void Sema::CheckExtraCXXDefaultArguments(Declarator &D) {
+  // C++ [dcl.fct.default]p3
+  //   A default argument expression shall be specified only in the
+  //   parameter-declaration-clause of a function declaration or in a
+  //   template-parameter (14.1). It shall not be specified for a
+  //   parameter pack. If it is specified in a
+  //   parameter-declaration-clause, it shall not occur within a
+  //   declarator or abstract-declarator of a parameter-declaration.
+  for (unsigned i = 0, e = D.getNumTypeObjects(); i != e; ++i) {
+    DeclaratorChunk &chunk = D.getTypeObject(i);
+    if (chunk.Kind == DeclaratorChunk::Function) {
+      for (unsigned argIdx = 0, e = chunk.Fun.NumArgs; argIdx != e; ++argIdx) {
+        ParmVarDecl *Param =
+          cast<ParmVarDecl>(chunk.Fun.ArgInfo[argIdx].Param.getAs<Decl>());
+        if (Param->hasUnparsedDefaultArg()) {
+          CachedTokens *Toks = chunk.Fun.ArgInfo[argIdx].DefaultArgTokens;
+          Diag(Param->getLocation(), diag::err_param_default_argument_nonfunc)
+            << SourceRange((*Toks)[1].getLocation(), Toks->back().getLocation());
+          delete Toks;
+          chunk.Fun.ArgInfo[argIdx].DefaultArgTokens = 0;
+        } else if (Param->getDefaultArg()) {
+          Diag(Param->getLocation(), diag::err_param_default_argument_nonfunc)
+            << Param->getDefaultArg()->getSourceRange();
+          Param->setDefaultArg(0);
+        }
+      }
+    }
+  }
+}
+
+// MergeCXXFunctionDecl - Merge two declarations of the same C++
+// function, once we already know that they have the same
+// type. Subroutine of MergeFunctionDecl. Returns true if there was an
+// error, false otherwise.
+bool Sema::MergeCXXFunctionDecl(FunctionDecl *New, FunctionDecl *Old) {
+  bool Invalid = false;
+
+  // C++ [dcl.fct.default]p4:
+  //   For non-template functions, default arguments can be added in
+  //   later declarations of a function in the same
+  //   scope. Declarations in different scopes have completely
+  //   distinct sets of default arguments. That is, declarations in
+  //   inner scopes do not acquire default arguments from
+  //   declarations in outer scopes, and vice versa. In a given
+  //   function declaration, all parameters subsequent to a
+  //   parameter with a default argument shall have default
+  //   arguments supplied in this or previous declarations. A
+  //   default argument shall not be redefined by a later
+  //   declaration (not even to the same value).
+  //
+  // C++ [dcl.fct.default]p6:
+  //   Except for member functions of class templates, the default arguments 
+  //   in a member function definition that appears outside of the class 
+  //   definition are added to the set of default arguments provided by the 
+  //   member function declaration in the class definition.
+  for (unsigned p = 0, NumParams = Old->getNumParams(); p < NumParams; ++p) {
+    ParmVarDecl *OldParam = Old->getParamDecl(p);
+    ParmVarDecl *NewParam = New->getParamDecl(p);
+
+    if (OldParam->hasDefaultArg() && NewParam->hasDefaultArg()) {
+      // FIXME: If we knew where the '=' was, we could easily provide a fix-it 
+      // hint here. Alternatively, we could walk the type-source information
+      // for NewParam to find the last source location in the type... but it
+      // isn't worth the effort right now. This is the kind of test case that
+      // is hard to get right:
+      
+      //   int f(int);
+      //   void g(int (*fp)(int) = f);
+      //   void g(int (*fp)(int) = &f);
+      Diag(NewParam->getLocation(),
+           diag::err_param_default_argument_redefinition)
+        << NewParam->getDefaultArgRange();
+      
+      // Look for the function declaration where the default argument was
+      // actually written, which may be a declaration prior to Old.
+      for (FunctionDecl *Older = Old->getPreviousDeclaration();
+           Older; Older = Older->getPreviousDeclaration()) {
+        if (!Older->getParamDecl(p)->hasDefaultArg())
+          break;
+        
+        OldParam = Older->getParamDecl(p);
+      }        
+      
+      Diag(OldParam->getLocation(), diag::note_previous_definition)
+        << OldParam->getDefaultArgRange();
+      Invalid = true;
+    } else if (OldParam->hasDefaultArg()) {
+      // Merge the old default argument into the new parameter
+      if (OldParam->hasUninstantiatedDefaultArg())
+        NewParam->setUninstantiatedDefaultArg(
+                                      OldParam->getUninstantiatedDefaultArg());
+      else
+        NewParam->setDefaultArg(OldParam->getDefaultArg());
+    } else if (NewParam->hasDefaultArg()) {
+      if (New->getDescribedFunctionTemplate()) {
+        // Paragraph 4, quoted above, only applies to non-template functions.
+        Diag(NewParam->getLocation(),
+             diag::err_param_default_argument_template_redecl)
+          << NewParam->getDefaultArgRange();
+        Diag(Old->getLocation(), diag::note_template_prev_declaration)
+          << false;
+      } else if (New->getTemplateSpecializationKind()
+                   != TSK_ImplicitInstantiation &&
+                 New->getTemplateSpecializationKind() != TSK_Undeclared) {
+        // C++ [temp.expr.spec]p21:
+        //   Default function arguments shall not be specified in a declaration
+        //   or a definition for one of the following explicit specializations:
+        //     - the explicit specialization of a function template;
+        //     - the explicit specialization of a member function template;
+        //     - the explicit specialization of a member function of a class 
+        //       template where the class template specialization to which the
+        //       member function specialization belongs is implicitly 
+        //       instantiated.
+        Diag(NewParam->getLocation(), diag::err_template_spec_default_arg)
+          << (New->getTemplateSpecializationKind() ==TSK_ExplicitSpecialization)
+          << New->getDeclName()
+          << NewParam->getDefaultArgRange();
+      } else if (New->getDeclContext()->isDependentContext()) {
+        // C++ [dcl.fct.default]p6 (DR217):
+        //   Default arguments for a member function of a class template shall 
+        //   be specified on the initial declaration of the member function 
+        //   within the class template.
+        //
+        // Reading the tea leaves a bit in DR217 and its reference to DR205 
+        // leads me to the conclusion that one cannot add default function 
+        // arguments for an out-of-line definition of a member function of a 
+        // dependent type.
+        int WhichKind = 2;
+        if (CXXRecordDecl *Record 
+              = dyn_cast<CXXRecordDecl>(New->getDeclContext())) {
+          if (Record->getDescribedClassTemplate())
+            WhichKind = 0;
+          else if (isa<ClassTemplatePartialSpecializationDecl>(Record))
+            WhichKind = 1;
+          else
+            WhichKind = 2;
+        }
+        
+        Diag(NewParam->getLocation(), 
+             diag::err_param_default_argument_member_template_redecl)
+          << WhichKind
+          << NewParam->getDefaultArgRange();
+      }
+    }
+  }
+
+  if (CheckEquivalentExceptionSpec(
+          Old->getType()->getAs<FunctionProtoType>(), Old->getLocation(),
+          New->getType()->getAs<FunctionProtoType>(), New->getLocation()))
+    Invalid = true;
+
+  return Invalid;
+}
+
+/// CheckCXXDefaultArguments - Verify that the default arguments for a
+/// function declaration are well-formed according to C++
+/// [dcl.fct.default].
+void Sema::CheckCXXDefaultArguments(FunctionDecl *FD) {
+  unsigned NumParams = FD->getNumParams();
+  unsigned p;
+
+  // Find first parameter with a default argument
+  for (p = 0; p < NumParams; ++p) {
+    ParmVarDecl *Param = FD->getParamDecl(p);
+    if (Param->hasDefaultArg())
+      break;
+  }
+
+  // C++ [dcl.fct.default]p4:
+  //   In a given function declaration, all parameters
+  //   subsequent to a parameter with a default argument shall
+  //   have default arguments supplied in this or previous
+  //   declarations. A default argument shall not be redefined
+  //   by a later declaration (not even to the same value).
+  unsigned LastMissingDefaultArg = 0;
+  for (; p < NumParams; ++p) {
+    ParmVarDecl *Param = FD->getParamDecl(p);
+    if (!Param->hasDefaultArg()) {
+      if (Param->isInvalidDecl())
+        /* We already complained about this parameter. */;
+      else if (Param->getIdentifier())
+        Diag(Param->getLocation(),
+             diag::err_param_default_argument_missing_name)
+          << Param->getIdentifier();
+      else
+        Diag(Param->getLocation(),
+             diag::err_param_default_argument_missing);
+
+      LastMissingDefaultArg = p;
+    }
+  }
+
+  if (LastMissingDefaultArg > 0) {
+    // Some default arguments were missing. Clear out all of the
+    // default arguments up to (and including) the last missing
+    // default argument, so that we leave the function parameters
+    // in a semantically valid state.
+    for (p = 0; p <= LastMissingDefaultArg; ++p) {
+      ParmVarDecl *Param = FD->getParamDecl(p);
+      if (Param->hasDefaultArg()) {
+        if (!Param->hasUnparsedDefaultArg())
+          Param->getDefaultArg()->Destroy(Context);
+        Param->setDefaultArg(0);
+      }
+    }
+  }
+}
+
+/// isCurrentClassName - Determine whether the identifier II is the
+/// name of the class type currently being defined. In the case of
+/// nested classes, this will only return true if II is the name of
+/// the innermost class.
+bool Sema::isCurrentClassName(const IdentifierInfo &II, Scope *,
+                              const CXXScopeSpec *SS) {
+  assert(getLangOptions().CPlusPlus && "No class names in C!");
+
+  CXXRecordDecl *CurDecl;
+  if (SS && SS->isSet() && !SS->isInvalid()) {
+    DeclContext *DC = computeDeclContext(*SS, true);
+    CurDecl = dyn_cast_or_null<CXXRecordDecl>(DC);
+  } else
+    CurDecl = dyn_cast_or_null<CXXRecordDecl>(CurContext);
+
+  if (CurDecl && CurDecl->getIdentifier())
+    return &II == CurDecl->getIdentifier();
+  else
+    return false;
+}
+
+/// \brief Check the validity of a C++ base class specifier.
+///
+/// \returns a new CXXBaseSpecifier if well-formed, emits diagnostics
+/// and returns NULL otherwise.
+CXXBaseSpecifier *
+Sema::CheckBaseSpecifier(CXXRecordDecl *Class,
+                         SourceRange SpecifierRange,
+                         bool Virtual, AccessSpecifier Access,
+                         QualType BaseType,
+                         SourceLocation BaseLoc) {
+  // C++ [class.union]p1:
+  //   A union shall not have base classes.
+  if (Class->isUnion()) {
+    Diag(Class->getLocation(), diag::err_base_clause_on_union)
+      << SpecifierRange;
+    return 0;
+  }
+
+  if (BaseType->isDependentType())
+    return new (Context) CXXBaseSpecifier(SpecifierRange, Virtual,
+                                Class->getTagKind() == RecordDecl::TK_class,
+                                Access, BaseType);
+
+  // Base specifiers must be record types.
+  if (!BaseType->isRecordType()) {
+    Diag(BaseLoc, diag::err_base_must_be_class) << SpecifierRange;
+    return 0;
+  }
+
+  // C++ [class.union]p1:
+  //   A union shall not be used as a base class.
+  if (BaseType->isUnionType()) {
+    Diag(BaseLoc, diag::err_union_as_base_class) << SpecifierRange;
+    return 0;
+  }
+
+  // C++ [class.derived]p2:
+  //   The class-name in a base-specifier shall not be an incompletely
+  //   defined class.
+  if (RequireCompleteType(BaseLoc, BaseType,
+                          PDiag(diag::err_incomplete_base_class)
+                            << SpecifierRange))
+    return 0;
+
+  // If the base class is polymorphic or isn't empty, the new one is/isn't, too.
+  RecordDecl *BaseDecl = BaseType->getAs<RecordType>()->getDecl();
+  assert(BaseDecl && "Record type has no declaration");
+  BaseDecl = BaseDecl->getDefinition(Context);
+  assert(BaseDecl && "Base type is not incomplete, but has no definition");
+  CXXRecordDecl * CXXBaseDecl = cast<CXXRecordDecl>(BaseDecl);
+  assert(CXXBaseDecl && "Base type is not a C++ type");
+
+  // C++0x CWG Issue #817 indicates that [[final]] classes shouldn't be bases.
+  if (CXXBaseDecl->hasAttr<FinalAttr>()) {
+    Diag(BaseLoc, diag::err_final_base) << BaseType.getAsString();
+    Diag(CXXBaseDecl->getLocation(), diag::note_previous_decl)
+      << BaseType;
+    return 0;
+  }
+
+  SetClassDeclAttributesFromBase(Class, CXXBaseDecl, Virtual);
+  
+  // Create the base specifier.
+  // FIXME: Allocate via ASTContext?
+  return new (Context) CXXBaseSpecifier(SpecifierRange, Virtual,
+                              Class->getTagKind() == RecordDecl::TK_class,
+                              Access, BaseType);
+}
+
+void Sema::SetClassDeclAttributesFromBase(CXXRecordDecl *Class,
+                                          const CXXRecordDecl *BaseClass,
+                                          bool BaseIsVirtual) {
+  // A class with a non-empty base class is not empty.
+  // FIXME: Standard ref?
+  if (!BaseClass->isEmpty())
+    Class->setEmpty(false);
+
+  // C++ [class.virtual]p1:
+  //   A class that [...] inherits a virtual function is called a polymorphic
+  //   class.
+  if (BaseClass->isPolymorphic())
+    Class->setPolymorphic(true);
+
+  // C++ [dcl.init.aggr]p1:
+  //   An aggregate is [...] a class with [...] no base classes [...].
+  Class->setAggregate(false);
+
+  // C++ [class]p4:
+  //   A POD-struct is an aggregate class...
+  Class->setPOD(false);
+
+  if (BaseIsVirtual) {
+    // C++ [class.ctor]p5:
+    //   A constructor is trivial if its class has no virtual base classes.
+    Class->setHasTrivialConstructor(false);
+
+    // C++ [class.copy]p6:
+    //   A copy constructor is trivial if its class has no virtual base classes.
+    Class->setHasTrivialCopyConstructor(false);
+
+    // C++ [class.copy]p11:
+    //   A copy assignment operator is trivial if its class has no virtual
+    //   base classes.
+    Class->setHasTrivialCopyAssignment(false);
+
+    // C++0x [meta.unary.prop] is_empty:
+    //    T is a class type, but not a union type, with ... no virtual base
+    //    classes
+    Class->setEmpty(false);
+  } else {
+    // C++ [class.ctor]p5:
+    //   A constructor is trivial if all the direct base classes of its
+    //   class have trivial constructors.
+    if (!BaseClass->hasTrivialConstructor())
+      Class->setHasTrivialConstructor(false);
+
+    // C++ [class.copy]p6:
+    //   A copy constructor is trivial if all the direct base classes of its
+    //   class have trivial copy constructors.
+    if (!BaseClass->hasTrivialCopyConstructor())
+      Class->setHasTrivialCopyConstructor(false);
+
+    // C++ [class.copy]p11:
+    //   A copy assignment operator is trivial if all the direct base classes
+    //   of its class have trivial copy assignment operators.
+    if (!BaseClass->hasTrivialCopyAssignment())
+      Class->setHasTrivialCopyAssignment(false);
+  }
+
+  // C++ [class.ctor]p3:
+  //   A destructor is trivial if all the direct base classes of its class
+  //   have trivial destructors.
+  if (!BaseClass->hasTrivialDestructor())
+    Class->setHasTrivialDestructor(false);
+}
+
+/// ActOnBaseSpecifier - Parsed a base specifier. A base specifier is
+/// one entry in the base class list of a class specifier, for
+/// example:
+///    class foo : public bar, virtual private baz {
+/// 'public bar' and 'virtual private baz' are each base-specifiers.
+Sema::BaseResult
+Sema::ActOnBaseSpecifier(DeclPtrTy classdecl, SourceRange SpecifierRange,
+                         bool Virtual, AccessSpecifier Access,
+                         TypeTy *basetype, SourceLocation BaseLoc) {
+  if (!classdecl)
+    return true;
+
+  AdjustDeclIfTemplate(classdecl);
+  CXXRecordDecl *Class = cast<CXXRecordDecl>(classdecl.getAs<Decl>());
+  QualType BaseType = GetTypeFromParser(basetype);
+  if (CXXBaseSpecifier *BaseSpec = CheckBaseSpecifier(Class, SpecifierRange,
+                                                      Virtual, Access,
+                                                      BaseType, BaseLoc))
+    return BaseSpec;
+
+  return true;
+}
+
+/// \brief Performs the actual work of attaching the given base class
+/// specifiers to a C++ class.
+bool Sema::AttachBaseSpecifiers(CXXRecordDecl *Class, CXXBaseSpecifier **Bases,
+                                unsigned NumBases) {
+ if (NumBases == 0)
+    return false;
+
+  // Used to keep track of which base types we have already seen, so
+  // that we can properly diagnose redundant direct base types. Note
+  // that the key is always the unqualified canonical type of the base
+  // class.
+  std::map<QualType, CXXBaseSpecifier*, QualTypeOrdering> KnownBaseTypes;
+
+  // Copy non-redundant base specifiers into permanent storage.
+  unsigned NumGoodBases = 0;
+  bool Invalid = false;
+  for (unsigned idx = 0; idx < NumBases; ++idx) {
+    QualType NewBaseType
+      = Context.getCanonicalType(Bases[idx]->getType());
+    NewBaseType = NewBaseType.getLocalUnqualifiedType();
+
+    if (KnownBaseTypes[NewBaseType]) {
+      // C++ [class.mi]p3:
+      //   A class shall not be specified as a direct base class of a
+      //   derived class more than once.
+      Diag(Bases[idx]->getSourceRange().getBegin(),
+           diag::err_duplicate_base_class)
+        << KnownBaseTypes[NewBaseType]->getType()
+        << Bases[idx]->getSourceRange();
+
+      // Delete the duplicate base class specifier; we're going to
+      // overwrite its pointer later.
+      Context.Deallocate(Bases[idx]);
+
+      Invalid = true;
+    } else {
+      // Okay, add this new base class.
+      KnownBaseTypes[NewBaseType] = Bases[idx];
+      Bases[NumGoodBases++] = Bases[idx];
+    }
+  }
+
+  // Attach the remaining base class specifiers to the derived class.
+  Class->setBases(Context, Bases, NumGoodBases);
+
+  // Delete the remaining (good) base class specifiers, since their
+  // data has been copied into the CXXRecordDecl.
+  for (unsigned idx = 0; idx < NumGoodBases; ++idx)
+    Context.Deallocate(Bases[idx]);
+
+  return Invalid;
+}
+
+/// ActOnBaseSpecifiers - Attach the given base specifiers to the
+/// class, after checking whether there are any duplicate base
+/// classes.
+void Sema::ActOnBaseSpecifiers(DeclPtrTy ClassDecl, BaseTy **Bases,
+                               unsigned NumBases) {
+  if (!ClassDecl || !Bases || !NumBases)
+    return;
+
+  AdjustDeclIfTemplate(ClassDecl);
+  AttachBaseSpecifiers(cast<CXXRecordDecl>(ClassDecl.getAs<Decl>()),
+                       (CXXBaseSpecifier**)(Bases), NumBases);
+}
+
+/// \brief Determine whether the type \p Derived is a C++ class that is
+/// derived from the type \p Base.
+bool Sema::IsDerivedFrom(QualType Derived, QualType Base) {
+  if (!getLangOptions().CPlusPlus)
+    return false;
+    
+  const RecordType *DerivedRT = Derived->getAs<RecordType>();
+  if (!DerivedRT)
+    return false;
+  
+  const RecordType *BaseRT = Base->getAs<RecordType>();
+  if (!BaseRT)
+    return false;
+  
+  CXXRecordDecl *DerivedRD = cast<CXXRecordDecl>(DerivedRT->getDecl());
+  CXXRecordDecl *BaseRD = cast<CXXRecordDecl>(BaseRT->getDecl());
+  // FIXME: instantiate DerivedRD if necessary.  We need a PoI for this.
+  return DerivedRD->hasDefinition() && DerivedRD->isDerivedFrom(BaseRD);
+}
+
+/// \brief Determine whether the type \p Derived is a C++ class that is
+/// derived from the type \p Base.
+bool Sema::IsDerivedFrom(QualType Derived, QualType Base, CXXBasePaths &Paths) {
+  if (!getLangOptions().CPlusPlus)
+    return false;
+  
+  const RecordType *DerivedRT = Derived->getAs<RecordType>();
+  if (!DerivedRT)
+    return false;
+  
+  const RecordType *BaseRT = Base->getAs<RecordType>();
+  if (!BaseRT)
+    return false;
+  
+  CXXRecordDecl *DerivedRD = cast<CXXRecordDecl>(DerivedRT->getDecl());
+  CXXRecordDecl *BaseRD = cast<CXXRecordDecl>(BaseRT->getDecl());
+  return DerivedRD->isDerivedFrom(BaseRD, Paths);
+}
+
+/// CheckDerivedToBaseConversion - Check whether the Derived-to-Base
+/// conversion (where Derived and Base are class types) is
+/// well-formed, meaning that the conversion is unambiguous (and
+/// that all of the base classes are accessible). Returns true
+/// and emits a diagnostic if the code is ill-formed, returns false
+/// otherwise. Loc is the location where this routine should point to
+/// if there is an error, and Range is the source range to highlight
+/// if there is an error.
+bool
+Sema::CheckDerivedToBaseConversion(QualType Derived, QualType Base,
+                                   AccessDiagnosticsKind ADK,
+                                   unsigned AmbigiousBaseConvID,
+                                   SourceLocation Loc, SourceRange Range,
+                                   DeclarationName Name) {
+  // First, determine whether the path from Derived to Base is
+  // ambiguous. This is slightly more expensive than checking whether
+  // the Derived to Base conversion exists, because here we need to
+  // explore multiple paths to determine if there is an ambiguity.
+  CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
+                     /*DetectVirtual=*/false);
+  bool DerivationOkay = IsDerivedFrom(Derived, Base, Paths);
+  assert(DerivationOkay &&
+         "Can only be used with a derived-to-base conversion");
+  (void)DerivationOkay;
+  
+  if (!Paths.isAmbiguous(Context.getCanonicalType(Base).getUnqualifiedType())) {
+    if (ADK == ADK_quiet)
+      return false;
+
+    // Check that the base class can be accessed.
+    switch (CheckBaseClassAccess(Loc, /*IsBaseToDerived*/ false,
+                                 Base, Derived, Paths.front(),
+                                 /*force*/ false,
+                                 /*unprivileged*/ false,
+                                 ADK)) {
+    case AR_accessible: return false;
+    case AR_inaccessible: return true;
+    case AR_dependent: return false;
+    case AR_delayed: return false;
+    }
+  }
+  
+  // We know that the derived-to-base conversion is ambiguous, and
+  // we're going to produce a diagnostic. Perform the derived-to-base
+  // search just one more time to compute all of the possible paths so
+  // that we can print them out. This is more expensive than any of
+  // the previous derived-to-base checks we've done, but at this point
+  // performance isn't as much of an issue.
+  Paths.clear();
+  Paths.setRecordingPaths(true);
+  bool StillOkay = IsDerivedFrom(Derived, Base, Paths);
+  assert(StillOkay && "Can only be used with a derived-to-base conversion");
+  (void)StillOkay;
+  
+  // Build up a textual representation of the ambiguous paths, e.g.,
+  // D -> B -> A, that will be used to illustrate the ambiguous
+  // conversions in the diagnostic. We only print one of the paths
+  // to each base class subobject.
+  std::string PathDisplayStr = getAmbiguousPathsDisplayString(Paths);
+  
+  Diag(Loc, AmbigiousBaseConvID)
+  << Derived << Base << PathDisplayStr << Range << Name;
+  return true;
+}
+
+bool
+Sema::CheckDerivedToBaseConversion(QualType Derived, QualType Base,
+                                   SourceLocation Loc, SourceRange Range,
+                                   bool IgnoreAccess) {
+  return CheckDerivedToBaseConversion(Derived, Base,
+                                      IgnoreAccess ? ADK_quiet : ADK_normal,
+                                      diag::err_ambiguous_derived_to_base_conv,
+                                      Loc, Range, DeclarationName());
+}
+
+
+/// @brief Builds a string representing ambiguous paths from a
+/// specific derived class to different subobjects of the same base
+/// class.
+///
+/// This function builds a string that can be used in error messages
+/// to show the different paths that one can take through the
+/// inheritance hierarchy to go from the derived class to different
+/// subobjects of a base class. The result looks something like this:
+/// @code
+/// struct D -> struct B -> struct A
+/// struct D -> struct C -> struct A
+/// @endcode
+std::string Sema::getAmbiguousPathsDisplayString(CXXBasePaths &Paths) {
+  std::string PathDisplayStr;
+  std::set<unsigned> DisplayedPaths;
+  for (CXXBasePaths::paths_iterator Path = Paths.begin();
+       Path != Paths.end(); ++Path) {
+    if (DisplayedPaths.insert(Path->back().SubobjectNumber).second) {
+      // We haven't displayed a path to this particular base
+      // class subobject yet.
+      PathDisplayStr += "\n    ";
+      PathDisplayStr += Context.getTypeDeclType(Paths.getOrigin()).getAsString();
+      for (CXXBasePath::const_iterator Element = Path->begin();
+           Element != Path->end(); ++Element)
+        PathDisplayStr += " -> " + Element->Base->getType().getAsString();
+    }
+  }
+  
+  return PathDisplayStr;
+}
+
+//===----------------------------------------------------------------------===//
+// C++ class member Handling
+//===----------------------------------------------------------------------===//
+
+/// ActOnCXXMemberDeclarator - This is invoked when a C++ class member
+/// declarator is parsed. 'AS' is the access specifier, 'BW' specifies the
+/// bitfield width if there is one and 'InitExpr' specifies the initializer if
+/// any.
+Sema::DeclPtrTy
+Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D,
+                               MultiTemplateParamsArg TemplateParameterLists,
+                               ExprTy *BW, ExprTy *InitExpr, bool IsDefinition,
+                               bool Deleted) {
+  const DeclSpec &DS = D.getDeclSpec();
+  DeclarationName Name = GetNameForDeclarator(D);
+  Expr *BitWidth = static_cast<Expr*>(BW);
+  Expr *Init = static_cast<Expr*>(InitExpr);
+  SourceLocation Loc = D.getIdentifierLoc();
+
+  bool isFunc = D.isFunctionDeclarator();
+
+  assert(!DS.isFriendSpecified());
+
+  // C++ 9.2p6: A member shall not be declared to have automatic storage
+  // duration (auto, register) or with the extern storage-class-specifier.
+  // C++ 7.1.1p8: The mutable specifier can be applied only to names of class
+  // data members and cannot be applied to names declared const or static,
+  // and cannot be applied to reference members.
+  switch (DS.getStorageClassSpec()) {
+    case DeclSpec::SCS_unspecified:
+    case DeclSpec::SCS_typedef:
+    case DeclSpec::SCS_static:
+      // FALL THROUGH.
+      break;
+    case DeclSpec::SCS_mutable:
+      if (isFunc) {
+        if (DS.getStorageClassSpecLoc().isValid())
+          Diag(DS.getStorageClassSpecLoc(), diag::err_mutable_function);
+        else
+          Diag(DS.getThreadSpecLoc(), diag::err_mutable_function);
+
+        // FIXME: It would be nicer if the keyword was ignored only for this
+        // declarator. Otherwise we could get follow-up errors.
+        D.getMutableDeclSpec().ClearStorageClassSpecs();
+      } else {
+        QualType T = GetTypeForDeclarator(D, S);
+        diag::kind err = static_cast<diag::kind>(0);
+        if (T->isReferenceType())
+          err = diag::err_mutable_reference;
+        else if (T.isConstQualified())
+          err = diag::err_mutable_const;
+        if (err != 0) {
+          if (DS.getStorageClassSpecLoc().isValid())
+            Diag(DS.getStorageClassSpecLoc(), err);
+          else
+            Diag(DS.getThreadSpecLoc(), err);
+          // FIXME: It would be nicer if the keyword was ignored only for this
+          // declarator. Otherwise we could get follow-up errors.
+          D.getMutableDeclSpec().ClearStorageClassSpecs();
+        }
+      }
+      break;
+    default:
+      if (DS.getStorageClassSpecLoc().isValid())
+        Diag(DS.getStorageClassSpecLoc(),
+             diag::err_storageclass_invalid_for_member);
+      else
+        Diag(DS.getThreadSpecLoc(), diag::err_storageclass_invalid_for_member);
+      D.getMutableDeclSpec().ClearStorageClassSpecs();
+  }
+
+  if (!isFunc &&
+      D.getDeclSpec().getTypeSpecType() == DeclSpec::TST_typename &&
+      D.getNumTypeObjects() == 0) {
+    // Check also for this case:
+    //
+    // typedef int f();
+    // f a;
+    //
+    QualType TDType = GetTypeFromParser(DS.getTypeRep());
+    isFunc = TDType->isFunctionType();
+  }
+
+  bool isInstField = ((DS.getStorageClassSpec() == DeclSpec::SCS_unspecified ||
+                       DS.getStorageClassSpec() == DeclSpec::SCS_mutable) &&
+                      !isFunc);
+
+  Decl *Member;
+  if (isInstField) {
+    // FIXME: Check for template parameters!
+    Member = HandleField(S, cast<CXXRecordDecl>(CurContext), Loc, D, BitWidth,
+                         AS);
+    assert(Member && "HandleField never returns null");
+  } else {
+    Member = HandleDeclarator(S, D, move(TemplateParameterLists), IsDefinition)
+               .getAs<Decl>();
+    if (!Member) {
+      if (BitWidth) DeleteExpr(BitWidth);
+      return DeclPtrTy();
+    }
+
+    // Non-instance-fields can't have a bitfield.
+    if (BitWidth) {
+      if (Member->isInvalidDecl()) {
+        // don't emit another diagnostic.
+      } else if (isa<VarDecl>(Member)) {
+        // C++ 9.6p3: A bit-field shall not be a static member.
+        // "static member 'A' cannot be a bit-field"
+        Diag(Loc, diag::err_static_not_bitfield)
+          << Name << BitWidth->getSourceRange();
+      } else if (isa<TypedefDecl>(Member)) {
+        // "typedef member 'x' cannot be a bit-field"
+        Diag(Loc, diag::err_typedef_not_bitfield)
+          << Name << BitWidth->getSourceRange();
+      } else {
+        // A function typedef ("typedef int f(); f a;").
+        // C++ 9.6p3: A bit-field shall have integral or enumeration type.
+        Diag(Loc, diag::err_not_integral_type_bitfield)
+          << Name << cast<ValueDecl>(Member)->getType()
+          << BitWidth->getSourceRange();
+      }
+
+      DeleteExpr(BitWidth);
+      BitWidth = 0;
+      Member->setInvalidDecl();
+    }
+
+    Member->setAccess(AS);
+
+    // If we have declared a member function template, set the access of the
+    // templated declaration as well.
+    if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(Member))
+      FunTmpl->getTemplatedDecl()->setAccess(AS);
+  }
+
+  assert((Name || isInstField) && "No identifier for non-field ?");
+
+  if (Init)
+    AddInitializerToDecl(DeclPtrTy::make(Member), ExprArg(*this, Init), false);
+  if (Deleted) // FIXME: Source location is not very good.
+    SetDeclDeleted(DeclPtrTy::make(Member), D.getSourceRange().getBegin());
+
+  if (isInstField) {
+    FieldCollector->Add(cast<FieldDecl>(Member));
+    return DeclPtrTy();
+  }
+  return DeclPtrTy::make(Member);
+}
+
+/// \brief Find the direct and/or virtual base specifiers that
+/// correspond to the given base type, for use in base initialization
+/// within a constructor.
+static bool FindBaseInitializer(Sema &SemaRef, 
+                                CXXRecordDecl *ClassDecl,
+                                QualType BaseType,
+                                const CXXBaseSpecifier *&DirectBaseSpec,
+                                const CXXBaseSpecifier *&VirtualBaseSpec) {
+  // First, check for a direct base class.
+  DirectBaseSpec = 0;
+  for (CXXRecordDecl::base_class_const_iterator Base
+         = ClassDecl->bases_begin(); 
+       Base != ClassDecl->bases_end(); ++Base) {
+    if (SemaRef.Context.hasSameUnqualifiedType(BaseType, Base->getType())) {
+      // We found a direct base of this type. That's what we're
+      // initializing.
+      DirectBaseSpec = &*Base;
+      break;
+    }
+  }
+
+  // Check for a virtual base class.
+  // FIXME: We might be able to short-circuit this if we know in advance that
+  // there are no virtual bases.
+  VirtualBaseSpec = 0;
+  if (!DirectBaseSpec || !DirectBaseSpec->isVirtual()) {
+    // We haven't found a base yet; search the class hierarchy for a
+    // virtual base class.
+    CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
+                       /*DetectVirtual=*/false);
+    if (SemaRef.IsDerivedFrom(SemaRef.Context.getTypeDeclType(ClassDecl), 
+                              BaseType, Paths)) {
+      for (CXXBasePaths::paths_iterator Path = Paths.begin();
+           Path != Paths.end(); ++Path) {
+        if (Path->back().Base->isVirtual()) {
+          VirtualBaseSpec = Path->back().Base;
+          break;
+        }
+      }
+    }
+  }
+
+  return DirectBaseSpec || VirtualBaseSpec;
+}
+
+/// ActOnMemInitializer - Handle a C++ member initializer.
+Sema::MemInitResult
+Sema::ActOnMemInitializer(DeclPtrTy ConstructorD,
+                          Scope *S,
+                          const CXXScopeSpec &SS,
+                          IdentifierInfo *MemberOrBase,
+                          TypeTy *TemplateTypeTy,
+                          SourceLocation IdLoc,
+                          SourceLocation LParenLoc,
+                          ExprTy **Args, unsigned NumArgs,
+                          SourceLocation *CommaLocs,
+                          SourceLocation RParenLoc) {
+  if (!ConstructorD)
+    return true;
+
+  AdjustDeclIfTemplate(ConstructorD);
+
+  CXXConstructorDecl *Constructor
+    = dyn_cast<CXXConstructorDecl>(ConstructorD.getAs<Decl>());
+  if (!Constructor) {
+    // The user wrote a constructor initializer on a function that is
+    // not a C++ constructor. Ignore the error for now, because we may
+    // have more member initializers coming; we'll diagnose it just
+    // once in ActOnMemInitializers.
+    return true;
+  }
+
+  CXXRecordDecl *ClassDecl = Constructor->getParent();
+
+  // C++ [class.base.init]p2:
+  //   Names in a mem-initializer-id are looked up in the scope of the
+  //   constructor’s class and, if not found in that scope, are looked
+  //   up in the scope containing the constructor’s
+  //   definition. [Note: if the constructor’s class contains a member
+  //   with the same name as a direct or virtual base class of the
+  //   class, a mem-initializer-id naming the member or base class and
+  //   composed of a single identifier refers to the class member. A
+  //   mem-initializer-id for the hidden base class may be specified
+  //   using a qualified name. ]
+  if (!SS.getScopeRep() && !TemplateTypeTy) {
+    // Look for a member, first.
+    FieldDecl *Member = 0;
+    DeclContext::lookup_result Result
+      = ClassDecl->lookup(MemberOrBase);
+    if (Result.first != Result.second)
+      Member = dyn_cast<FieldDecl>(*Result.first);
+
+    // FIXME: Handle members of an anonymous union.
+
+    if (Member)
+      return BuildMemberInitializer(Member, (Expr**)Args, NumArgs, IdLoc,
+                                    LParenLoc, RParenLoc);
+  }
+  // It didn't name a member, so see if it names a class.
+  QualType BaseType;
+  TypeSourceInfo *TInfo = 0;
+
+  if (TemplateTypeTy) {
+    BaseType = GetTypeFromParser(TemplateTypeTy, &TInfo);
+  } else {
+    LookupResult R(*this, MemberOrBase, IdLoc, LookupOrdinaryName);
+    LookupParsedName(R, S, &SS);
+
+    TypeDecl *TyD = R.getAsSingle<TypeDecl>();
+    if (!TyD) {
+      if (R.isAmbiguous()) return true;
+
+      if (SS.isSet() && isDependentScopeSpecifier(SS)) {
+        bool NotUnknownSpecialization = false;
+        DeclContext *DC = computeDeclContext(SS, false);
+        if (CXXRecordDecl *Record = dyn_cast_or_null<CXXRecordDecl>(DC)) 
+          NotUnknownSpecialization = !Record->hasAnyDependentBases();
+
+        if (!NotUnknownSpecialization) {
+          // When the scope specifier can refer to a member of an unknown
+          // specialization, we take it as a type name.
+          BaseType = CheckTypenameType((NestedNameSpecifier *)SS.getScopeRep(),
+                                       *MemberOrBase, SS.getRange());
+          R.clear();
+        }
+      }
+
+      // If no results were found, try to correct typos.
+      if (R.empty() && BaseType.isNull() &&
+          CorrectTypo(R, S, &SS, ClassDecl) && R.isSingleResult()) {
+        if (FieldDecl *Member = R.getAsSingle<FieldDecl>()) {
+          if (Member->getDeclContext()->getLookupContext()->Equals(ClassDecl)) {
+            // We have found a non-static data member with a similar
+            // name to what was typed; complain and initialize that
+            // member.
+            Diag(R.getNameLoc(), diag::err_mem_init_not_member_or_class_suggest)
+              << MemberOrBase << true << R.getLookupName()
+              << CodeModificationHint::CreateReplacement(R.getNameLoc(),
+                                               R.getLookupName().getAsString());
+            Diag(Member->getLocation(), diag::note_previous_decl)
+              << Member->getDeclName();
+
+            return BuildMemberInitializer(Member, (Expr**)Args, NumArgs, IdLoc,
+                                          LParenLoc, RParenLoc);
+          }
+        } else if (TypeDecl *Type = R.getAsSingle<TypeDecl>()) {
+          const CXXBaseSpecifier *DirectBaseSpec;
+          const CXXBaseSpecifier *VirtualBaseSpec;
+          if (FindBaseInitializer(*this, ClassDecl, 
+                                  Context.getTypeDeclType(Type),
+                                  DirectBaseSpec, VirtualBaseSpec)) {
+            // We have found a direct or virtual base class with a
+            // similar name to what was typed; complain and initialize
+            // that base class.
+            Diag(R.getNameLoc(), diag::err_mem_init_not_member_or_class_suggest)
+              << MemberOrBase << false << R.getLookupName()
+              << CodeModificationHint::CreateReplacement(R.getNameLoc(),
+                                               R.getLookupName().getAsString());
+
+            const CXXBaseSpecifier *BaseSpec = DirectBaseSpec? DirectBaseSpec 
+                                                             : VirtualBaseSpec;
+            Diag(BaseSpec->getSourceRange().getBegin(),
+                 diag::note_base_class_specified_here)
+              << BaseSpec->getType()
+              << BaseSpec->getSourceRange();
+
+            TyD = Type;
+          }
+        }
+      }
+
+      if (!TyD && BaseType.isNull()) {
+        Diag(IdLoc, diag::err_mem_init_not_member_or_class)
+          << MemberOrBase << SourceRange(IdLoc, RParenLoc);
+        return true;
+      }
+    }
+
+    if (BaseType.isNull()) {
+      BaseType = Context.getTypeDeclType(TyD);
+      if (SS.isSet()) {
+        NestedNameSpecifier *Qualifier =
+          static_cast<NestedNameSpecifier*>(SS.getScopeRep());
+
+        // FIXME: preserve source range information
+        BaseType = Context.getQualifiedNameType(Qualifier, BaseType);
+      }
+    }
+  }
+
+  if (!TInfo)
+    TInfo = Context.getTrivialTypeSourceInfo(BaseType, IdLoc);
+
+  return BuildBaseInitializer(BaseType, TInfo, (Expr **)Args, NumArgs, 
+                              LParenLoc, RParenLoc, ClassDecl);
+}
+
+/// Checks an initializer expression for use of uninitialized fields, such as
+/// containing the field that is being initialized. Returns true if there is an
+/// uninitialized field was used an updates the SourceLocation parameter; false
+/// otherwise.
+static bool InitExprContainsUninitializedFields(const Stmt* S,
+                                                const FieldDecl* LhsField,
+                                                SourceLocation* L) {
+  const MemberExpr* ME = dyn_cast<MemberExpr>(S);
+  if (ME) {
+    const NamedDecl* RhsField = ME->getMemberDecl();
+    if (RhsField == LhsField) {
+      // Initializing a field with itself. Throw a warning.
+      // But wait; there are exceptions!
+      // Exception #1:  The field may not belong to this record.
+      // e.g. Foo(const Foo& rhs) : A(rhs.A) {}
+      const Expr* base = ME->getBase();
+      if (base != NULL && !isa<CXXThisExpr>(base->IgnoreParenCasts())) {
+        // Even though the field matches, it does not belong to this record.
+        return false;
+      }
+      // None of the exceptions triggered; return true to indicate an
+      // uninitialized field was used.
+      *L = ME->getMemberLoc();
+      return true;
+    }
+  }
+  bool found = false;
+  for (Stmt::const_child_iterator it = S->child_begin();
+       it != S->child_end() && found == false;
+       ++it) {
+    if (isa<CallExpr>(S)) {
+      // Do not descend into function calls or constructors, as the use
+      // of an uninitialized field may be valid. One would have to inspect
+      // the contents of the function/ctor to determine if it is safe or not.
+      // i.e. Pass-by-value is never safe, but pass-by-reference and pointers
+      // may be safe, depending on what the function/ctor does.
+      continue;
+    }
+    found = InitExprContainsUninitializedFields(*it, LhsField, L);
+  }
+  return found;
+}
+
+Sema::MemInitResult
+Sema::BuildMemberInitializer(FieldDecl *Member, Expr **Args,
+                             unsigned NumArgs, SourceLocation IdLoc,
+                             SourceLocation LParenLoc,
+                             SourceLocation RParenLoc) {
+  // Diagnose value-uses of fields to initialize themselves, e.g.
+  //   foo(foo)
+  // where foo is not also a parameter to the constructor.
+  // TODO: implement -Wuninitialized and fold this into that framework.
+  for (unsigned i = 0; i < NumArgs; ++i) {
+    SourceLocation L;
+    if (InitExprContainsUninitializedFields(Args[i], Member, &L)) {
+      // FIXME: Return true in the case when other fields are used before being
+      // uninitialized. For example, let this field be the i'th field. When
+      // initializing the i'th field, throw a warning if any of the >= i'th
+      // fields are used, as they are not yet initialized.
+      // Right now we are only handling the case where the i'th field uses
+      // itself in its initializer.
+      Diag(L, diag::warn_field_is_uninit);
+    }
+  }
+
+  bool HasDependentArg = false;
+  for (unsigned i = 0; i < NumArgs; i++)
+    HasDependentArg |= Args[i]->isTypeDependent();
+
+  QualType FieldType = Member->getType();
+  if (const ArrayType *Array = Context.getAsArrayType(FieldType))
+    FieldType = Array->getElementType();
+  ASTOwningVector<&ActionBase::DeleteExpr> ConstructorArgs(*this);
+  if (FieldType->isDependentType() || HasDependentArg) {
+    // Can't check initialization for a member of dependent type or when
+    // any of the arguments are type-dependent expressions.
+    OwningExprResult Init
+      = Owned(new (Context) ParenListExpr(Context, LParenLoc, Args, NumArgs,
+                                          RParenLoc));
+
+    // Erase any temporaries within this evaluation context; we're not
+    // going to track them in the AST, since we'll be rebuilding the
+    // ASTs during template instantiation.
+    ExprTemporaries.erase(
+              ExprTemporaries.begin() + ExprEvalContexts.back().NumTemporaries,
+                          ExprTemporaries.end());
+    
+    return new (Context) CXXBaseOrMemberInitializer(Context, Member, IdLoc,
+                                                    LParenLoc, 
+                                                    Init.takeAs<Expr>(),
+                                                    RParenLoc);
+    
+  }
+  
+  if (Member->isInvalidDecl())
+    return true;
+  
+  // Initialize the member.
+  InitializedEntity MemberEntity =
+    InitializedEntity::InitializeMember(Member, 0);
+  InitializationKind Kind = 
+    InitializationKind::CreateDirect(IdLoc, LParenLoc, RParenLoc);
+  
+  InitializationSequence InitSeq(*this, MemberEntity, Kind, Args, NumArgs);
+  
+  OwningExprResult MemberInit =
+    InitSeq.Perform(*this, MemberEntity, Kind, 
+                    MultiExprArg(*this, (void**)Args, NumArgs), 0);
+  if (MemberInit.isInvalid())
+    return true;
+  
+  // C++0x [class.base.init]p7:
+  //   The initialization of each base and member constitutes a 
+  //   full-expression.
+  MemberInit = MaybeCreateCXXExprWithTemporaries(move(MemberInit));
+  if (MemberInit.isInvalid())
+    return true;
+  
+  // If we are in a dependent context, template instantiation will
+  // perform this type-checking again. Just save the arguments that we
+  // received in a ParenListExpr.
+  // FIXME: This isn't quite ideal, since our ASTs don't capture all
+  // of the information that we have about the member
+  // initializer. However, deconstructing the ASTs is a dicey process,
+  // and this approach is far more likely to get the corner cases right.
+  if (CurContext->isDependentContext()) {
+    // Bump the reference count of all of the arguments.
+    for (unsigned I = 0; I != NumArgs; ++I)
+      Args[I]->Retain();
+
+    OwningExprResult Init
+      = Owned(new (Context) ParenListExpr(Context, LParenLoc, Args, NumArgs,
+                                          RParenLoc));
+    return new (Context) CXXBaseOrMemberInitializer(Context, Member, IdLoc,
+                                                    LParenLoc, 
+                                                    Init.takeAs<Expr>(),
+                                                    RParenLoc);
+  }
+
+  return new (Context) CXXBaseOrMemberInitializer(Context, Member, IdLoc,
+                                                  LParenLoc, 
+                                                  MemberInit.takeAs<Expr>(),
+                                                  RParenLoc);
+}
+
+Sema::MemInitResult
+Sema::BuildBaseInitializer(QualType BaseType, TypeSourceInfo *BaseTInfo,
+                           Expr **Args, unsigned NumArgs, 
+                           SourceLocation LParenLoc, SourceLocation RParenLoc, 
+                           CXXRecordDecl *ClassDecl) {
+  bool HasDependentArg = false;
+  for (unsigned i = 0; i < NumArgs; i++)
+    HasDependentArg |= Args[i]->isTypeDependent();
+
+  SourceLocation BaseLoc = BaseTInfo->getTypeLoc().getSourceRange().getBegin();
+  if (BaseType->isDependentType() || HasDependentArg) {
+    // Can't check initialization for a base of dependent type or when
+    // any of the arguments are type-dependent expressions.
+    OwningExprResult BaseInit
+      = Owned(new (Context) ParenListExpr(Context, LParenLoc, Args, NumArgs,
+                                          RParenLoc));
+
+    // Erase any temporaries within this evaluation context; we're not
+    // going to track them in the AST, since we'll be rebuilding the
+    // ASTs during template instantiation.
+    ExprTemporaries.erase(
+              ExprTemporaries.begin() + ExprEvalContexts.back().NumTemporaries,
+                          ExprTemporaries.end());
+
+    return new (Context) CXXBaseOrMemberInitializer(Context, BaseTInfo, 
+                                                    LParenLoc, 
+                                                    BaseInit.takeAs<Expr>(),
+                                                    RParenLoc);
+  }
+  
+  if (!BaseType->isRecordType())
+    return Diag(BaseLoc, diag::err_base_init_does_not_name_class)
+             << BaseType << BaseTInfo->getTypeLoc().getSourceRange();
+
+  // C++ [class.base.init]p2:
+  //   [...] Unless the mem-initializer-id names a nonstatic data
+  //   member of the constructor’s class or a direct or virtual base
+  //   of that class, the mem-initializer is ill-formed. A
+  //   mem-initializer-list can initialize a base class using any
+  //   name that denotes that base class type.
+
+  // Check for direct and virtual base classes.
+  const CXXBaseSpecifier *DirectBaseSpec = 0;
+  const CXXBaseSpecifier *VirtualBaseSpec = 0;
+  FindBaseInitializer(*this, ClassDecl, BaseType, DirectBaseSpec, 
+                      VirtualBaseSpec);
+
+  // C++ [base.class.init]p2:
+  //   If a mem-initializer-id is ambiguous because it designates both
+  //   a direct non-virtual base class and an inherited virtual base
+  //   class, the mem-initializer is ill-formed.
+  if (DirectBaseSpec && VirtualBaseSpec)
+    return Diag(BaseLoc, diag::err_base_init_direct_and_virtual)
+      << BaseType << BaseTInfo->getTypeLoc().getSourceRange();
+  // C++ [base.class.init]p2:
+  // Unless the mem-initializer-id names a nonstatic data membeer of the
+  // constructor's class ot a direst or virtual base of that class, the
+  // mem-initializer is ill-formed.
+  if (!DirectBaseSpec && !VirtualBaseSpec)
+    return Diag(BaseLoc, diag::err_not_direct_base_or_virtual)
+      << BaseType << ClassDecl->getNameAsCString()
+      << BaseTInfo->getTypeLoc().getSourceRange();
+
+  CXXBaseSpecifier *BaseSpec
+    = const_cast<CXXBaseSpecifier *>(DirectBaseSpec);
+  if (!BaseSpec)
+    BaseSpec = const_cast<CXXBaseSpecifier *>(VirtualBaseSpec);
+
+  // Initialize the base.
+  InitializedEntity BaseEntity =
+    InitializedEntity::InitializeBase(Context, BaseSpec);
+  InitializationKind Kind = 
+    InitializationKind::CreateDirect(BaseLoc, LParenLoc, RParenLoc);
+  
+  InitializationSequence InitSeq(*this, BaseEntity, Kind, Args, NumArgs);
+  
+  OwningExprResult BaseInit =
+    InitSeq.Perform(*this, BaseEntity, Kind, 
+                    MultiExprArg(*this, (void**)Args, NumArgs), 0);
+  if (BaseInit.isInvalid())
+    return true;
+  
+  // C++0x [class.base.init]p7:
+  //   The initialization of each base and member constitutes a 
+  //   full-expression.
+  BaseInit = MaybeCreateCXXExprWithTemporaries(move(BaseInit));
+  if (BaseInit.isInvalid())
+    return true;
+
+  // If we are in a dependent context, template instantiation will
+  // perform this type-checking again. Just save the arguments that we
+  // received in a ParenListExpr.
+  // FIXME: This isn't quite ideal, since our ASTs don't capture all
+  // of the information that we have about the base
+  // initializer. However, deconstructing the ASTs is a dicey process,
+  // and this approach is far more likely to get the corner cases right.
+  if (CurContext->isDependentContext()) {
+    // Bump the reference count of all of the arguments.
+    for (unsigned I = 0; I != NumArgs; ++I)
+      Args[I]->Retain();
+
+    OwningExprResult Init
+      = Owned(new (Context) ParenListExpr(Context, LParenLoc, Args, NumArgs,
+                                          RParenLoc));
+    return new (Context) CXXBaseOrMemberInitializer(Context, BaseTInfo,
+                                                    LParenLoc, 
+                                                    Init.takeAs<Expr>(),
+                                                    RParenLoc);
+  }
+
+  return new (Context) CXXBaseOrMemberInitializer(Context, BaseTInfo,
+                                                  LParenLoc, 
+                                                  BaseInit.takeAs<Expr>(),
+                                                  RParenLoc);
+}
+
+bool
+Sema::SetBaseOrMemberInitializers(CXXConstructorDecl *Constructor,
+                                  CXXBaseOrMemberInitializer **Initializers,
+                                  unsigned NumInitializers,
+                                  bool IsImplicitConstructor,
+                                  bool AnyErrors) {
+  // We need to build the initializer AST according to order of construction
+  // and not what user specified in the Initializers list.
+  CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(Constructor->getDeclContext());
+  llvm::SmallVector<CXXBaseOrMemberInitializer*, 32> AllToInit;
+  llvm::DenseMap<const void *, CXXBaseOrMemberInitializer*> AllBaseFields;
+  bool HasDependentBaseInit = false;
+  bool HadError = false;
+
+  for (unsigned i = 0; i < NumInitializers; i++) {
+    CXXBaseOrMemberInitializer *Member = Initializers[i];
+    if (Member->isBaseInitializer()) {
+      if (Member->getBaseClass()->isDependentType())
+        HasDependentBaseInit = true;
+      AllBaseFields[Member->getBaseClass()->getAs<RecordType>()] = Member;
+    } else {
+      AllBaseFields[Member->getMember()] = Member;
+    }
+  }
+
+  if (HasDependentBaseInit) {
+    // FIXME. This does not preserve the ordering of the initializers.
+    // Try (with -Wreorder)
+    // template<class X> struct A {};
+    // template<class X> struct B : A<X> {
+    //   B() : x1(10), A<X>() {}
+    //   int x1;
+    // };
+    // B<int> x;
+    // On seeing one dependent type, we should essentially exit this routine
+    // while preserving user-declared initializer list. When this routine is
+    // called during instantiatiation process, this routine will rebuild the
+    // ordered initializer list correctly.
+
+    // If we have a dependent base initialization, we can't determine the
+    // association between initializers and bases; just dump the known
+    // initializers into the list, and don't try to deal with other bases.
+    for (unsigned i = 0; i < NumInitializers; i++) {
+      CXXBaseOrMemberInitializer *Member = Initializers[i];
+      if (Member->isBaseInitializer())
+        AllToInit.push_back(Member);
+    }
+  } else {
+    llvm::SmallVector<CXXBaseSpecifier *, 4> BasesToDefaultInit;
+    
+    // Push virtual bases before others.
+    for (CXXRecordDecl::base_class_iterator VBase =
+         ClassDecl->vbases_begin(),
+         E = ClassDecl->vbases_end(); VBase != E; ++VBase) {
+      if (VBase->getType()->isDependentType())
+        continue;
+      if (CXXBaseOrMemberInitializer *Value
+            = AllBaseFields.lookup(VBase->getType()->getAs<RecordType>())) {
+        AllToInit.push_back(Value);
+      } else if (!AnyErrors) {
+        InitializedEntity InitEntity
+          = InitializedEntity::InitializeBase(Context, VBase);
+        InitializationKind InitKind
+          = InitializationKind::CreateDefault(Constructor->getLocation());
+        InitializationSequence InitSeq(*this, InitEntity, InitKind, 0, 0);        
+        OwningExprResult BaseInit = InitSeq.Perform(*this, InitEntity, InitKind,
+                                                    MultiExprArg(*this, 0, 0));
+        BaseInit = MaybeCreateCXXExprWithTemporaries(move(BaseInit));
+        if (BaseInit.isInvalid()) {
+          HadError = true;
+          continue;
+        }
+
+        // Don't attach synthesized base initializers in a dependent
+        // context; they'll be checked again at template instantiation
+        // time.
+        if (CurContext->isDependentContext())
+          continue;
+        
+        CXXBaseOrMemberInitializer *CXXBaseInit =
+          new (Context) CXXBaseOrMemberInitializer(Context,
+                             Context.getTrivialTypeSourceInfo(VBase->getType(), 
+                                                              SourceLocation()),
+                                                   SourceLocation(),
+                                                   BaseInit.takeAs<Expr>(),
+                                                   SourceLocation());
+        AllToInit.push_back(CXXBaseInit);
+      }
+    }
+
+    for (CXXRecordDecl::base_class_iterator Base =
+         ClassDecl->bases_begin(),
+         E = ClassDecl->bases_end(); Base != E; ++Base) {
+      // Virtuals are in the virtual base list and already constructed.
+      if (Base->isVirtual())
+        continue;
+      // Skip dependent types.
+      if (Base->getType()->isDependentType())
+        continue;
+      if (CXXBaseOrMemberInitializer *Value
+            = AllBaseFields.lookup(Base->getType()->getAs<RecordType>())) {
+        AllToInit.push_back(Value);
+      }
+      else if (!AnyErrors) {
+        InitializedEntity InitEntity
+          = InitializedEntity::InitializeBase(Context, Base);
+        InitializationKind InitKind
+          = InitializationKind::CreateDefault(Constructor->getLocation());
+        InitializationSequence InitSeq(*this, InitEntity, InitKind, 0, 0);        
+        OwningExprResult BaseInit = InitSeq.Perform(*this, InitEntity, InitKind,
+                                                    MultiExprArg(*this, 0, 0));
+        BaseInit = MaybeCreateCXXExprWithTemporaries(move(BaseInit));
+        if (BaseInit.isInvalid()) {
+          HadError = true;
+          continue;
+        }
+        
+        // Don't attach synthesized base initializers in a dependent
+        // context; they'll be regenerated at template instantiation
+        // time.
+        if (CurContext->isDependentContext())
+          continue;
+        
+        CXXBaseOrMemberInitializer *CXXBaseInit =
+          new (Context) CXXBaseOrMemberInitializer(Context,
+                             Context.getTrivialTypeSourceInfo(Base->getType(), 
+                                                              SourceLocation()),
+                                                   SourceLocation(),
+                                                   BaseInit.takeAs<Expr>(),
+                                                   SourceLocation());
+        AllToInit.push_back(CXXBaseInit);
+      }
+    }
+  }
+
+  // non-static data members.
+  for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(),
+       E = ClassDecl->field_end(); Field != E; ++Field) {
+    if ((*Field)->isAnonymousStructOrUnion()) {
+      if (const RecordType *FieldClassType =
+          Field->getType()->getAs<RecordType>()) {
+        CXXRecordDecl *FieldClassDecl
+          = cast<CXXRecordDecl>(FieldClassType->getDecl());
+        for (RecordDecl::field_iterator FA = FieldClassDecl->field_begin(),
+            EA = FieldClassDecl->field_end(); FA != EA; FA++) {
+          if (CXXBaseOrMemberInitializer *Value = AllBaseFields.lookup(*FA)) {
+            // 'Member' is the anonymous union field and 'AnonUnionMember' is
+            // set to the anonymous union data member used in the initializer
+            // list.
+            Value->setMember(*Field);
+            Value->setAnonUnionMember(*FA);
+            AllToInit.push_back(Value);
+            break;
+          }
+        }
+      }
+      continue;
+    }
+    if (CXXBaseOrMemberInitializer *Value = AllBaseFields.lookup(*Field)) {
+      AllToInit.push_back(Value);
+      continue;
+    }
+
+    if ((*Field)->getType()->isDependentType() || AnyErrors)
+      continue;
+    
+    QualType FT = Context.getBaseElementType((*Field)->getType());
+    if (FT->getAs<RecordType>()) {
+      InitializedEntity InitEntity
+        = InitializedEntity::InitializeMember(*Field);
+      InitializationKind InitKind
+        = InitializationKind::CreateDefault(Constructor->getLocation());
+
+      InitializationSequence InitSeq(*this, InitEntity, InitKind, 0, 0);
+      OwningExprResult MemberInit = InitSeq.Perform(*this, InitEntity, InitKind,
+                                                    MultiExprArg(*this, 0, 0));
+      MemberInit = MaybeCreateCXXExprWithTemporaries(move(MemberInit));
+      if (MemberInit.isInvalid()) {
+        HadError = true;
+        continue;
+      }
+      
+      // Don't attach synthesized member initializers in a dependent
+      // context; they'll be regenerated a template instantiation
+      // time.
+      if (CurContext->isDependentContext())
+        continue;
+      
+      CXXBaseOrMemberInitializer *Member =
+        new (Context) CXXBaseOrMemberInitializer(Context,
+                                                 *Field, SourceLocation(),
+                                                 SourceLocation(),
+                                                 MemberInit.takeAs<Expr>(),
+                                                 SourceLocation());
+
+      AllToInit.push_back(Member);
+    }
+    else if (FT->isReferenceType()) {
+      Diag(Constructor->getLocation(), diag::err_uninitialized_member_in_ctor)
+        << (int)IsImplicitConstructor << Context.getTagDeclType(ClassDecl)
+        << 0 << (*Field)->getDeclName();
+      Diag((*Field)->getLocation(), diag::note_declared_at);
+      HadError = true;
+    }
+    else if (FT.isConstQualified()) {
+      Diag(Constructor->getLocation(), diag::err_uninitialized_member_in_ctor)
+        << (int)IsImplicitConstructor << Context.getTagDeclType(ClassDecl)
+        << 1 << (*Field)->getDeclName();
+      Diag((*Field)->getLocation(), diag::note_declared_at);
+      HadError = true;
+    }
+  }
+
+  NumInitializers = AllToInit.size();
+  if (NumInitializers > 0) {
+    Constructor->setNumBaseOrMemberInitializers(NumInitializers);
+    CXXBaseOrMemberInitializer **baseOrMemberInitializers =
+      new (Context) CXXBaseOrMemberInitializer*[NumInitializers];
+
+    Constructor->setBaseOrMemberInitializers(baseOrMemberInitializers);
+    for (unsigned Idx = 0; Idx < NumInitializers; ++Idx)
+      baseOrMemberInitializers[Idx] = AllToInit[Idx];
+  }
+
+  return HadError;
+}
+
+static void *GetKeyForTopLevelField(FieldDecl *Field) {
+  // For anonymous unions, use the class declaration as the key.
+  if (const RecordType *RT = Field->getType()->getAs<RecordType>()) {
+    if (RT->getDecl()->isAnonymousStructOrUnion())
+      return static_cast<void *>(RT->getDecl());
+  }
+  return static_cast<void *>(Field);
+}
+
+static void *GetKeyForBase(QualType BaseType) {
+  if (const RecordType *RT = BaseType->getAs<RecordType>())
+    return (void *)RT;
+
+  assert(0 && "Unexpected base type!");
+  return 0;
+}
+
+static void *GetKeyForMember(CXXBaseOrMemberInitializer *Member,
+                             bool MemberMaybeAnon = false) {
+  // For fields injected into the class via declaration of an anonymous union,
+  // use its anonymous union class declaration as the unique key.
+  if (Member->isMemberInitializer()) {
+    FieldDecl *Field = Member->getMember();
+
+    // After SetBaseOrMemberInitializers call, Field is the anonymous union
+    // data member of the class. Data member used in the initializer list is
+    // in AnonUnionMember field.
+    if (MemberMaybeAnon && Field->isAnonymousStructOrUnion())
+      Field = Member->getAnonUnionMember();
+    if (Field->getDeclContext()->isRecord()) {
+      RecordDecl *RD = cast<RecordDecl>(Field->getDeclContext());
+      if (RD->isAnonymousStructOrUnion())
+        return static_cast<void *>(RD);
+    }
+    return static_cast<void *>(Field);
+  }
+
+  return GetKeyForBase(QualType(Member->getBaseClass(), 0));
+}
+
+/// ActOnMemInitializers - Handle the member initializers for a constructor.
+void Sema::ActOnMemInitializers(DeclPtrTy ConstructorDecl,
+                                SourceLocation ColonLoc,
+                                MemInitTy **MemInits, unsigned NumMemInits,
+                                bool AnyErrors) {
+  if (!ConstructorDecl)
+    return;
+
+  AdjustDeclIfTemplate(ConstructorDecl);
+
+  CXXConstructorDecl *Constructor
+    = dyn_cast<CXXConstructorDecl>(ConstructorDecl.getAs<Decl>());
+
+  if (!Constructor) {
+    Diag(ColonLoc, diag::err_only_constructors_take_base_inits);
+    return;
+  }
+
+  if (!Constructor->isDependentContext()) {
+    llvm::DenseMap<void*, CXXBaseOrMemberInitializer *>Members;
+    bool err = false;
+    for (unsigned i = 0; i < NumMemInits; i++) {
+      CXXBaseOrMemberInitializer *Member =
+        static_cast<CXXBaseOrMemberInitializer*>(MemInits[i]);
+      void *KeyToMember = GetKeyForMember(Member);
+      CXXBaseOrMemberInitializer *&PrevMember = Members[KeyToMember];
+      if (!PrevMember) {
+        PrevMember = Member;
+        continue;
+      }
+      if (FieldDecl *Field = Member->getMember())
+        Diag(Member->getSourceLocation(),
+             diag::error_multiple_mem_initialization)
+          << Field->getNameAsString()
+          << Member->getSourceRange();
+      else {
+        Type *BaseClass = Member->getBaseClass();
+        assert(BaseClass && "ActOnMemInitializers - neither field or base");
+        Diag(Member->getSourceLocation(),
+             diag::error_multiple_base_initialization)
+          << QualType(BaseClass, 0)
+          << Member->getSourceRange();
+      }
+      Diag(PrevMember->getSourceLocation(), diag::note_previous_initializer)
+        << 0;
+      err = true;
+    }
+
+    if (err)
+      return;
+  }
+
+  SetBaseOrMemberInitializers(Constructor,
+                      reinterpret_cast<CXXBaseOrMemberInitializer **>(MemInits),
+                      NumMemInits, false, AnyErrors);
+
+  if (Constructor->isDependentContext())
+    return;
+
+  if (Diags.getDiagnosticLevel(diag::warn_base_initialized) ==
+      Diagnostic::Ignored &&
+      Diags.getDiagnosticLevel(diag::warn_field_initialized) ==
+      Diagnostic::Ignored)
+    return;
+
+  // Also issue warning if order of ctor-initializer list does not match order
+  // of 1) base class declarations and 2) order of non-static data members.
+  llvm::SmallVector<const void*, 32> AllBaseOrMembers;
+
+  CXXRecordDecl *ClassDecl
+    = cast<CXXRecordDecl>(Constructor->getDeclContext());
+  // Push virtual bases before others.
+  for (CXXRecordDecl::base_class_iterator VBase =
+       ClassDecl->vbases_begin(),
+       E = ClassDecl->vbases_end(); VBase != E; ++VBase)
+    AllBaseOrMembers.push_back(GetKeyForBase(VBase->getType()));
+
+  for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin(),
+       E = ClassDecl->bases_end(); Base != E; ++Base) {
+    // Virtuals are alread in the virtual base list and are constructed
+    // first.
+    if (Base->isVirtual())
+      continue;
+    AllBaseOrMembers.push_back(GetKeyForBase(Base->getType()));
+  }
+
+  for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(),
+       E = ClassDecl->field_end(); Field != E; ++Field)
+    AllBaseOrMembers.push_back(GetKeyForTopLevelField(*Field));
+
+  int Last = AllBaseOrMembers.size();
+  int curIndex = 0;
+  CXXBaseOrMemberInitializer *PrevMember = 0;
+  for (unsigned i = 0; i < NumMemInits; i++) {
+    CXXBaseOrMemberInitializer *Member =
+      static_cast<CXXBaseOrMemberInitializer*>(MemInits[i]);
+    void *MemberInCtorList = GetKeyForMember(Member, true);
+
+    for (; curIndex < Last; curIndex++)
+      if (MemberInCtorList == AllBaseOrMembers[curIndex])
+        break;
+    if (curIndex == Last) {
+      assert(PrevMember && "Member not in member list?!");
+      // Initializer as specified in ctor-initializer list is out of order.
+      // Issue a warning diagnostic.
+      if (PrevMember->isBaseInitializer()) {
+        // Diagnostics is for an initialized base class.
+        Type *BaseClass = PrevMember->getBaseClass();
+        Diag(PrevMember->getSourceLocation(),
+             diag::warn_base_initialized)
+          << QualType(BaseClass, 0);
+      } else {
+        FieldDecl *Field = PrevMember->getMember();
+        Diag(PrevMember->getSourceLocation(),
+             diag::warn_field_initialized)
+          << Field->getNameAsString();
+      }
+      // Also the note!
+      if (FieldDecl *Field = Member->getMember())
+        Diag(Member->getSourceLocation(),
+             diag::note_fieldorbase_initialized_here) << 0
+          << Field->getNameAsString();
+      else {
+        Type *BaseClass = Member->getBaseClass();
+        Diag(Member->getSourceLocation(),
+             diag::note_fieldorbase_initialized_here) << 1
+          << QualType(BaseClass, 0);
+      }
+      for (curIndex = 0; curIndex < Last; curIndex++)
+        if (MemberInCtorList == AllBaseOrMembers[curIndex])
+          break;
+    }
+    PrevMember = Member;
+  }
+}
+
+void
+Sema::MarkBaseAndMemberDestructorsReferenced(CXXDestructorDecl *Destructor) {
+  // Ignore dependent destructors.
+  if (Destructor->isDependentContext())
+    return;
+  
+  CXXRecordDecl *ClassDecl = Destructor->getParent();
+
+  // Non-static data members.
+  for (CXXRecordDecl::field_iterator I = ClassDecl->field_begin(),
+       E = ClassDecl->field_end(); I != E; ++I) {
+    FieldDecl *Field = *I;
+    
+    QualType FieldType = Context.getBaseElementType(Field->getType());
+    
+    const RecordType* RT = FieldType->getAs<RecordType>();
+    if (!RT)
+      continue;
+    
+    CXXRecordDecl *FieldClassDecl = cast<CXXRecordDecl>(RT->getDecl());
+    if (FieldClassDecl->hasTrivialDestructor())
+      continue;
+
+    const CXXDestructorDecl *Dtor = FieldClassDecl->getDestructor(Context);
+    MarkDeclarationReferenced(Destructor->getLocation(),
+                              const_cast<CXXDestructorDecl*>(Dtor));
+  }
+
+  // Bases.
+  for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin(),
+       E = ClassDecl->bases_end(); Base != E; ++Base) {
+    // Ignore virtual bases.
+    if (Base->isVirtual())
+      continue;
+
+    // Ignore trivial destructors.
+    CXXRecordDecl *BaseClassDecl
+      = cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl());
+    if (BaseClassDecl->hasTrivialDestructor())
+      continue;
+    
+    const CXXDestructorDecl *Dtor = BaseClassDecl->getDestructor(Context);
+    MarkDeclarationReferenced(Destructor->getLocation(),
+                              const_cast<CXXDestructorDecl*>(Dtor));
+  }
+  
+  // Virtual bases.
+  for (CXXRecordDecl::base_class_iterator VBase = ClassDecl->vbases_begin(),
+       E = ClassDecl->vbases_end(); VBase != E; ++VBase) {
+    // Ignore trivial destructors.
+    CXXRecordDecl *BaseClassDecl
+      = cast<CXXRecordDecl>(VBase->getType()->getAs<RecordType>()->getDecl());
+    if (BaseClassDecl->hasTrivialDestructor())
+      continue;
+    
+    const CXXDestructorDecl *Dtor = BaseClassDecl->getDestructor(Context);
+    MarkDeclarationReferenced(Destructor->getLocation(),
+                              const_cast<CXXDestructorDecl*>(Dtor));
+  }
+}
+
+void Sema::ActOnDefaultCtorInitializers(DeclPtrTy CDtorDecl) {
+  if (!CDtorDecl)
+    return;
+
+  AdjustDeclIfTemplate(CDtorDecl);
+
+  if (CXXConstructorDecl *Constructor
+      = dyn_cast<CXXConstructorDecl>(CDtorDecl.getAs<Decl>()))
+    SetBaseOrMemberInitializers(Constructor, 0, 0, false, false);
+}
+
+namespace {
+  /// PureVirtualMethodCollector - traverses a class and its superclasses
+  /// and determines if it has any pure virtual methods.
+  class PureVirtualMethodCollector {
+    ASTContext &Context;
+
+  public:
+    typedef llvm::SmallVector<const CXXMethodDecl*, 8> MethodList;
+
+  private:
+    MethodList Methods;
+
+    void Collect(const CXXRecordDecl* RD, MethodList& Methods);
+
+  public:
+    PureVirtualMethodCollector(ASTContext &Ctx, const CXXRecordDecl* RD)
+      : Context(Ctx) {
+
+      MethodList List;
+      Collect(RD, List);
+
+      // Copy the temporary list to methods, and make sure to ignore any
+      // null entries.
+      for (size_t i = 0, e = List.size(); i != e; ++i) {
+        if (List[i])
+          Methods.push_back(List[i]);
+      }
+    }
+
+    bool empty() const { return Methods.empty(); }
+
+    MethodList::const_iterator methods_begin() { return Methods.begin(); }
+    MethodList::const_iterator methods_end() { return Methods.end(); }
+  };
+
+  void PureVirtualMethodCollector::Collect(const CXXRecordDecl* RD,
+                                           MethodList& Methods) {
+    // First, collect the pure virtual methods for the base classes.
+    for (CXXRecordDecl::base_class_const_iterator Base = RD->bases_begin(),
+         BaseEnd = RD->bases_end(); Base != BaseEnd; ++Base) {
+      if (const RecordType *RT = Base->getType()->getAs<RecordType>()) {
+        const CXXRecordDecl *BaseDecl = cast<CXXRecordDecl>(RT->getDecl());
+        if (BaseDecl && BaseDecl->isAbstract())
+          Collect(BaseDecl, Methods);
+      }
+    }
+
+    // Next, zero out any pure virtual methods that this class overrides.
+    typedef llvm::SmallPtrSet<const CXXMethodDecl*, 4> MethodSetTy;
+
+    MethodSetTy OverriddenMethods;
+    size_t MethodsSize = Methods.size();
+
+    for (RecordDecl::decl_iterator i = RD->decls_begin(), e = RD->decls_end();
+         i != e; ++i) {
+      // Traverse the record, looking for methods.
+      if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(*i)) {
+        // If the method is pure virtual, add it to the methods vector.
+        if (MD->isPure())
+          Methods.push_back(MD);
+
+        // Record all the overridden methods in our set.
+        for (CXXMethodDecl::method_iterator I = MD->begin_overridden_methods(),
+             E = MD->end_overridden_methods(); I != E; ++I) {
+          // Keep track of the overridden methods.
+          OverriddenMethods.insert(*I);
+        }
+      }
+    }
+
+    // Now go through the methods and zero out all the ones we know are
+    // overridden.
+    for (size_t i = 0, e = MethodsSize; i != e; ++i) {
+      if (OverriddenMethods.count(Methods[i]))
+        Methods[i] = 0;
+    }
+
+  }
+}
+
+
+bool Sema::RequireNonAbstractType(SourceLocation Loc, QualType T,
+                                  unsigned DiagID, AbstractDiagSelID SelID,
+                                  const CXXRecordDecl *CurrentRD) {
+  if (SelID == -1)
+    return RequireNonAbstractType(Loc, T,
+                                  PDiag(DiagID), CurrentRD);
+  else
+    return RequireNonAbstractType(Loc, T,
+                                  PDiag(DiagID) << SelID, CurrentRD);
+}
+
+bool Sema::RequireNonAbstractType(SourceLocation Loc, QualType T,
+                                  const PartialDiagnostic &PD,
+                                  const CXXRecordDecl *CurrentRD) {
+  if (!getLangOptions().CPlusPlus)
+    return false;
+
+  if (const ArrayType *AT = Context.getAsArrayType(T))
+    return RequireNonAbstractType(Loc, AT->getElementType(), PD,
+                                  CurrentRD);
+
+  if (const PointerType *PT = T->getAs<PointerType>()) {
+    // Find the innermost pointer type.
+    while (const PointerType *T = PT->getPointeeType()->getAs<PointerType>())
+      PT = T;
+
+    if (const ArrayType *AT = Context.getAsArrayType(PT->getPointeeType()))
+      return RequireNonAbstractType(Loc, AT->getElementType(), PD, CurrentRD);
+  }
+
+  const RecordType *RT = T->getAs<RecordType>();
+  if (!RT)
+    return false;
+
+  const CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
+
+  if (CurrentRD && CurrentRD != RD)
+    return false;
+
+  // FIXME: is this reasonable?  It matches current behavior, but....
+  if (!RD->getDefinition(Context))
+    return false;
+
+  if (!RD->isAbstract())
+    return false;
+
+  Diag(Loc, PD) << RD->getDeclName();
+
+  // Check if we've already emitted the list of pure virtual functions for this
+  // class.
+  if (PureVirtualClassDiagSet && PureVirtualClassDiagSet->count(RD))
+    return true;
+
+  PureVirtualMethodCollector Collector(Context, RD);
+
+  for (PureVirtualMethodCollector::MethodList::const_iterator I =
+       Collector.methods_begin(), E = Collector.methods_end(); I != E; ++I) {
+    const CXXMethodDecl *MD = *I;
+
+    Diag(MD->getLocation(), diag::note_pure_virtual_function) <<
+      MD->getDeclName();
+  }
+
+  if (!PureVirtualClassDiagSet)
+    PureVirtualClassDiagSet.reset(new RecordDeclSetTy);
+  PureVirtualClassDiagSet->insert(RD);
+
+  return true;
+}
+
+namespace {
+  class AbstractClassUsageDiagnoser
+    : public DeclVisitor<AbstractClassUsageDiagnoser, bool> {
+    Sema &SemaRef;
+    CXXRecordDecl *AbstractClass;
+
+    bool VisitDeclContext(const DeclContext *DC) {
+      bool Invalid = false;
+
+      for (CXXRecordDecl::decl_iterator I = DC->decls_begin(),
+           E = DC->decls_end(); I != E; ++I)
+        Invalid |= Visit(*I);
+
+      return Invalid;
+    }
+
+  public:
+    AbstractClassUsageDiagnoser(Sema& SemaRef, CXXRecordDecl *ac)
+      : SemaRef(SemaRef), AbstractClass(ac) {
+        Visit(SemaRef.Context.getTranslationUnitDecl());
+    }
+
+    bool VisitFunctionDecl(const FunctionDecl *FD) {
+      if (FD->isThisDeclarationADefinition()) {
+        // No need to do the check if we're in a definition, because it requires
+        // that the return/param types are complete.
+        // because that requires
+        return VisitDeclContext(FD);
+      }
+
+      // Check the return type.
+      QualType RTy = FD->getType()->getAs<FunctionType>()->getResultType();
+      bool Invalid =
+        SemaRef.RequireNonAbstractType(FD->getLocation(), RTy,
+                                       diag::err_abstract_type_in_decl,
+                                       Sema::AbstractReturnType,
+                                       AbstractClass);
+
+      for (FunctionDecl::param_const_iterator I = FD->param_begin(),
+           E = FD->param_end(); I != E; ++I) {
+        const ParmVarDecl *VD = *I;
+        Invalid |=
+          SemaRef.RequireNonAbstractType(VD->getLocation(),
+                                         VD->getOriginalType(),
+                                         diag::err_abstract_type_in_decl,
+                                         Sema::AbstractParamType,
+                                         AbstractClass);
+      }
+
+      return Invalid;
+    }
+
+    bool VisitDecl(const Decl* D) {
+      if (const DeclContext *DC = dyn_cast<DeclContext>(D))
+        return VisitDeclContext(DC);
+
+      return false;
+    }
+  };
+}
+
+/// \brief Perform semantic checks on a class definition that has been
+/// completing, introducing implicitly-declared members, checking for
+/// abstract types, etc.
+void Sema::CheckCompletedCXXClass(CXXRecordDecl *Record) {
+  if (!Record || Record->isInvalidDecl())
+    return;
+
+  if (!Record->isDependentType())
+    AddImplicitlyDeclaredMembersToClass(Record);
+  
+  if (Record->isInvalidDecl())
+    return;
+
+  // Set access bits correctly on the directly-declared conversions.
+  UnresolvedSetImpl *Convs = Record->getConversionFunctions();
+  for (UnresolvedSetIterator I = Convs->begin(), E = Convs->end(); I != E; ++I)
+    Convs->setAccess(I, (*I)->getAccess());
+
+  if (!Record->isAbstract()) {
+    // Collect all the pure virtual methods and see if this is an abstract
+    // class after all.
+    PureVirtualMethodCollector Collector(Context, Record);
+    if (!Collector.empty())
+      Record->setAbstract(true);
+  }
+
+  if (Record->isAbstract())
+    (void)AbstractClassUsageDiagnoser(*this, Record);
+}
+
+void Sema::ActOnFinishCXXMemberSpecification(Scope* S, SourceLocation RLoc,
+                                             DeclPtrTy TagDecl,
+                                             SourceLocation LBrac,
+                                             SourceLocation RBrac) {
+  if (!TagDecl)
+    return;
+
+  AdjustDeclIfTemplate(TagDecl);
+
+  ActOnFields(S, RLoc, TagDecl,
+              (DeclPtrTy*)FieldCollector->getCurFields(),
+              FieldCollector->getCurNumFields(), LBrac, RBrac, 0);
+
+  CheckCompletedCXXClass(
+                      dyn_cast_or_null<CXXRecordDecl>(TagDecl.getAs<Decl>()));
+}
+
+/// AddImplicitlyDeclaredMembersToClass - Adds any implicitly-declared
+/// special functions, such as the default constructor, copy
+/// constructor, or destructor, to the given C++ class (C++
+/// [special]p1).  This routine can only be executed just before the
+/// definition of the class is complete.
+void Sema::AddImplicitlyDeclaredMembersToClass(CXXRecordDecl *ClassDecl) {
+  CanQualType ClassType
+    = Context.getCanonicalType(Context.getTypeDeclType(ClassDecl));
+
+  // FIXME: Implicit declarations have exception specifications, which are
+  // the union of the specifications of the implicitly called functions.
+
+  if (!ClassDecl->hasUserDeclaredConstructor()) {
+    // C++ [class.ctor]p5:
+    //   A default constructor for a class X is a constructor of class X
+    //   that can be called without an argument. If there is no
+    //   user-declared constructor for class X, a default constructor is
+    //   implicitly declared. An implicitly-declared default constructor
+    //   is an inline public member of its class.
+    DeclarationName Name
+      = Context.DeclarationNames.getCXXConstructorName(ClassType);
+    CXXConstructorDecl *DefaultCon =
+      CXXConstructorDecl::Create(Context, ClassDecl,
+                                 ClassDecl->getLocation(), Name,
+                                 Context.getFunctionType(Context.VoidTy,
+                                                         0, 0, false, 0),
+                                 /*TInfo=*/0,
+                                 /*isExplicit=*/false,
+                                 /*isInline=*/true,
+                                 /*isImplicitlyDeclared=*/true);
+    DefaultCon->setAccess(AS_public);
+    DefaultCon->setImplicit();
+    DefaultCon->setTrivial(ClassDecl->hasTrivialConstructor());
+    ClassDecl->addDecl(DefaultCon);
+  }
+
+  if (!ClassDecl->hasUserDeclaredCopyConstructor()) {
+    // C++ [class.copy]p4:
+    //   If the class definition does not explicitly declare a copy
+    //   constructor, one is declared implicitly.
+
+    // C++ [class.copy]p5:
+    //   The implicitly-declared copy constructor for a class X will
+    //   have the form
+    //
+    //       X::X(const X&)
+    //
+    //   if
+    bool HasConstCopyConstructor = true;
+
+    //     -- each direct or virtual base class B of X has a copy
+    //        constructor whose first parameter is of type const B& or
+    //        const volatile B&, and
+    for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin();
+         HasConstCopyConstructor && Base != ClassDecl->bases_end(); ++Base) {
+      const CXXRecordDecl *BaseClassDecl
+        = cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl());
+      HasConstCopyConstructor
+        = BaseClassDecl->hasConstCopyConstructor(Context);
+    }
+
+    //     -- for all the nonstatic data members of X that are of a
+    //        class type M (or array thereof), each such class type
+    //        has a copy constructor whose first parameter is of type
+    //        const M& or const volatile M&.
+    for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin();
+         HasConstCopyConstructor && Field != ClassDecl->field_end();
+         ++Field) {
+      QualType FieldType = (*Field)->getType();
+      if (const ArrayType *Array = Context.getAsArrayType(FieldType))
+        FieldType = Array->getElementType();
+      if (const RecordType *FieldClassType = FieldType->getAs<RecordType>()) {
+        const CXXRecordDecl *FieldClassDecl
+          = cast<CXXRecordDecl>(FieldClassType->getDecl());
+        HasConstCopyConstructor
+          = FieldClassDecl->hasConstCopyConstructor(Context);
+      }
+    }
+
+    //   Otherwise, the implicitly declared copy constructor will have
+    //   the form
+    //
+    //       X::X(X&)
+    QualType ArgType = ClassType;
+    if (HasConstCopyConstructor)
+      ArgType = ArgType.withConst();
+    ArgType = Context.getLValueReferenceType(ArgType);
+
+    //   An implicitly-declared copy constructor is an inline public
+    //   member of its class.
+    DeclarationName Name
+      = Context.DeclarationNames.getCXXConstructorName(ClassType);
+    CXXConstructorDecl *CopyConstructor
+      = CXXConstructorDecl::Create(Context, ClassDecl,
+                                   ClassDecl->getLocation(), Name,
+                                   Context.getFunctionType(Context.VoidTy,
+                                                           &ArgType, 1,
+                                                           false, 0),
+                                   /*TInfo=*/0,
+                                   /*isExplicit=*/false,
+                                   /*isInline=*/true,
+                                   /*isImplicitlyDeclared=*/true);
+    CopyConstructor->setAccess(AS_public);
+    CopyConstructor->setImplicit();
+    CopyConstructor->setTrivial(ClassDecl->hasTrivialCopyConstructor());
+
+    // Add the parameter to the constructor.
+    ParmVarDecl *FromParam = ParmVarDecl::Create(Context, CopyConstructor,
+                                                 ClassDecl->getLocation(),
+                                                 /*IdentifierInfo=*/0,
+                                                 ArgType, /*TInfo=*/0,
+                                                 VarDecl::None, 0);
+    CopyConstructor->setParams(Context, &FromParam, 1);
+    ClassDecl->addDecl(CopyConstructor);
+  }
+
+  if (!ClassDecl->hasUserDeclaredCopyAssignment()) {
+    // Note: The following rules are largely analoguous to the copy
+    // constructor rules. Note that virtual bases are not taken into account
+    // for determining the argument type of the operator. Note also that
+    // operators taking an object instead of a reference are allowed.
+    //
+    // C++ [class.copy]p10:
+    //   If the class definition does not explicitly declare a copy
+    //   assignment operator, one is declared implicitly.
+    //   The implicitly-defined copy assignment operator for a class X
+    //   will have the form
+    //
+    //       X& X::operator=(const X&)
+    //
+    //   if
+    bool HasConstCopyAssignment = true;
+
+    //       -- each direct base class B of X has a copy assignment operator
+    //          whose parameter is of type const B&, const volatile B& or B,
+    //          and
+    for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin();
+         HasConstCopyAssignment && Base != ClassDecl->bases_end(); ++Base) {
+      assert(!Base->getType()->isDependentType() &&
+            "Cannot generate implicit members for class with dependent bases.");
+      const CXXRecordDecl *BaseClassDecl
+        = cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl());
+      const CXXMethodDecl *MD = 0;
+      HasConstCopyAssignment = BaseClassDecl->hasConstCopyAssignment(Context,
+                                                                     MD);
+    }
+
+    //       -- for all the nonstatic data members of X that are of a class
+    //          type M (or array thereof), each such class type has a copy
+    //          assignment operator whose parameter is of type const M&,
+    //          const volatile M& or M.
+    for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin();
+         HasConstCopyAssignment && Field != ClassDecl->field_end();
+         ++Field) {
+      QualType FieldType = (*Field)->getType();
+      if (const ArrayType *Array = Context.getAsArrayType(FieldType))
+        FieldType = Array->getElementType();
+      if (const RecordType *FieldClassType = FieldType->getAs<RecordType>()) {
+        const CXXRecordDecl *FieldClassDecl
+          = cast<CXXRecordDecl>(FieldClassType->getDecl());
+        const CXXMethodDecl *MD = 0;
+        HasConstCopyAssignment
+          = FieldClassDecl->hasConstCopyAssignment(Context, MD);
+      }
+    }
+
+    //   Otherwise, the implicitly declared copy assignment operator will
+    //   have the form
+    //
+    //       X& X::operator=(X&)
+    QualType ArgType = ClassType;
+    QualType RetType = Context.getLValueReferenceType(ArgType);
+    if (HasConstCopyAssignment)
+      ArgType = ArgType.withConst();
+    ArgType = Context.getLValueReferenceType(ArgType);
+
+    //   An implicitly-declared copy assignment operator is an inline public
+    //   member of its class.
+    DeclarationName Name =
+      Context.DeclarationNames.getCXXOperatorName(OO_Equal);
+    CXXMethodDecl *CopyAssignment =
+      CXXMethodDecl::Create(Context, ClassDecl, ClassDecl->getLocation(), Name,
+                            Context.getFunctionType(RetType, &ArgType, 1,
+                                                    false, 0),
+                            /*TInfo=*/0, /*isStatic=*/false, /*isInline=*/true);
+    CopyAssignment->setAccess(AS_public);
+    CopyAssignment->setImplicit();
+    CopyAssignment->setTrivial(ClassDecl->hasTrivialCopyAssignment());
+    CopyAssignment->setCopyAssignment(true);
+
+    // Add the parameter to the operator.
+    ParmVarDecl *FromParam = ParmVarDecl::Create(Context, CopyAssignment,
+                                                 ClassDecl->getLocation(),
+                                                 /*IdentifierInfo=*/0,
+                                                 ArgType, /*TInfo=*/0,
+                                                 VarDecl::None, 0);
+    CopyAssignment->setParams(Context, &FromParam, 1);
+
+    // Don't call addedAssignmentOperator. There is no way to distinguish an
+    // implicit from an explicit assignment operator.
+    ClassDecl->addDecl(CopyAssignment);
+    AddOverriddenMethods(ClassDecl, CopyAssignment);
+  }
+
+  if (!ClassDecl->hasUserDeclaredDestructor()) {
+    // C++ [class.dtor]p2:
+    //   If a class has no user-declared destructor, a destructor is
+    //   declared implicitly. An implicitly-declared destructor is an
+    //   inline public member of its class.
+    DeclarationName Name
+      = Context.DeclarationNames.getCXXDestructorName(ClassType);
+    CXXDestructorDecl *Destructor
+      = CXXDestructorDecl::Create(Context, ClassDecl,
+                                  ClassDecl->getLocation(), Name,
+                                  Context.getFunctionType(Context.VoidTy,
+                                                          0, 0, false, 0),
+                                  /*isInline=*/true,
+                                  /*isImplicitlyDeclared=*/true);
+    Destructor->setAccess(AS_public);
+    Destructor->setImplicit();
+    Destructor->setTrivial(ClassDecl->hasTrivialDestructor());
+    ClassDecl->addDecl(Destructor);
+    
+    AddOverriddenMethods(ClassDecl, Destructor);
+  }
+}
+
+void Sema::ActOnReenterTemplateScope(Scope *S, DeclPtrTy TemplateD) {
+  Decl *D = TemplateD.getAs<Decl>();
+  if (!D)
+    return;
+  
+  TemplateParameterList *Params = 0;
+  if (TemplateDecl *Template = dyn_cast<TemplateDecl>(D))
+    Params = Template->getTemplateParameters();
+  else if (ClassTemplatePartialSpecializationDecl *PartialSpec
+           = dyn_cast<ClassTemplatePartialSpecializationDecl>(D))
+    Params = PartialSpec->getTemplateParameters();
+  else
+    return;
+
+  for (TemplateParameterList::iterator Param = Params->begin(),
+                                    ParamEnd = Params->end();
+       Param != ParamEnd; ++Param) {
+    NamedDecl *Named = cast<NamedDecl>(*Param);
+    if (Named->getDeclName()) {
+      S->AddDecl(DeclPtrTy::make(Named));
+      IdResolver.AddDecl(Named);
+    }
+  }
+}
+
+void Sema::ActOnStartDelayedMemberDeclarations(Scope *S, DeclPtrTy RecordD) {
+  if (!RecordD) return;
+  AdjustDeclIfTemplate(RecordD);
+  CXXRecordDecl *Record = cast<CXXRecordDecl>(RecordD.getAs<Decl>());
+  PushDeclContext(S, Record);
+}
+
+void Sema::ActOnFinishDelayedMemberDeclarations(Scope *S, DeclPtrTy RecordD) {
+  if (!RecordD) return;
+  PopDeclContext();
+}
+
+/// ActOnStartDelayedCXXMethodDeclaration - We have completed
+/// parsing a top-level (non-nested) C++ class, and we are now
+/// parsing those parts of the given Method declaration that could
+/// not be parsed earlier (C++ [class.mem]p2), such as default
+/// arguments. This action should enter the scope of the given
+/// Method declaration as if we had just parsed the qualified method
+/// name. However, it should not bring the parameters into scope;
+/// that will be performed by ActOnDelayedCXXMethodParameter.
+void Sema::ActOnStartDelayedCXXMethodDeclaration(Scope *S, DeclPtrTy MethodD) {
+}
+
+/// ActOnDelayedCXXMethodParameter - We've already started a delayed
+/// C++ method declaration. We're (re-)introducing the given
+/// function parameter into scope for use in parsing later parts of
+/// the method declaration. For example, we could see an
+/// ActOnParamDefaultArgument event for this parameter.
+void Sema::ActOnDelayedCXXMethodParameter(Scope *S, DeclPtrTy ParamD) {
+  if (!ParamD)
+    return;
+
+  ParmVarDecl *Param = cast<ParmVarDecl>(ParamD.getAs<Decl>());
+
+  // If this parameter has an unparsed default argument, clear it out
+  // to make way for the parsed default argument.
+  if (Param->hasUnparsedDefaultArg())
+    Param->setDefaultArg(0);
+
+  S->AddDecl(DeclPtrTy::make(Param));
+  if (Param->getDeclName())
+    IdResolver.AddDecl(Param);
+}
+
+/// ActOnFinishDelayedCXXMethodDeclaration - We have finished
+/// processing the delayed method declaration for Method. The method
+/// declaration is now considered finished. There may be a separate
+/// ActOnStartOfFunctionDef action later (not necessarily
+/// immediately!) for this method, if it was also defined inside the
+/// class body.
+void Sema::ActOnFinishDelayedCXXMethodDeclaration(Scope *S, DeclPtrTy MethodD) {
+  if (!MethodD)
+    return;
+
+  AdjustDeclIfTemplate(MethodD);
+
+  FunctionDecl *Method = cast<FunctionDecl>(MethodD.getAs<Decl>());
+
+  // Now that we have our default arguments, check the constructor
+  // again. It could produce additional diagnostics or affect whether
+  // the class has implicitly-declared destructors, among other
+  // things.
+  if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(Method))
+    CheckConstructor(Constructor);
+
+  // Check the default arguments, which we may have added.
+  if (!Method->isInvalidDecl())
+    CheckCXXDefaultArguments(Method);
+}
+
+/// CheckConstructorDeclarator - Called by ActOnDeclarator to check
+/// the well-formedness of the constructor declarator @p D with type @p
+/// R. If there are any errors in the declarator, this routine will
+/// emit diagnostics and set the invalid bit to true.  In any case, the type
+/// will be updated to reflect a well-formed type for the constructor and
+/// returned.
+QualType Sema::CheckConstructorDeclarator(Declarator &D, QualType R,
+                                          FunctionDecl::StorageClass &SC) {
+  bool isVirtual = D.getDeclSpec().isVirtualSpecified();
+
+  // C++ [class.ctor]p3:
+  //   A constructor shall not be virtual (10.3) or static (9.4). A
+  //   constructor can be invoked for a const, volatile or const
+  //   volatile object. A constructor shall not be declared const,
+  //   volatile, or const volatile (9.3.2).
+  if (isVirtual) {
+    if (!D.isInvalidType())
+      Diag(D.getIdentifierLoc(), diag::err_constructor_cannot_be)
+        << "virtual" << SourceRange(D.getDeclSpec().getVirtualSpecLoc())
+        << SourceRange(D.getIdentifierLoc());
+    D.setInvalidType();
+  }
+  if (SC == FunctionDecl::Static) {
+    if (!D.isInvalidType())
+      Diag(D.getIdentifierLoc(), diag::err_constructor_cannot_be)
+        << "static" << SourceRange(D.getDeclSpec().getStorageClassSpecLoc())
+        << SourceRange(D.getIdentifierLoc());
+    D.setInvalidType();
+    SC = FunctionDecl::None;
+  }
+
+  DeclaratorChunk::FunctionTypeInfo &FTI = D.getTypeObject(0).Fun;
+  if (FTI.TypeQuals != 0) {
+    if (FTI.TypeQuals & Qualifiers::Const)
+      Diag(D.getIdentifierLoc(), diag::err_invalid_qualified_constructor)
+        << "const" << SourceRange(D.getIdentifierLoc());
+    if (FTI.TypeQuals & Qualifiers::Volatile)
+      Diag(D.getIdentifierLoc(), diag::err_invalid_qualified_constructor)
+        << "volatile" << SourceRange(D.getIdentifierLoc());
+    if (FTI.TypeQuals & Qualifiers::Restrict)
+      Diag(D.getIdentifierLoc(), diag::err_invalid_qualified_constructor)
+        << "restrict" << SourceRange(D.getIdentifierLoc());
+  }
+
+  // Rebuild the function type "R" without any type qualifiers (in
+  // case any of the errors above fired) and with "void" as the
+  // return type, since constructors don't have return types. We
+  // *always* have to do this, because GetTypeForDeclarator will
+  // put in a result type of "int" when none was specified.
+  const FunctionProtoType *Proto = R->getAs<FunctionProtoType>();
+  return Context.getFunctionType(Context.VoidTy, Proto->arg_type_begin(),
+                                 Proto->getNumArgs(),
+                                 Proto->isVariadic(), 0);
+}
+
+/// CheckConstructor - Checks a fully-formed constructor for
+/// well-formedness, issuing any diagnostics required. Returns true if
+/// the constructor declarator is invalid.
+void Sema::CheckConstructor(CXXConstructorDecl *Constructor) {
+  CXXRecordDecl *ClassDecl
+    = dyn_cast<CXXRecordDecl>(Constructor->getDeclContext());
+  if (!ClassDecl)
+    return Constructor->setInvalidDecl();
+
+  // C++ [class.copy]p3:
+  //   A declaration of a constructor for a class X is ill-formed if
+  //   its first parameter is of type (optionally cv-qualified) X and
+  //   either there are no other parameters or else all other
+  //   parameters have default arguments.
+  if (!Constructor->isInvalidDecl() &&
+      ((Constructor->getNumParams() == 1) ||
+       (Constructor->getNumParams() > 1 &&
+        Constructor->getParamDecl(1)->hasDefaultArg())) &&
+      Constructor->getTemplateSpecializationKind()
+                                              != TSK_ImplicitInstantiation) {
+    QualType ParamType = Constructor->getParamDecl(0)->getType();
+    QualType ClassTy = Context.getTagDeclType(ClassDecl);
+    if (Context.getCanonicalType(ParamType).getUnqualifiedType() == ClassTy) {
+      SourceLocation ParamLoc = Constructor->getParamDecl(0)->getLocation();
+      Diag(ParamLoc, diag::err_constructor_byvalue_arg)
+        << CodeModificationHint::CreateInsertion(ParamLoc, " const &");
+
+      // FIXME: Rather that making the constructor invalid, we should endeavor
+      // to fix the type.
+      Constructor->setInvalidDecl();
+    }
+  }
+
+  // Notify the class that we've added a constructor.
+  ClassDecl->addedConstructor(Context, Constructor);
+}
+
+/// CheckDestructor - Checks a fully-formed destructor for well-formedness, 
+/// issuing any diagnostics required. Returns true on error.
+bool Sema::CheckDestructor(CXXDestructorDecl *Destructor) {
+  CXXRecordDecl *RD = Destructor->getParent();
+  
+  if (Destructor->isVirtual()) {
+    SourceLocation Loc;
+    
+    if (!Destructor->isImplicit())
+      Loc = Destructor->getLocation();
+    else
+      Loc = RD->getLocation();
+    
+    // If we have a virtual destructor, look up the deallocation function
+    FunctionDecl *OperatorDelete = 0;
+    DeclarationName Name = 
+    Context.DeclarationNames.getCXXOperatorName(OO_Delete);
+    if (FindDeallocationFunction(Loc, RD, Name, OperatorDelete))
+      return true;
+    
+    Destructor->setOperatorDelete(OperatorDelete);
+  }
+  
+  return false;
+}
+
+static inline bool
+FTIHasSingleVoidArgument(DeclaratorChunk::FunctionTypeInfo &FTI) {
+  return (FTI.NumArgs == 1 && !FTI.isVariadic && FTI.ArgInfo[0].Ident == 0 &&
+          FTI.ArgInfo[0].Param &&
+          FTI.ArgInfo[0].Param.getAs<ParmVarDecl>()->getType()->isVoidType());
+}
+
+/// CheckDestructorDeclarator - Called by ActOnDeclarator to check
+/// the well-formednes of the destructor declarator @p D with type @p
+/// R. If there are any errors in the declarator, this routine will
+/// emit diagnostics and set the declarator to invalid.  Even if this happens,
+/// will be updated to reflect a well-formed type for the destructor and
+/// returned.
+QualType Sema::CheckDestructorDeclarator(Declarator &D,
+                                         FunctionDecl::StorageClass& SC) {
+  // C++ [class.dtor]p1:
+  //   [...] A typedef-name that names a class is a class-name
+  //   (7.1.3); however, a typedef-name that names a class shall not
+  //   be used as the identifier in the declarator for a destructor
+  //   declaration.
+  QualType DeclaratorType = GetTypeFromParser(D.getName().DestructorName);
+  if (isa<TypedefType>(DeclaratorType)) {
+    Diag(D.getIdentifierLoc(), diag::err_destructor_typedef_name)
+      << DeclaratorType;
+    D.setInvalidType();
+  }
+
+  // C++ [class.dtor]p2:
+  //   A destructor is used to destroy objects of its class type. A
+  //   destructor takes no parameters, and no return type can be
+  //   specified for it (not even void). The address of a destructor
+  //   shall not be taken. A destructor shall not be static. A
+  //   destructor can be invoked for a const, volatile or const
+  //   volatile object. A destructor shall not be declared const,
+  //   volatile or const volatile (9.3.2).
+  if (SC == FunctionDecl::Static) {
+    if (!D.isInvalidType())
+      Diag(D.getIdentifierLoc(), diag::err_destructor_cannot_be)
+        << "static" << SourceRange(D.getDeclSpec().getStorageClassSpecLoc())
+        << SourceRange(D.getIdentifierLoc());
+    SC = FunctionDecl::None;
+    D.setInvalidType();
+  }
+  if (D.getDeclSpec().hasTypeSpecifier() && !D.isInvalidType()) {
+    // Destructors don't have return types, but the parser will
+    // happily parse something like:
+    //
+    //   class X {
+    //     float ~X();
+    //   };
+    //
+    // The return type will be eliminated later.
+    Diag(D.getIdentifierLoc(), diag::err_destructor_return_type)
+      << SourceRange(D.getDeclSpec().getTypeSpecTypeLoc())
+      << SourceRange(D.getIdentifierLoc());
+  }
+
+  DeclaratorChunk::FunctionTypeInfo &FTI = D.getTypeObject(0).Fun;
+  if (FTI.TypeQuals != 0 && !D.isInvalidType()) {
+    if (FTI.TypeQuals & Qualifiers::Const)
+      Diag(D.getIdentifierLoc(), diag::err_invalid_qualified_destructor)
+        << "const" << SourceRange(D.getIdentifierLoc());
+    if (FTI.TypeQuals & Qualifiers::Volatile)
+      Diag(D.getIdentifierLoc(), diag::err_invalid_qualified_destructor)
+        << "volatile" << SourceRange(D.getIdentifierLoc());
+    if (FTI.TypeQuals & Qualifiers::Restrict)
+      Diag(D.getIdentifierLoc(), diag::err_invalid_qualified_destructor)
+        << "restrict" << SourceRange(D.getIdentifierLoc());
+    D.setInvalidType();
+  }
+
+  // Make sure we don't have any parameters.
+  if (FTI.NumArgs > 0 && !FTIHasSingleVoidArgument(FTI)) {
+    Diag(D.getIdentifierLoc(), diag::err_destructor_with_params);
+
+    // Delete the parameters.
+    FTI.freeArgs();
+    D.setInvalidType();
+  }
+
+  // Make sure the destructor isn't variadic.
+  if (FTI.isVariadic) {
+    Diag(D.getIdentifierLoc(), diag::err_destructor_variadic);
+    D.setInvalidType();
+  }
+
+  // Rebuild the function type "R" without any type qualifiers or
+  // parameters (in case any of the errors above fired) and with
+  // "void" as the return type, since destructors don't have return
+  // types. We *always* have to do this, because GetTypeForDeclarator
+  // will put in a result type of "int" when none was specified.
+  return Context.getFunctionType(Context.VoidTy, 0, 0, false, 0);
+}
+
+/// CheckConversionDeclarator - Called by ActOnDeclarator to check the
+/// well-formednes of the conversion function declarator @p D with
+/// type @p R. If there are any errors in the declarator, this routine
+/// will emit diagnostics and return true. Otherwise, it will return
+/// false. Either way, the type @p R will be updated to reflect a
+/// well-formed type for the conversion operator.
+void Sema::CheckConversionDeclarator(Declarator &D, QualType &R,
+                                     FunctionDecl::StorageClass& SC) {
+  // C++ [class.conv.fct]p1:
+  //   Neither parameter types nor return type can be specified. The
+  //   type of a conversion function (8.3.5) is "function taking no
+  //   parameter returning conversion-type-id."
+  if (SC == FunctionDecl::Static) {
+    if (!D.isInvalidType())
+      Diag(D.getIdentifierLoc(), diag::err_conv_function_not_member)
+        << "static" << SourceRange(D.getDeclSpec().getStorageClassSpecLoc())
+        << SourceRange(D.getIdentifierLoc());
+    D.setInvalidType();
+    SC = FunctionDecl::None;
+  }
+  if (D.getDeclSpec().hasTypeSpecifier() && !D.isInvalidType()) {
+    // Conversion functions don't have return types, but the parser will
+    // happily parse something like:
+    //
+    //   class X {
+    //     float operator bool();
+    //   };
+    //
+    // The return type will be changed later anyway.
+    Diag(D.getIdentifierLoc(), diag::err_conv_function_return_type)
+      << SourceRange(D.getDeclSpec().getTypeSpecTypeLoc())
+      << SourceRange(D.getIdentifierLoc());
+  }
+
+  // Make sure we don't have any parameters.
+  if (R->getAs<FunctionProtoType>()->getNumArgs() > 0) {
+    Diag(D.getIdentifierLoc(), diag::err_conv_function_with_params);
+
+    // Delete the parameters.
+    D.getTypeObject(0).Fun.freeArgs();
+    D.setInvalidType();
+  }
+
+  // Make sure the conversion function isn't variadic.
+  if (R->getAs<FunctionProtoType>()->isVariadic() && !D.isInvalidType()) {
+    Diag(D.getIdentifierLoc(), diag::err_conv_function_variadic);
+    D.setInvalidType();
+  }
+
+  // C++ [class.conv.fct]p4:
+  //   The conversion-type-id shall not represent a function type nor
+  //   an array type.
+  QualType ConvType = GetTypeFromParser(D.getName().ConversionFunctionId);
+  if (ConvType->isArrayType()) {
+    Diag(D.getIdentifierLoc(), diag::err_conv_function_to_array);
+    ConvType = Context.getPointerType(ConvType);
+    D.setInvalidType();
+  } else if (ConvType->isFunctionType()) {
+    Diag(D.getIdentifierLoc(), diag::err_conv_function_to_function);
+    ConvType = Context.getPointerType(ConvType);
+    D.setInvalidType();
+  }
+
+  // Rebuild the function type "R" without any parameters (in case any
+  // of the errors above fired) and with the conversion type as the
+  // return type.
+  R = Context.getFunctionType(ConvType, 0, 0, false,
+                              R->getAs<FunctionProtoType>()->getTypeQuals());
+
+  // C++0x explicit conversion operators.
+  if (D.getDeclSpec().isExplicitSpecified() && !getLangOptions().CPlusPlus0x)
+    Diag(D.getDeclSpec().getExplicitSpecLoc(),
+         diag::warn_explicit_conversion_functions)
+      << SourceRange(D.getDeclSpec().getExplicitSpecLoc());
+}
+
+/// ActOnConversionDeclarator - Called by ActOnDeclarator to complete
+/// the declaration of the given C++ conversion function. This routine
+/// is responsible for recording the conversion function in the C++
+/// class, if possible.
+Sema::DeclPtrTy Sema::ActOnConversionDeclarator(CXXConversionDecl *Conversion) {
+  assert(Conversion && "Expected to receive a conversion function declaration");
+
+  CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(Conversion->getDeclContext());
+
+  // Make sure we aren't redeclaring the conversion function.
+  QualType ConvType = Context.getCanonicalType(Conversion->getConversionType());
+
+  // C++ [class.conv.fct]p1:
+  //   [...] A conversion function is never used to convert a
+  //   (possibly cv-qualified) object to the (possibly cv-qualified)
+  //   same object type (or a reference to it), to a (possibly
+  //   cv-qualified) base class of that type (or a reference to it),
+  //   or to (possibly cv-qualified) void.
+  // FIXME: Suppress this warning if the conversion function ends up being a
+  // virtual function that overrides a virtual function in a base class.
+  QualType ClassType
+    = Context.getCanonicalType(Context.getTypeDeclType(ClassDecl));
+  if (const ReferenceType *ConvTypeRef = ConvType->getAs<ReferenceType>())
+    ConvType = ConvTypeRef->getPointeeType();
+  if (ConvType->isRecordType()) {
+    ConvType = Context.getCanonicalType(ConvType).getUnqualifiedType();
+    if (ConvType == ClassType)
+      Diag(Conversion->getLocation(), diag::warn_conv_to_self_not_used)
+        << ClassType;
+    else if (IsDerivedFrom(ClassType, ConvType))
+      Diag(Conversion->getLocation(), diag::warn_conv_to_base_not_used)
+        <<  ClassType << ConvType;
+  } else if (ConvType->isVoidType()) {
+    Diag(Conversion->getLocation(), diag::warn_conv_to_void_not_used)
+      << ClassType << ConvType;
+  }
+
+  if (Conversion->getPrimaryTemplate()) {
+    // ignore specializations
+  } else if (Conversion->getPreviousDeclaration()) {
+    if (FunctionTemplateDecl *ConversionTemplate
+                                  = Conversion->getDescribedFunctionTemplate()) {
+      if (ClassDecl->replaceConversion(
+                                   ConversionTemplate->getPreviousDeclaration(),
+                                       ConversionTemplate))
+        return DeclPtrTy::make(ConversionTemplate);
+    } else if (ClassDecl->replaceConversion(Conversion->getPreviousDeclaration(),
+                                            Conversion))
+      return DeclPtrTy::make(Conversion);
+    assert(Conversion->isInvalidDecl() && "Conversion should not get here.");
+  } else if (FunctionTemplateDecl *ConversionTemplate
+               = Conversion->getDescribedFunctionTemplate())
+    ClassDecl->addConversionFunction(ConversionTemplate);
+  else 
+    ClassDecl->addConversionFunction(Conversion);
+
+  return DeclPtrTy::make(Conversion);
+}
+
+//===----------------------------------------------------------------------===//
+// Namespace Handling
+//===----------------------------------------------------------------------===//
+
+/// ActOnStartNamespaceDef - This is called at the start of a namespace
+/// definition.
+Sema::DeclPtrTy Sema::ActOnStartNamespaceDef(Scope *NamespcScope,
+                                             SourceLocation IdentLoc,
+                                             IdentifierInfo *II,
+                                             SourceLocation LBrace,
+                                             AttributeList *AttrList) {
+  NamespaceDecl *Namespc =
+      NamespaceDecl::Create(Context, CurContext, IdentLoc, II);
+  Namespc->setLBracLoc(LBrace);
+
+  Scope *DeclRegionScope = NamespcScope->getParent();
+
+  ProcessDeclAttributeList(DeclRegionScope, Namespc, AttrList);
+
+  if (II) {
+    // C++ [namespace.def]p2:
+    // The identifier in an original-namespace-definition shall not have been
+    // previously defined in the declarative region in which the
+    // original-namespace-definition appears. The identifier in an
+    // original-namespace-definition is the name of the namespace. Subsequently
+    // in that declarative region, it is treated as an original-namespace-name.
+
+    NamedDecl *PrevDecl
+      = LookupSingleName(DeclRegionScope, II, LookupOrdinaryName,
+                         ForRedeclaration);
+
+    if (NamespaceDecl *OrigNS = dyn_cast_or_null<NamespaceDecl>(PrevDecl)) {
+      // This is an extended namespace definition.
+      // Attach this namespace decl to the chain of extended namespace
+      // definitions.
+      OrigNS->setNextNamespace(Namespc);
+      Namespc->setOriginalNamespace(OrigNS->getOriginalNamespace());
+
+      // Remove the previous declaration from the scope.
+      if (DeclRegionScope->isDeclScope(DeclPtrTy::make(OrigNS))) {
+        IdResolver.RemoveDecl(OrigNS);
+        DeclRegionScope->RemoveDecl(DeclPtrTy::make(OrigNS));
+      }
+    } else if (PrevDecl) {
+      // This is an invalid name redefinition.
+      Diag(Namespc->getLocation(), diag::err_redefinition_different_kind)
+       << Namespc->getDeclName();
+      Diag(PrevDecl->getLocation(), diag::note_previous_definition);
+      Namespc->setInvalidDecl();
+      // Continue on to push Namespc as current DeclContext and return it.
+    } else if (II->isStr("std") && 
+               CurContext->getLookupContext()->isTranslationUnit()) {
+      // This is the first "real" definition of the namespace "std", so update
+      // our cache of the "std" namespace to point at this definition.
+      if (StdNamespace) {
+        // We had already defined a dummy namespace "std". Link this new 
+        // namespace definition to the dummy namespace "std".
+        StdNamespace->setNextNamespace(Namespc);
+        StdNamespace->setLocation(IdentLoc);
+        Namespc->setOriginalNamespace(StdNamespace->getOriginalNamespace());
+      }
+      
+      // Make our StdNamespace cache point at the first real definition of the
+      // "std" namespace.
+      StdNamespace = Namespc;
+    }
+
+    PushOnScopeChains(Namespc, DeclRegionScope);
+  } else {
+    // Anonymous namespaces.
+    assert(Namespc->isAnonymousNamespace());
+    CurContext->addDecl(Namespc);
+
+    // Link the anonymous namespace into its parent.
+    NamespaceDecl *PrevDecl;
+    DeclContext *Parent = CurContext->getLookupContext();
+    if (TranslationUnitDecl *TU = dyn_cast<TranslationUnitDecl>(Parent)) {
+      PrevDecl = TU->getAnonymousNamespace();
+      TU->setAnonymousNamespace(Namespc);
+    } else {
+      NamespaceDecl *ND = cast<NamespaceDecl>(Parent);
+      PrevDecl = ND->getAnonymousNamespace();
+      ND->setAnonymousNamespace(Namespc);
+    }
+
+    // Link the anonymous namespace with its previous declaration.
+    if (PrevDecl) {
+      assert(PrevDecl->isAnonymousNamespace());
+      assert(!PrevDecl->getNextNamespace());
+      Namespc->setOriginalNamespace(PrevDecl->getOriginalNamespace());
+      PrevDecl->setNextNamespace(Namespc);
+    }
+
+    // C++ [namespace.unnamed]p1.  An unnamed-namespace-definition
+    //   behaves as if it were replaced by
+    //     namespace unique { /* empty body */ }
+    //     using namespace unique;
+    //     namespace unique { namespace-body }
+    //   where all occurrences of 'unique' in a translation unit are
+    //   replaced by the same identifier and this identifier differs
+    //   from all other identifiers in the entire program.
+
+    // We just create the namespace with an empty name and then add an
+    // implicit using declaration, just like the standard suggests.
+    //
+    // CodeGen enforces the "universally unique" aspect by giving all
+    // declarations semantically contained within an anonymous
+    // namespace internal linkage.
+
+    if (!PrevDecl) {
+      UsingDirectiveDecl* UD
+        = UsingDirectiveDecl::Create(Context, CurContext,
+                                     /* 'using' */ LBrace,
+                                     /* 'namespace' */ SourceLocation(),
+                                     /* qualifier */ SourceRange(),
+                                     /* NNS */ NULL,
+                                     /* identifier */ SourceLocation(),
+                                     Namespc,
+                                     /* Ancestor */ CurContext);
+      UD->setImplicit();
+      CurContext->addDecl(UD);
+    }
+  }
+
+  // Although we could have an invalid decl (i.e. the namespace name is a
+  // redefinition), push it as current DeclContext and try to continue parsing.
+  // FIXME: We should be able to push Namespc here, so that the each DeclContext
+  // for the namespace has the declarations that showed up in that particular
+  // namespace definition.
+  PushDeclContext(NamespcScope, Namespc);
+  return DeclPtrTy::make(Namespc);
+}
+
+/// getNamespaceDecl - Returns the namespace a decl represents. If the decl
+/// is a namespace alias, returns the namespace it points to.
+static inline NamespaceDecl *getNamespaceDecl(NamedDecl *D) {
+  if (NamespaceAliasDecl *AD = dyn_cast_or_null<NamespaceAliasDecl>(D))
+    return AD->getNamespace();
+  return dyn_cast_or_null<NamespaceDecl>(D);
+}
+
+/// ActOnFinishNamespaceDef - This callback is called after a namespace is
+/// exited. Decl is the DeclTy returned by ActOnStartNamespaceDef.
+void Sema::ActOnFinishNamespaceDef(DeclPtrTy D, SourceLocation RBrace) {
+  Decl *Dcl = D.getAs<Decl>();
+  NamespaceDecl *Namespc = dyn_cast_or_null<NamespaceDecl>(Dcl);
+  assert(Namespc && "Invalid parameter, expected NamespaceDecl");
+  Namespc->setRBracLoc(RBrace);
+  PopDeclContext();
+}
+
+Sema::DeclPtrTy Sema::ActOnUsingDirective(Scope *S,
+                                          SourceLocation UsingLoc,
+                                          SourceLocation NamespcLoc,
+                                          const CXXScopeSpec &SS,
+                                          SourceLocation IdentLoc,
+                                          IdentifierInfo *NamespcName,
+                                          AttributeList *AttrList) {
+  assert(!SS.isInvalid() && "Invalid CXXScopeSpec.");
+  assert(NamespcName && "Invalid NamespcName.");
+  assert(IdentLoc.isValid() && "Invalid NamespceName location.");
+  assert(S->getFlags() & Scope::DeclScope && "Invalid Scope.");
+
+  UsingDirectiveDecl *UDir = 0;
+
+  // Lookup namespace name.
+  LookupResult R(*this, NamespcName, IdentLoc, LookupNamespaceName);
+  LookupParsedName(R, S, &SS);
+  if (R.isAmbiguous())
+    return DeclPtrTy();
+
+  if (!R.empty()) {
+    NamedDecl *Named = R.getFoundDecl();
+    assert((isa<NamespaceDecl>(Named) || isa<NamespaceAliasDecl>(Named))
+        && "expected namespace decl");
+    // C++ [namespace.udir]p1:
+    //   A using-directive specifies that the names in the nominated
+    //   namespace can be used in the scope in which the
+    //   using-directive appears after the using-directive. During
+    //   unqualified name lookup (3.4.1), the names appear as if they
+    //   were declared in the nearest enclosing namespace which
+    //   contains both the using-directive and the nominated
+    //   namespace. [Note: in this context, "contains" means "contains
+    //   directly or indirectly". ]
+
+    // Find enclosing context containing both using-directive and
+    // nominated namespace.
+    NamespaceDecl *NS = getNamespaceDecl(Named);
+    DeclContext *CommonAncestor = cast<DeclContext>(NS);
+    while (CommonAncestor && !CommonAncestor->Encloses(CurContext))
+      CommonAncestor = CommonAncestor->getParent();
+
+    UDir = UsingDirectiveDecl::Create(Context, CurContext, UsingLoc, NamespcLoc,
+                                      SS.getRange(),
+                                      (NestedNameSpecifier *)SS.getScopeRep(),
+                                      IdentLoc, Named, CommonAncestor);
+    PushUsingDirective(S, UDir);
+  } else {
+    Diag(IdentLoc, diag::err_expected_namespace_name) << SS.getRange();
+  }
+
+  // FIXME: We ignore attributes for now.
+  delete AttrList;
+  return DeclPtrTy::make(UDir);
+}
+
+void Sema::PushUsingDirective(Scope *S, UsingDirectiveDecl *UDir) {
+  // If scope has associated entity, then using directive is at namespace
+  // or translation unit scope. We add UsingDirectiveDecls, into
+  // it's lookup structure.
+  if (DeclContext *Ctx = static_cast<DeclContext*>(S->getEntity()))
+    Ctx->addDecl(UDir);
+  else
+    // Otherwise it is block-sope. using-directives will affect lookup
+    // only to the end of scope.
+    S->PushUsingDirective(DeclPtrTy::make(UDir));
+}
+
+
+Sema::DeclPtrTy Sema::ActOnUsingDeclaration(Scope *S,
+                                            AccessSpecifier AS,
+                                            bool HasUsingKeyword,
+                                            SourceLocation UsingLoc,
+                                            const CXXScopeSpec &SS,
+                                            UnqualifiedId &Name,
+                                            AttributeList *AttrList,
+                                            bool IsTypeName,
+                                            SourceLocation TypenameLoc) {
+  assert(S->getFlags() & Scope::DeclScope && "Invalid Scope.");
+
+  switch (Name.getKind()) {
+  case UnqualifiedId::IK_Identifier:
+  case UnqualifiedId::IK_OperatorFunctionId:
+  case UnqualifiedId::IK_LiteralOperatorId:
+  case UnqualifiedId::IK_ConversionFunctionId:
+    break;
+      
+  case UnqualifiedId::IK_ConstructorName:
+  case UnqualifiedId::IK_ConstructorTemplateId:
+    // C++0x inherited constructors.
+    if (getLangOptions().CPlusPlus0x) break;
+
+    Diag(Name.getSourceRange().getBegin(), diag::err_using_decl_constructor)
+      << SS.getRange();
+    return DeclPtrTy();
+      
+  case UnqualifiedId::IK_DestructorName:
+    Diag(Name.getSourceRange().getBegin(), diag::err_using_decl_destructor)
+      << SS.getRange();
+    return DeclPtrTy();
+      
+  case UnqualifiedId::IK_TemplateId:
+    Diag(Name.getSourceRange().getBegin(), diag::err_using_decl_template_id)
+      << SourceRange(Name.TemplateId->LAngleLoc, Name.TemplateId->RAngleLoc);
+    return DeclPtrTy();
+  }
+  
+  DeclarationName TargetName = GetNameFromUnqualifiedId(Name);
+  if (!TargetName)
+    return DeclPtrTy();
+
+  // Warn about using declarations.
+  // TODO: store that the declaration was written without 'using' and
+  // talk about access decls instead of using decls in the
+  // diagnostics.
+  if (!HasUsingKeyword) {
+    UsingLoc = Name.getSourceRange().getBegin();
+    
+    Diag(UsingLoc, diag::warn_access_decl_deprecated)
+      << CodeModificationHint::CreateInsertion(SS.getRange().getBegin(),
+                                               "using ");
+  }
+
+  NamedDecl *UD = BuildUsingDeclaration(S, AS, UsingLoc, SS,
+                                        Name.getSourceRange().getBegin(),
+                                        TargetName, AttrList,
+                                        /* IsInstantiation */ false,
+                                        IsTypeName, TypenameLoc);
+  if (UD)
+    PushOnScopeChains(UD, S, /*AddToContext*/ false);
+
+  return DeclPtrTy::make(UD);
+}
+
+/// Determines whether to create a using shadow decl for a particular
+/// decl, given the set of decls existing prior to this using lookup.
+bool Sema::CheckUsingShadowDecl(UsingDecl *Using, NamedDecl *Orig,
+                                const LookupResult &Previous) {
+  // Diagnose finding a decl which is not from a base class of the
+  // current class.  We do this now because there are cases where this
+  // function will silently decide not to build a shadow decl, which
+  // will pre-empt further diagnostics.
+  //
+  // We don't need to do this in C++0x because we do the check once on
+  // the qualifier.
+  //
+  // FIXME: diagnose the following if we care enough:
+  //   struct A { int foo; };
+  //   struct B : A { using A::foo; };
+  //   template <class T> struct C : A {};
+  //   template <class T> struct D : C<T> { using B::foo; } // <---
+  // This is invalid (during instantiation) in C++03 because B::foo
+  // resolves to the using decl in B, which is not a base class of D<T>.
+  // We can't diagnose it immediately because C<T> is an unknown
+  // specialization.  The UsingShadowDecl in D<T> then points directly
+  // to A::foo, which will look well-formed when we instantiate.
+  // The right solution is to not collapse the shadow-decl chain.
+  if (!getLangOptions().CPlusPlus0x && CurContext->isRecord()) {
+    DeclContext *OrigDC = Orig->getDeclContext();
+
+    // Handle enums and anonymous structs.
+    if (isa<EnumDecl>(OrigDC)) OrigDC = OrigDC->getParent();
+    CXXRecordDecl *OrigRec = cast<CXXRecordDecl>(OrigDC);
+    while (OrigRec->isAnonymousStructOrUnion())
+      OrigRec = cast<CXXRecordDecl>(OrigRec->getDeclContext());
+
+    if (cast<CXXRecordDecl>(CurContext)->isProvablyNotDerivedFrom(OrigRec)) {
+      if (OrigDC == CurContext) {
+        Diag(Using->getLocation(),
+             diag::err_using_decl_nested_name_specifier_is_current_class)
+          << Using->getNestedNameRange();
+        Diag(Orig->getLocation(), diag::note_using_decl_target);
+        return true;
+      }
+
+      Diag(Using->getNestedNameRange().getBegin(),
+           diag::err_using_decl_nested_name_specifier_is_not_base_class)
+        << Using->getTargetNestedNameDecl()
+        << cast<CXXRecordDecl>(CurContext)
+        << Using->getNestedNameRange();
+      Diag(Orig->getLocation(), diag::note_using_decl_target);
+      return true;
+    }
+  }
+
+  if (Previous.empty()) return false;
+
+  NamedDecl *Target = Orig;
+  if (isa<UsingShadowDecl>(Target))
+    Target = cast<UsingShadowDecl>(Target)->getTargetDecl();
+
+  // If the target happens to be one of the previous declarations, we
+  // don't have a conflict.
+  // 
+  // FIXME: but we might be increasing its access, in which case we
+  // should redeclare it.
+  NamedDecl *NonTag = 0, *Tag = 0;
+  for (LookupResult::iterator I = Previous.begin(), E = Previous.end();
+         I != E; ++I) {
+    NamedDecl *D = (*I)->getUnderlyingDecl();
+    if (D->getCanonicalDecl() == Target->getCanonicalDecl())
+      return false;
+
+    (isa<TagDecl>(D) ? Tag : NonTag) = D;
+  }
+
+  if (Target->isFunctionOrFunctionTemplate()) {
+    FunctionDecl *FD;
+    if (isa<FunctionTemplateDecl>(Target))
+      FD = cast<FunctionTemplateDecl>(Target)->getTemplatedDecl();
+    else
+      FD = cast<FunctionDecl>(Target);
+
+    NamedDecl *OldDecl = 0;
+    switch (CheckOverload(FD, Previous, OldDecl)) {
+    case Ovl_Overload:
+      return false;
+
+    case Ovl_NonFunction:
+      Diag(Using->getLocation(), diag::err_using_decl_conflict);
+      break;
+      
+    // We found a decl with the exact signature.
+    case Ovl_Match:
+      if (isa<UsingShadowDecl>(OldDecl)) {
+        // Silently ignore the possible conflict.
+        return false;
+      }
+
+      // If we're in a record, we want to hide the target, so we
+      // return true (without a diagnostic) to tell the caller not to
+      // build a shadow decl.
+      if (CurContext->isRecord())
+        return true;
+
+      // If we're not in a record, this is an error.
+      Diag(Using->getLocation(), diag::err_using_decl_conflict);
+      break;
+    }
+
+    Diag(Target->getLocation(), diag::note_using_decl_target);
+    Diag(OldDecl->getLocation(), diag::note_using_decl_conflict);
+    return true;
+  }
+
+  // Target is not a function.
+
+  if (isa<TagDecl>(Target)) {
+    // No conflict between a tag and a non-tag.
+    if (!Tag) return false;
+
+    Diag(Using->getLocation(), diag::err_using_decl_conflict);
+    Diag(Target->getLocation(), diag::note_using_decl_target);
+    Diag(Tag->getLocation(), diag::note_using_decl_conflict);
+    return true;
+  }
+
+  // No conflict between a tag and a non-tag.
+  if (!NonTag) return false;
+
+  Diag(Using->getLocation(), diag::err_using_decl_conflict);
+  Diag(Target->getLocation(), diag::note_using_decl_target);
+  Diag(NonTag->getLocation(), diag::note_using_decl_conflict);
+  return true;
+}
+
+/// Builds a shadow declaration corresponding to a 'using' declaration.
+UsingShadowDecl *Sema::BuildUsingShadowDecl(Scope *S,
+                                            UsingDecl *UD,
+                                            NamedDecl *Orig) {
+
+  // If we resolved to another shadow declaration, just coalesce them.
+  NamedDecl *Target = Orig;
+  if (isa<UsingShadowDecl>(Target)) {
+    Target = cast<UsingShadowDecl>(Target)->getTargetDecl();
+    assert(!isa<UsingShadowDecl>(Target) && "nested shadow declaration");
+  }
+  
+  UsingShadowDecl *Shadow
+    = UsingShadowDecl::Create(Context, CurContext,
+                              UD->getLocation(), UD, Target);
+  UD->addShadowDecl(Shadow);
+
+  if (S)
+    PushOnScopeChains(Shadow, S);
+  else
+    CurContext->addDecl(Shadow);
+  Shadow->setAccess(UD->getAccess());
+
+  if (Orig->isInvalidDecl() || UD->isInvalidDecl())
+    Shadow->setInvalidDecl();
+
+  return Shadow;
+}
+
+/// Hides a using shadow declaration.  This is required by the current
+/// using-decl implementation when a resolvable using declaration in a
+/// class is followed by a declaration which would hide or override
+/// one or more of the using decl's targets; for example:
+///
+///   struct Base { void foo(int); };
+///   struct Derived : Base {
+///     using Base::foo;
+///     void foo(int);
+///   };
+///
+/// The governing language is C++03 [namespace.udecl]p12:
+///
+///   When a using-declaration brings names from a base class into a
+///   derived class scope, member functions in the derived class
+///   override and/or hide member functions with the same name and
+///   parameter types in a base class (rather than conflicting).
+///
+/// There are two ways to implement this:
+///   (1) optimistically create shadow decls when they're not hidden
+///       by existing declarations, or
+///   (2) don't create any shadow decls (or at least don't make them
+///       visible) until we've fully parsed/instantiated the class.
+/// The problem with (1) is that we might have to retroactively remove
+/// a shadow decl, which requires several O(n) operations because the
+/// decl structures are (very reasonably) not designed for removal.
+/// (2) avoids this but is very fiddly and phase-dependent.
+void Sema::HideUsingShadowDecl(Scope *S, UsingShadowDecl *Shadow) {
+  // Remove it from the DeclContext...
+  Shadow->getDeclContext()->removeDecl(Shadow);
+
+  // ...and the scope, if applicable...
+  if (S) {
+    S->RemoveDecl(DeclPtrTy::make(static_cast<Decl*>(Shadow)));
+    IdResolver.RemoveDecl(Shadow);
+  }
+
+  // ...and the using decl.
+  Shadow->getUsingDecl()->removeShadowDecl(Shadow);
+
+  // TODO: complain somehow if Shadow was used.  It shouldn't
+  // be possible for this to happen, because 
+}
+
+/// Builds a using declaration.
+///
+/// \param IsInstantiation - Whether this call arises from an
+///   instantiation of an unresolved using declaration.  We treat
+///   the lookup differently for these declarations.
+NamedDecl *Sema::BuildUsingDeclaration(Scope *S, AccessSpecifier AS,
+                                       SourceLocation UsingLoc,
+                                       const CXXScopeSpec &SS,
+                                       SourceLocation IdentLoc,
+                                       DeclarationName Name,
+                                       AttributeList *AttrList,
+                                       bool IsInstantiation,
+                                       bool IsTypeName,
+                                       SourceLocation TypenameLoc) {
+  assert(!SS.isInvalid() && "Invalid CXXScopeSpec.");
+  assert(IdentLoc.isValid() && "Invalid TargetName location.");
+
+  // FIXME: We ignore attributes for now.
+  delete AttrList;
+
+  if (SS.isEmpty()) {
+    Diag(IdentLoc, diag::err_using_requires_qualname);
+    return 0;
+  }
+
+  // Do the redeclaration lookup in the current scope.
+  LookupResult Previous(*this, Name, IdentLoc, LookupUsingDeclName,
+                        ForRedeclaration);
+  Previous.setHideTags(false);
+  if (S) {
+    LookupName(Previous, S);
+
+    // It is really dumb that we have to do this.
+    LookupResult::Filter F = Previous.makeFilter();
+    while (F.hasNext()) {
+      NamedDecl *D = F.next();
+      if (!isDeclInScope(D, CurContext, S))
+        F.erase();
+    }
+    F.done();
+  } else {
+    assert(IsInstantiation && "no scope in non-instantiation");
+    assert(CurContext->isRecord() && "scope not record in instantiation");
+    LookupQualifiedName(Previous, CurContext);
+  }
+
+  NestedNameSpecifier *NNS =
+    static_cast<NestedNameSpecifier *>(SS.getScopeRep());
+
+  // Check for invalid redeclarations.
+  if (CheckUsingDeclRedeclaration(UsingLoc, IsTypeName, SS, IdentLoc, Previous))
+    return 0;
+
+  // Check for bad qualifiers.
+  if (CheckUsingDeclQualifier(UsingLoc, SS, IdentLoc))
+    return 0;
+
+  DeclContext *LookupContext = computeDeclContext(SS);
+  NamedDecl *D;
+  if (!LookupContext) {
+    if (IsTypeName) {
+      // FIXME: not all declaration name kinds are legal here
+      D = UnresolvedUsingTypenameDecl::Create(Context, CurContext,
+                                              UsingLoc, TypenameLoc,
+                                              SS.getRange(), NNS,
+                                              IdentLoc, Name);
+    } else {
+      D = UnresolvedUsingValueDecl::Create(Context, CurContext,
+                                           UsingLoc, SS.getRange(), NNS,
+                                           IdentLoc, Name);
+    }
+  } else {
+    D = UsingDecl::Create(Context, CurContext, IdentLoc,
+                          SS.getRange(), UsingLoc, NNS, Name,
+                          IsTypeName);
+  }
+  D->setAccess(AS);
+  CurContext->addDecl(D);
+
+  if (!LookupContext) return D;
+  UsingDecl *UD = cast<UsingDecl>(D);
+
+  if (RequireCompleteDeclContext(SS)) {
+    UD->setInvalidDecl();
+    return UD;
+  }
+
+  // Look up the target name.
+
+  LookupResult R(*this, Name, IdentLoc, LookupOrdinaryName);
+
+  // Unlike most lookups, we don't always want to hide tag
+  // declarations: tag names are visible through the using declaration
+  // even if hidden by ordinary names, *except* in a dependent context
+  // where it's important for the sanity of two-phase lookup.
+  if (!IsInstantiation)
+    R.setHideTags(false);
+
+  LookupQualifiedName(R, LookupContext);
+
+  if (R.empty()) {
+    Diag(IdentLoc, diag::err_no_member) 
+      << Name << LookupContext << SS.getRange();
+    UD->setInvalidDecl();
+    return UD;
+  }
+
+  if (R.isAmbiguous()) {
+    UD->setInvalidDecl();
+    return UD;
+  }
+
+  if (IsTypeName) {
+    // If we asked for a typename and got a non-type decl, error out.
+    if (!R.getAsSingle<TypeDecl>()) {
+      Diag(IdentLoc, diag::err_using_typename_non_type);
+      for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I)
+        Diag((*I)->getUnderlyingDecl()->getLocation(),
+             diag::note_using_decl_target);
+      UD->setInvalidDecl();
+      return UD;
+    }
+  } else {
+    // If we asked for a non-typename and we got a type, error out,
+    // but only if this is an instantiation of an unresolved using
+    // decl.  Otherwise just silently find the type name.
+    if (IsInstantiation && R.getAsSingle<TypeDecl>()) {
+      Diag(IdentLoc, diag::err_using_dependent_value_is_type);
+      Diag(R.getFoundDecl()->getLocation(), diag::note_using_decl_target);
+      UD->setInvalidDecl();
+      return UD;
+    }
+  }
+
+  // C++0x N2914 [namespace.udecl]p6:
+  // A using-declaration shall not name a namespace.
+  if (R.getAsSingle<NamespaceDecl>()) {
+    Diag(IdentLoc, diag::err_using_decl_can_not_refer_to_namespace)
+      << SS.getRange();
+    UD->setInvalidDecl();
+    return UD;
+  }
+
+  for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I) {
+    if (!CheckUsingShadowDecl(UD, *I, Previous))
+      BuildUsingShadowDecl(S, UD, *I);
+  }
+
+  return UD;
+}
+
+/// Checks that the given using declaration is not an invalid
+/// redeclaration.  Note that this is checking only for the using decl
+/// itself, not for any ill-formedness among the UsingShadowDecls.
+bool Sema::CheckUsingDeclRedeclaration(SourceLocation UsingLoc,
+                                       bool isTypeName,
+                                       const CXXScopeSpec &SS,
+                                       SourceLocation NameLoc,
+                                       const LookupResult &Prev) {
+  // C++03 [namespace.udecl]p8:
+  // C++0x [namespace.udecl]p10:
+  //   A using-declaration is a declaration and can therefore be used
+  //   repeatedly where (and only where) multiple declarations are
+  //   allowed.
+  // That's only in file contexts.
+  if (CurContext->getLookupContext()->isFileContext())
+    return false;
+
+  NestedNameSpecifier *Qual
+    = static_cast<NestedNameSpecifier*>(SS.getScopeRep());
+
+  for (LookupResult::iterator I = Prev.begin(), E = Prev.end(); I != E; ++I) {
+    NamedDecl *D = *I;
+
+    bool DTypename;
+    NestedNameSpecifier *DQual;
+    if (UsingDecl *UD = dyn_cast<UsingDecl>(D)) {
+      DTypename = UD->isTypeName();
+      DQual = UD->getTargetNestedNameDecl();
+    } else if (UnresolvedUsingValueDecl *UD
+                 = dyn_cast<UnresolvedUsingValueDecl>(D)) {
+      DTypename = false;
+      DQual = UD->getTargetNestedNameSpecifier();
+    } else if (UnresolvedUsingTypenameDecl *UD
+                 = dyn_cast<UnresolvedUsingTypenameDecl>(D)) {
+      DTypename = true;
+      DQual = UD->getTargetNestedNameSpecifier();
+    } else continue;
+
+    // using decls differ if one says 'typename' and the other doesn't.
+    // FIXME: non-dependent using decls?
+    if (isTypeName != DTypename) continue;
+
+    // using decls differ if they name different scopes (but note that
+    // template instantiation can cause this check to trigger when it
+    // didn't before instantiation).
+    if (Context.getCanonicalNestedNameSpecifier(Qual) !=
+        Context.getCanonicalNestedNameSpecifier(DQual))
+      continue;
+
+    Diag(NameLoc, diag::err_using_decl_redeclaration) << SS.getRange();
+    Diag(D->getLocation(), diag::note_using_decl) << 1;
+    return true;
+  }
+
+  return false;
+}
+
+
+/// Checks that the given nested-name qualifier used in a using decl
+/// in the current context is appropriately related to the current
+/// scope.  If an error is found, diagnoses it and returns true.
+bool Sema::CheckUsingDeclQualifier(SourceLocation UsingLoc,
+                                   const CXXScopeSpec &SS,
+                                   SourceLocation NameLoc) {
+  DeclContext *NamedContext = computeDeclContext(SS);
+
+  if (!CurContext->isRecord()) {
+    // C++03 [namespace.udecl]p3:
+    // C++0x [namespace.udecl]p8:
+    //   A using-declaration for a class member shall be a member-declaration.
+
+    // If we weren't able to compute a valid scope, it must be a
+    // dependent class scope.
+    if (!NamedContext || NamedContext->isRecord()) {
+      Diag(NameLoc, diag::err_using_decl_can_not_refer_to_class_member)
+        << SS.getRange();
+      return true;
+    }
+
+    // Otherwise, everything is known to be fine.
+    return false;
+  }
+
+  // The current scope is a record.
+
+  // If the named context is dependent, we can't decide much.
+  if (!NamedContext) {
+    // FIXME: in C++0x, we can diagnose if we can prove that the
+    // nested-name-specifier does not refer to a base class, which is
+    // still possible in some cases.
+
+    // Otherwise we have to conservatively report that things might be
+    // okay.
+    return false;
+  }
+
+  if (!NamedContext->isRecord()) {
+    // Ideally this would point at the last name in the specifier,
+    // but we don't have that level of source info.
+    Diag(SS.getRange().getBegin(),
+         diag::err_using_decl_nested_name_specifier_is_not_class)
+      << (NestedNameSpecifier*) SS.getScopeRep() << SS.getRange();
+    return true;
+  }
+
+  if (getLangOptions().CPlusPlus0x) {
+    // C++0x [namespace.udecl]p3:
+    //   In a using-declaration used as a member-declaration, the
+    //   nested-name-specifier shall name a base class of the class
+    //   being defined.
+
+    if (cast<CXXRecordDecl>(CurContext)->isProvablyNotDerivedFrom(
+                                 cast<CXXRecordDecl>(NamedContext))) {
+      if (CurContext == NamedContext) {
+        Diag(NameLoc,
+             diag::err_using_decl_nested_name_specifier_is_current_class)
+          << SS.getRange();
+        return true;
+      }
+
+      Diag(SS.getRange().getBegin(),
+           diag::err_using_decl_nested_name_specifier_is_not_base_class)
+        << (NestedNameSpecifier*) SS.getScopeRep()
+        << cast<CXXRecordDecl>(CurContext)
+        << SS.getRange();
+      return true;
+    }
+
+    return false;
+  }
+
+  // C++03 [namespace.udecl]p4:
+  //   A using-declaration used as a member-declaration shall refer
+  //   to a member of a base class of the class being defined [etc.].
+
+  // Salient point: SS doesn't have to name a base class as long as
+  // lookup only finds members from base classes.  Therefore we can
+  // diagnose here only if we can prove that that can't happen,
+  // i.e. if the class hierarchies provably don't intersect.
+
+  // TODO: it would be nice if "definitely valid" results were cached
+  // in the UsingDecl and UsingShadowDecl so that these checks didn't
+  // need to be repeated.
+
+  struct UserData {
+    llvm::DenseSet<const CXXRecordDecl*> Bases;
+
+    static bool collect(const CXXRecordDecl *Base, void *OpaqueData) {
+      UserData *Data = reinterpret_cast<UserData*>(OpaqueData);
+      Data->Bases.insert(Base);
+      return true;
+    }
+
+    bool hasDependentBases(const CXXRecordDecl *Class) {
+      return !Class->forallBases(collect, this);
+    }
+
+    /// Returns true if the base is dependent or is one of the
+    /// accumulated base classes.
+    static bool doesNotContain(const CXXRecordDecl *Base, void *OpaqueData) {
+      UserData *Data = reinterpret_cast<UserData*>(OpaqueData);
+      return !Data->Bases.count(Base);
+    }
+
+    bool mightShareBases(const CXXRecordDecl *Class) {
+      return Bases.count(Class) || !Class->forallBases(doesNotContain, this);
+    }
+  };
+
+  UserData Data;
+
+  // Returns false if we find a dependent base.
+  if (Data.hasDependentBases(cast<CXXRecordDecl>(CurContext)))
+    return false;
+
+  // Returns false if the class has a dependent base or if it or one
+  // of its bases is present in the base set of the current context.
+  if (Data.mightShareBases(cast<CXXRecordDecl>(NamedContext)))
+    return false;
+
+  Diag(SS.getRange().getBegin(),
+       diag::err_using_decl_nested_name_specifier_is_not_base_class)
+    << (NestedNameSpecifier*) SS.getScopeRep()
+    << cast<CXXRecordDecl>(CurContext)
+    << SS.getRange();
+
+  return true;
+}
+
+Sema::DeclPtrTy Sema::ActOnNamespaceAliasDef(Scope *S,
+                                             SourceLocation NamespaceLoc,
+                                             SourceLocation AliasLoc,
+                                             IdentifierInfo *Alias,
+                                             const CXXScopeSpec &SS,
+                                             SourceLocation IdentLoc,
+                                             IdentifierInfo *Ident) {
+
+  // Lookup the namespace name.
+  LookupResult R(*this, Ident, IdentLoc, LookupNamespaceName);
+  LookupParsedName(R, S, &SS);
+
+  // Check if we have a previous declaration with the same name.
+  if (NamedDecl *PrevDecl
+        = LookupSingleName(S, Alias, LookupOrdinaryName, ForRedeclaration)) {
+    if (NamespaceAliasDecl *AD = dyn_cast<NamespaceAliasDecl>(PrevDecl)) {
+      // We already have an alias with the same name that points to the same
+      // namespace, so don't create a new one.
+      if (!R.isAmbiguous() && !R.empty() &&
+          AD->getNamespace() == getNamespaceDecl(R.getFoundDecl()))
+        return DeclPtrTy();
+    }
+
+    unsigned DiagID = isa<NamespaceDecl>(PrevDecl) ? diag::err_redefinition :
+      diag::err_redefinition_different_kind;
+    Diag(AliasLoc, DiagID) << Alias;
+    Diag(PrevDecl->getLocation(), diag::note_previous_definition);
+    return DeclPtrTy();
+  }
+
+  if (R.isAmbiguous())
+    return DeclPtrTy();
+
+  if (R.empty()) {
+    Diag(NamespaceLoc, diag::err_expected_namespace_name) << SS.getRange();
+    return DeclPtrTy();
+  }
+
+  NamespaceAliasDecl *AliasDecl =
+    NamespaceAliasDecl::Create(Context, CurContext, NamespaceLoc, AliasLoc,
+                               Alias, SS.getRange(),
+                               (NestedNameSpecifier *)SS.getScopeRep(),
+                               IdentLoc, R.getFoundDecl());
+
+  CurContext->addDecl(AliasDecl);
+  return DeclPtrTy::make(AliasDecl);
+}
+
+void Sema::DefineImplicitDefaultConstructor(SourceLocation CurrentLocation,
+                                            CXXConstructorDecl *Constructor) {
+  assert((Constructor->isImplicit() && Constructor->isDefaultConstructor() &&
+          !Constructor->isUsed()) &&
+    "DefineImplicitDefaultConstructor - call it for implicit default ctor");
+
+  CXXRecordDecl *ClassDecl
+    = cast<CXXRecordDecl>(Constructor->getDeclContext());
+  assert(ClassDecl && "DefineImplicitDefaultConstructor - invalid constructor");
+
+  DeclContext *PreviousContext = CurContext;
+  CurContext = Constructor;
+  if (SetBaseOrMemberInitializers(Constructor, 0, 0, true, false)) {
+    Diag(CurrentLocation, diag::note_member_synthesized_at) 
+      << CXXDefaultConstructor << Context.getTagDeclType(ClassDecl);
+    Constructor->setInvalidDecl();
+  } else {
+    Constructor->setUsed();
+  }
+  CurContext = PreviousContext;
+}
+
+void Sema::DefineImplicitDestructor(SourceLocation CurrentLocation,
+                                    CXXDestructorDecl *Destructor) {
+  assert((Destructor->isImplicit() && !Destructor->isUsed()) &&
+         "DefineImplicitDestructor - call it for implicit default dtor");
+  CXXRecordDecl *ClassDecl = Destructor->getParent();
+  assert(ClassDecl && "DefineImplicitDestructor - invalid destructor");
+
+  DeclContext *PreviousContext = CurContext;
+  CurContext = Destructor;
+
+  // C++ [class.dtor] p5
+  // Before the implicitly-declared default destructor for a class is
+  // implicitly defined, all the implicitly-declared default destructors
+  // for its base class and its non-static data members shall have been
+  // implicitly defined.
+  for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin(),
+       E = ClassDecl->bases_end(); Base != E; ++Base) {
+    CXXRecordDecl *BaseClassDecl
+      = cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl());
+    if (!BaseClassDecl->hasTrivialDestructor()) {
+      if (CXXDestructorDecl *BaseDtor =
+          const_cast<CXXDestructorDecl*>(BaseClassDecl->getDestructor(Context)))
+        MarkDeclarationReferenced(CurrentLocation, BaseDtor);
+      else
+        assert(false &&
+               "DefineImplicitDestructor - missing dtor in a base class");
+    }
+  }
+
+  for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(),
+       E = ClassDecl->field_end(); Field != E; ++Field) {
+    QualType FieldType = Context.getCanonicalType((*Field)->getType());
+    if (const ArrayType *Array = Context.getAsArrayType(FieldType))
+      FieldType = Array->getElementType();
+    if (const RecordType *FieldClassType = FieldType->getAs<RecordType>()) {
+      CXXRecordDecl *FieldClassDecl
+        = cast<CXXRecordDecl>(FieldClassType->getDecl());
+      if (!FieldClassDecl->hasTrivialDestructor()) {
+        if (CXXDestructorDecl *FieldDtor =
+            const_cast<CXXDestructorDecl*>(
+                                        FieldClassDecl->getDestructor(Context)))
+          MarkDeclarationReferenced(CurrentLocation, FieldDtor);
+        else
+          assert(false &&
+          "DefineImplicitDestructor - missing dtor in class of a data member");
+      }
+    }
+  }
+  
+  // FIXME: If CheckDestructor fails, we should emit a note about where the
+  // implicit destructor was needed.
+  if (CheckDestructor(Destructor)) {
+    Diag(CurrentLocation, diag::note_member_synthesized_at) 
+      << CXXDestructor << Context.getTagDeclType(ClassDecl);
+
+    Destructor->setInvalidDecl();
+    CurContext = PreviousContext;
+
+    return;
+  }
+  CurContext = PreviousContext;
+
+  Destructor->setUsed();
+}
+
+void Sema::DefineImplicitOverloadedAssign(SourceLocation CurrentLocation,
+                                          CXXMethodDecl *MethodDecl) {
+  assert((MethodDecl->isImplicit() && MethodDecl->isOverloadedOperator() &&
+          MethodDecl->getOverloadedOperator() == OO_Equal &&
+          !MethodDecl->isUsed()) &&
+         "DefineImplicitOverloadedAssign - call it for implicit assignment op");
+
+  CXXRecordDecl *ClassDecl
+    = cast<CXXRecordDecl>(MethodDecl->getDeclContext());
+
+  DeclContext *PreviousContext = CurContext;
+  CurContext = MethodDecl;
+
+  // C++[class.copy] p12
+  // Before the implicitly-declared copy assignment operator for a class is
+  // implicitly defined, all implicitly-declared copy assignment operators
+  // for its direct base classes and its nonstatic data members shall have
+  // been implicitly defined.
+  bool err = false;
+  for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin(),
+       E = ClassDecl->bases_end(); Base != E; ++Base) {
+    CXXRecordDecl *BaseClassDecl
+      = cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl());
+    if (CXXMethodDecl *BaseAssignOpMethod =
+          getAssignOperatorMethod(CurrentLocation, MethodDecl->getParamDecl(0), 
+                                  BaseClassDecl))
+      MarkDeclarationReferenced(CurrentLocation, BaseAssignOpMethod);
+  }
+  for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(),
+       E = ClassDecl->field_end(); Field != E; ++Field) {
+    QualType FieldType = Context.getCanonicalType((*Field)->getType());
+    if (const ArrayType *Array = Context.getAsArrayType(FieldType))
+      FieldType = Array->getElementType();
+    if (const RecordType *FieldClassType = FieldType->getAs<RecordType>()) {
+      CXXRecordDecl *FieldClassDecl
+        = cast<CXXRecordDecl>(FieldClassType->getDecl());
+      if (CXXMethodDecl *FieldAssignOpMethod =
+          getAssignOperatorMethod(CurrentLocation, MethodDecl->getParamDecl(0), 
+                                  FieldClassDecl))
+        MarkDeclarationReferenced(CurrentLocation, FieldAssignOpMethod);
+    } else if (FieldType->isReferenceType()) {
+      Diag(ClassDecl->getLocation(), diag::err_uninitialized_member_for_assign)
+      << Context.getTagDeclType(ClassDecl) << 0 << Field->getDeclName();
+      Diag(Field->getLocation(), diag::note_declared_at);
+      Diag(CurrentLocation, diag::note_first_required_here);
+      err = true;
+    } else if (FieldType.isConstQualified()) {
+      Diag(ClassDecl->getLocation(), diag::err_uninitialized_member_for_assign)
+      << Context.getTagDeclType(ClassDecl) << 1 << Field->getDeclName();
+      Diag(Field->getLocation(), diag::note_declared_at);
+      Diag(CurrentLocation, diag::note_first_required_here);
+      err = true;
+    }
+  }
+  if (!err)
+    MethodDecl->setUsed();
+
+  CurContext = PreviousContext;
+}
+
+CXXMethodDecl *
+Sema::getAssignOperatorMethod(SourceLocation CurrentLocation,
+                              ParmVarDecl *ParmDecl,
+                              CXXRecordDecl *ClassDecl) {
+  QualType LHSType = Context.getTypeDeclType(ClassDecl);
+  QualType RHSType(LHSType);
+  // If class's assignment operator argument is const/volatile qualified,
+  // look for operator = (const/volatile B&). Otherwise, look for
+  // operator = (B&).
+  RHSType = Context.getCVRQualifiedType(RHSType,
+                                     ParmDecl->getType().getCVRQualifiers());
+  ExprOwningPtr<Expr> LHS(this,  new (Context) DeclRefExpr(ParmDecl,
+                                                           LHSType,
+                                                           SourceLocation()));
+  ExprOwningPtr<Expr> RHS(this,  new (Context) DeclRefExpr(ParmDecl,
+                                                           RHSType,
+                                                           CurrentLocation));
+  Expr *Args[2] = { &*LHS, &*RHS };
+  OverloadCandidateSet CandidateSet(CurrentLocation);
+  AddMemberOperatorCandidates(clang::OO_Equal, SourceLocation(), Args, 2,
+                              CandidateSet);
+  OverloadCandidateSet::iterator Best;
+  if (BestViableFunction(CandidateSet, CurrentLocation, Best) == OR_Success)
+    return cast<CXXMethodDecl>(Best->Function);
+  assert(false &&
+         "getAssignOperatorMethod - copy assignment operator method not found");
+  return 0;
+}
+
+void Sema::DefineImplicitCopyConstructor(SourceLocation CurrentLocation,
+                                   CXXConstructorDecl *CopyConstructor,
+                                   unsigned TypeQuals) {
+  assert((CopyConstructor->isImplicit() &&
+          CopyConstructor->isCopyConstructor(TypeQuals) &&
+          !CopyConstructor->isUsed()) &&
+         "DefineImplicitCopyConstructor - call it for implicit copy ctor");
+
+  CXXRecordDecl *ClassDecl
+    = cast<CXXRecordDecl>(CopyConstructor->getDeclContext());
+  assert(ClassDecl && "DefineImplicitCopyConstructor - invalid constructor");
+
+  DeclContext *PreviousContext = CurContext;
+  CurContext = CopyConstructor;
+
+  // C++ [class.copy] p209
+  // Before the implicitly-declared copy constructor for a class is
+  // implicitly defined, all the implicitly-declared copy constructors
+  // for its base class and its non-static data members shall have been
+  // implicitly defined.
+  for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin();
+       Base != ClassDecl->bases_end(); ++Base) {
+    CXXRecordDecl *BaseClassDecl
+      = cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl());
+    if (CXXConstructorDecl *BaseCopyCtor =
+        BaseClassDecl->getCopyConstructor(Context, TypeQuals))
+      MarkDeclarationReferenced(CurrentLocation, BaseCopyCtor);
+  }
+  for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(),
+                                  FieldEnd = ClassDecl->field_end();
+       Field != FieldEnd; ++Field) {
+    QualType FieldType = Context.getCanonicalType((*Field)->getType());
+    if (const ArrayType *Array = Context.getAsArrayType(FieldType))
+      FieldType = Array->getElementType();
+    if (const RecordType *FieldClassType = FieldType->getAs<RecordType>()) {
+      CXXRecordDecl *FieldClassDecl
+        = cast<CXXRecordDecl>(FieldClassType->getDecl());
+      if (CXXConstructorDecl *FieldCopyCtor =
+          FieldClassDecl->getCopyConstructor(Context, TypeQuals))
+        MarkDeclarationReferenced(CurrentLocation, FieldCopyCtor);
+    }
+  }
+  CopyConstructor->setUsed();
+
+  CurContext = PreviousContext;
+}
+
+Sema::OwningExprResult
+Sema::BuildCXXConstructExpr(SourceLocation ConstructLoc, QualType DeclInitType,
+                            CXXConstructorDecl *Constructor,
+                            MultiExprArg ExprArgs,
+                            bool RequiresZeroInit,
+                            bool BaseInitialization) {
+  bool Elidable = false;
+
+  // C++ [class.copy]p15:
+  //   Whenever a temporary class object is copied using a copy constructor, and
+  //   this object and the copy have the same cv-unqualified type, an
+  //   implementation is permitted to treat the original and the copy as two
+  //   different ways of referring to the same object and not perform a copy at
+  //   all, even if the class copy constructor or destructor have side effects.
+
+  // FIXME: Is this enough?
+  if (Constructor->isCopyConstructor()) {
+    Expr *E = ((Expr **)ExprArgs.get())[0];
+    if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(E))
+      if (ICE->getCastKind() == CastExpr::CK_NoOp)
+        E = ICE->getSubExpr();
+    if (CXXFunctionalCastExpr *FCE = dyn_cast<CXXFunctionalCastExpr>(E))
+      E = FCE->getSubExpr();
+    while (CXXBindTemporaryExpr *BE = dyn_cast<CXXBindTemporaryExpr>(E))
+      E = BE->getSubExpr();
+    if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(E))
+      if (ICE->getCastKind() == CastExpr::CK_NoOp)
+        E = ICE->getSubExpr();
+
+    if (CallExpr *CE = dyn_cast<CallExpr>(E))
+      Elidable = !CE->getCallReturnType()->isReferenceType();
+    else if (isa<CXXTemporaryObjectExpr>(E))
+      Elidable = true;
+    else if (isa<CXXConstructExpr>(E))
+      Elidable = true;
+  }
+
+  return BuildCXXConstructExpr(ConstructLoc, DeclInitType, Constructor,
+                               Elidable, move(ExprArgs), RequiresZeroInit,
+                               BaseInitialization);
+}
+
+/// BuildCXXConstructExpr - Creates a complete call to a constructor,
+/// including handling of its default argument expressions.
+Sema::OwningExprResult
+Sema::BuildCXXConstructExpr(SourceLocation ConstructLoc, QualType DeclInitType,
+                            CXXConstructorDecl *Constructor, bool Elidable,
+                            MultiExprArg ExprArgs,
+                            bool RequiresZeroInit,
+                            bool BaseInitialization) {
+  unsigned NumExprs = ExprArgs.size();
+  Expr **Exprs = (Expr **)ExprArgs.release();
+
+  MarkDeclarationReferenced(ConstructLoc, Constructor);
+  return Owned(CXXConstructExpr::Create(Context, DeclInitType, ConstructLoc,
+                                        Constructor, Elidable, Exprs, NumExprs, 
+                                        RequiresZeroInit, BaseInitialization));
+}
+
+bool Sema::InitializeVarWithConstructor(VarDecl *VD,
+                                        CXXConstructorDecl *Constructor,
+                                        MultiExprArg Exprs) {
+  OwningExprResult TempResult =
+    BuildCXXConstructExpr(VD->getLocation(), VD->getType(), Constructor,
+                          move(Exprs));
+  if (TempResult.isInvalid())
+    return true;
+
+  Expr *Temp = TempResult.takeAs<Expr>();
+  MarkDeclarationReferenced(VD->getLocation(), Constructor);
+  Temp = MaybeCreateCXXExprWithTemporaries(Temp);
+  VD->setInit(Context, Temp);
+
+  return false;
+}
+
+void Sema::FinalizeVarWithDestructor(VarDecl *VD, const RecordType *Record) {
+  CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(Record->getDecl());
+  if (!ClassDecl->hasTrivialDestructor()) {
+    CXXDestructorDecl *Destructor = ClassDecl->getDestructor(Context);
+    MarkDeclarationReferenced(VD->getLocation(), Destructor);
+    CheckDestructorAccess(VD->getLocation(), Record);
+  }
+}
+
+/// AddCXXDirectInitializerToDecl - This action is called immediately after
+/// ActOnDeclarator, when a C++ direct initializer is present.
+/// e.g: "int x(1);"
+void Sema::AddCXXDirectInitializerToDecl(DeclPtrTy Dcl,
+                                         SourceLocation LParenLoc,
+                                         MultiExprArg Exprs,
+                                         SourceLocation *CommaLocs,
+                                         SourceLocation RParenLoc) {
+  assert(Exprs.size() != 0 && Exprs.get() && "missing expressions");
+  Decl *RealDecl = Dcl.getAs<Decl>();
+
+  // If there is no declaration, there was an error parsing it.  Just ignore
+  // the initializer.
+  if (RealDecl == 0)
+    return;
+
+  VarDecl *VDecl = dyn_cast<VarDecl>(RealDecl);
+  if (!VDecl) {
+    Diag(RealDecl->getLocation(), diag::err_illegal_initializer);
+    RealDecl->setInvalidDecl();
+    return;
+  }
+
+  // We will represent direct-initialization similarly to copy-initialization:
+  //    int x(1);  -as-> int x = 1;
+  //    ClassType x(a,b,c); -as-> ClassType x = ClassType(a,b,c);
+  //
+  // Clients that want to distinguish between the two forms, can check for
+  // direct initializer using VarDecl::hasCXXDirectInitializer().
+  // A major benefit is that clients that don't particularly care about which
+  // exactly form was it (like the CodeGen) can handle both cases without
+  // special case code.
+
+  // If either the declaration has a dependent type or if any of the expressions
+  // is type-dependent, we represent the initialization via a ParenListExpr for
+  // later use during template instantiation.
+  if (VDecl->getType()->isDependentType() ||
+      Expr::hasAnyTypeDependentArguments((Expr **)Exprs.get(), Exprs.size())) {
+    // Let clients know that initialization was done with a direct initializer.
+    VDecl->setCXXDirectInitializer(true);
+
+    // Store the initialization expressions as a ParenListExpr.
+    unsigned NumExprs = Exprs.size();
+    VDecl->setInit(Context,
+                   new (Context) ParenListExpr(Context, LParenLoc,
+                                               (Expr **)Exprs.release(),
+                                               NumExprs, RParenLoc));
+    return;
+  }
+
+
+  // C++ 8.5p11:
+  // The form of initialization (using parentheses or '=') is generally
+  // insignificant, but does matter when the entity being initialized has a
+  // class type.
+  QualType DeclInitType = VDecl->getType();
+  if (const ArrayType *Array = Context.getAsArrayType(DeclInitType))
+    DeclInitType = Context.getBaseElementType(Array);
+
+  if (RequireCompleteType(VDecl->getLocation(), VDecl->getType(),
+                          diag::err_typecheck_decl_incomplete_type)) {
+    VDecl->setInvalidDecl();
+    return;
+  }
+
+  // The variable can not have an abstract class type.
+  if (RequireNonAbstractType(VDecl->getLocation(), VDecl->getType(),
+                             diag::err_abstract_type_in_decl,
+                             AbstractVariableType))
+    VDecl->setInvalidDecl();
+
+  const VarDecl *Def;
+  if ((Def = VDecl->getDefinition()) && Def != VDecl) {
+    Diag(VDecl->getLocation(), diag::err_redefinition)
+    << VDecl->getDeclName();
+    Diag(Def->getLocation(), diag::note_previous_definition);
+    VDecl->setInvalidDecl();
+    return;
+  }
+  
+  // Capture the variable that is being initialized and the style of
+  // initialization.
+  InitializedEntity Entity = InitializedEntity::InitializeVariable(VDecl);
+  
+  // FIXME: Poor source location information.
+  InitializationKind Kind
+    = InitializationKind::CreateDirect(VDecl->getLocation(),
+                                       LParenLoc, RParenLoc);
+  
+  InitializationSequence InitSeq(*this, Entity, Kind, 
+                                 (Expr**)Exprs.get(), Exprs.size());
+  OwningExprResult Result = InitSeq.Perform(*this, Entity, Kind, move(Exprs));
+  if (Result.isInvalid()) {
+    VDecl->setInvalidDecl();
+    return;
+  }
+  
+  Result = MaybeCreateCXXExprWithTemporaries(move(Result));
+  VDecl->setInit(Context, Result.takeAs<Expr>());
+  VDecl->setCXXDirectInitializer(true);
+
+  if (const RecordType *Record = VDecl->getType()->getAs<RecordType>())
+    FinalizeVarWithDestructor(VDecl, Record);
+}
+
+/// \brief Add the applicable constructor candidates for an initialization
+/// by constructor.
+static void AddConstructorInitializationCandidates(Sema &SemaRef,
+                                                   QualType ClassType,
+                                                   Expr **Args,
+                                                   unsigned NumArgs,
+                                                   InitializationKind Kind,
+                                           OverloadCandidateSet &CandidateSet) {
+  // C++ [dcl.init]p14:
+  //   If the initialization is direct-initialization, or if it is
+  //   copy-initialization where the cv-unqualified version of the
+  //   source type is the same class as, or a derived class of, the
+  //   class of the destination, constructors are considered. The
+  //   applicable constructors are enumerated (13.3.1.3), and the
+  //   best one is chosen through overload resolution (13.3). The
+  //   constructor so selected is called to initialize the object,
+  //   with the initializer expression(s) as its argument(s). If no
+  //   constructor applies, or the overload resolution is ambiguous,
+  //   the initialization is ill-formed.
+  const RecordType *ClassRec = ClassType->getAs<RecordType>();
+  assert(ClassRec && "Can only initialize a class type here");
+  
+  // FIXME: When we decide not to synthesize the implicitly-declared
+  // constructors, we'll need to make them appear here.
+
+  const CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(ClassRec->getDecl());
+  DeclarationName ConstructorName
+    = SemaRef.Context.DeclarationNames.getCXXConstructorName(
+              SemaRef.Context.getCanonicalType(ClassType).getUnqualifiedType());
+  DeclContext::lookup_const_iterator Con, ConEnd;
+  for (llvm::tie(Con, ConEnd) = ClassDecl->lookup(ConstructorName);
+       Con != ConEnd; ++Con) {
+    // Find the constructor (which may be a template).
+    CXXConstructorDecl *Constructor = 0;
+    FunctionTemplateDecl *ConstructorTmpl= dyn_cast<FunctionTemplateDecl>(*Con);
+    if (ConstructorTmpl)
+      Constructor
+      = cast<CXXConstructorDecl>(ConstructorTmpl->getTemplatedDecl());
+    else
+      Constructor = cast<CXXConstructorDecl>(*Con);
+    
+    if ((Kind.getKind() == InitializationKind::IK_Direct) ||
+        (Kind.getKind() == InitializationKind::IK_Value) ||
+        (Kind.getKind() == InitializationKind::IK_Copy &&
+         Constructor->isConvertingConstructor(/*AllowExplicit=*/false)) ||
+        ((Kind.getKind() == InitializationKind::IK_Default) && 
+         Constructor->isDefaultConstructor())) {
+      if (ConstructorTmpl)
+        SemaRef.AddTemplateOverloadCandidate(ConstructorTmpl,
+                                             ConstructorTmpl->getAccess(),
+                                             /*ExplicitArgs*/ 0,
+                                             Args, NumArgs, CandidateSet);
+      else
+        SemaRef.AddOverloadCandidate(Constructor, Constructor->getAccess(),
+                                     Args, NumArgs, CandidateSet);
+    }
+  }
+}
+
+/// \brief Attempt to perform initialization by constructor 
+/// (C++ [dcl.init]p14), which may occur as part of direct-initialization or 
+/// copy-initialization. 
+///
+/// This routine determines whether initialization by constructor is possible,
+/// but it does not emit any diagnostics in the case where the initialization
+/// is ill-formed.
+///
+/// \param ClassType the type of the object being initialized, which must have
+/// class type.
+///
+/// \param Args the arguments provided to initialize the object
+///
+/// \param NumArgs the number of arguments provided to initialize the object
+///
+/// \param Kind the type of initialization being performed
+///
+/// \returns the constructor used to initialize the object, if successful.
+/// Otherwise, emits a diagnostic and returns NULL.
+CXXConstructorDecl *
+Sema::TryInitializationByConstructor(QualType ClassType,
+                                     Expr **Args, unsigned NumArgs,
+                                     SourceLocation Loc,
+                                     InitializationKind Kind) {
+  // Build the overload candidate set
+  OverloadCandidateSet CandidateSet(Loc);
+  AddConstructorInitializationCandidates(*this, ClassType, Args, NumArgs, Kind,
+                                         CandidateSet);
+  
+  // Determine whether we found a constructor we can use.
+  OverloadCandidateSet::iterator Best;
+  switch (BestViableFunction(CandidateSet, Loc, Best)) {
+    case OR_Success:
+    case OR_Deleted:
+      // We found a constructor. Return it.
+      return cast<CXXConstructorDecl>(Best->Function);
+      
+    case OR_No_Viable_Function:
+    case OR_Ambiguous:
+      // Overload resolution failed. Return nothing.
+      return 0;
+  }
+  
+  // Silence GCC warning
+  return 0;
+}
+
+/// \brief Given a constructor and the set of arguments provided for the
+/// constructor, convert the arguments and add any required default arguments
+/// to form a proper call to this constructor.
+///
+/// \returns true if an error occurred, false otherwise.
+bool 
+Sema::CompleteConstructorCall(CXXConstructorDecl *Constructor,
+                              MultiExprArg ArgsPtr,
+                              SourceLocation Loc,                                    
+                     ASTOwningVector<&ActionBase::DeleteExpr> &ConvertedArgs) {
+  // FIXME: This duplicates a lot of code from Sema::ConvertArgumentsForCall.
+  unsigned NumArgs = ArgsPtr.size();
+  Expr **Args = (Expr **)ArgsPtr.get();
+
+  const FunctionProtoType *Proto 
+    = Constructor->getType()->getAs<FunctionProtoType>();
+  assert(Proto && "Constructor without a prototype?");
+  unsigned NumArgsInProto = Proto->getNumArgs();
+  
+  // If too few arguments are available, we'll fill in the rest with defaults.
+  if (NumArgs < NumArgsInProto)
+    ConvertedArgs.reserve(NumArgsInProto);
+  else
+    ConvertedArgs.reserve(NumArgs);
+
+  VariadicCallType CallType = 
+    Proto->isVariadic() ? VariadicConstructor : VariadicDoesNotApply;
+  llvm::SmallVector<Expr *, 8> AllArgs;
+  bool Invalid = GatherArgumentsForCall(Loc, Constructor,
+                                        Proto, 0, Args, NumArgs, AllArgs, 
+                                        CallType);
+  for (unsigned i =0, size = AllArgs.size(); i < size; i++)
+    ConvertedArgs.push_back(AllArgs[i]);
+  return Invalid;
+}
+
+/// CompareReferenceRelationship - Compare the two types T1 and T2 to
+/// determine whether they are reference-related,
+/// reference-compatible, reference-compatible with added
+/// qualification, or incompatible, for use in C++ initialization by
+/// reference (C++ [dcl.ref.init]p4). Neither type can be a reference
+/// type, and the first type (T1) is the pointee type of the reference
+/// type being initialized.
+Sema::ReferenceCompareResult
+Sema::CompareReferenceRelationship(SourceLocation Loc,
+                                   QualType OrigT1, QualType OrigT2,
+                                   bool& DerivedToBase) {
+  assert(!OrigT1->isReferenceType() &&
+    "T1 must be the pointee type of the reference type");
+  assert(!OrigT2->isReferenceType() && "T2 cannot be a reference type");
+
+  QualType T1 = Context.getCanonicalType(OrigT1);
+  QualType T2 = Context.getCanonicalType(OrigT2);
+  Qualifiers T1Quals, T2Quals;
+  QualType UnqualT1 = Context.getUnqualifiedArrayType(T1, T1Quals);
+  QualType UnqualT2 = Context.getUnqualifiedArrayType(T2, T2Quals);
+
+  // C++ [dcl.init.ref]p4:
+  //   Given types "cv1 T1" and "cv2 T2," "cv1 T1" is
+  //   reference-related to "cv2 T2" if T1 is the same type as T2, or
+  //   T1 is a base class of T2.
+  if (UnqualT1 == UnqualT2)
+    DerivedToBase = false;
+  else if (!RequireCompleteType(Loc, OrigT1, PDiag()) &&
+           !RequireCompleteType(Loc, OrigT2, PDiag()) &&
+           IsDerivedFrom(UnqualT2, UnqualT1))
+    DerivedToBase = true;
+  else
+    return Ref_Incompatible;
+
+  // At this point, we know that T1 and T2 are reference-related (at
+  // least).
+
+  // If the type is an array type, promote the element qualifiers to the type
+  // for comparison.
+  if (isa<ArrayType>(T1) && T1Quals)
+    T1 = Context.getQualifiedType(UnqualT1, T1Quals);
+  if (isa<ArrayType>(T2) && T2Quals)
+    T2 = Context.getQualifiedType(UnqualT2, T2Quals);
+
+  // C++ [dcl.init.ref]p4:
+  //   "cv1 T1" is reference-compatible with "cv2 T2" if T1 is
+  //   reference-related to T2 and cv1 is the same cv-qualification
+  //   as, or greater cv-qualification than, cv2. For purposes of
+  //   overload resolution, cases for which cv1 is greater
+  //   cv-qualification than cv2 are identified as
+  //   reference-compatible with added qualification (see 13.3.3.2).
+  if (T1Quals.getCVRQualifiers() == T2Quals.getCVRQualifiers())
+    return Ref_Compatible;
+  else if (T1.isMoreQualifiedThan(T2))
+    return Ref_Compatible_With_Added_Qualification;
+  else
+    return Ref_Related;
+}
+
+/// CheckReferenceInit - Check the initialization of a reference
+/// variable with the given initializer (C++ [dcl.init.ref]). Init is
+/// the initializer (either a simple initializer or an initializer
+/// list), and DeclType is the type of the declaration. When ICS is
+/// non-null, this routine will compute the implicit conversion
+/// sequence according to C++ [over.ics.ref] and will not produce any
+/// diagnostics; when ICS is null, it will emit diagnostics when any
+/// errors are found. Either way, a return value of true indicates
+/// that there was a failure, a return value of false indicates that
+/// the reference initialization succeeded.
+///
+/// When @p SuppressUserConversions, user-defined conversions are
+/// suppressed.
+/// When @p AllowExplicit, we also permit explicit user-defined
+/// conversion functions.
+/// When @p ForceRValue, we unconditionally treat the initializer as an rvalue.
+/// When @p IgnoreBaseAccess, we don't do access control on to-base conversion.
+/// This is used when this is called from a C-style cast.
+bool
+Sema::CheckReferenceInit(Expr *&Init, QualType DeclType,
+                         SourceLocation DeclLoc,
+                         bool SuppressUserConversions,
+                         bool AllowExplicit, bool ForceRValue,
+                         ImplicitConversionSequence *ICS,
+                         bool IgnoreBaseAccess) {
+  assert(DeclType->isReferenceType() && "Reference init needs a reference");
+
+  QualType T1 = DeclType->getAs<ReferenceType>()->getPointeeType();
+  QualType T2 = Init->getType();
+
+  // If the initializer is the address of an overloaded function, try
+  // to resolve the overloaded function. If all goes well, T2 is the
+  // type of the resulting function.
+  if (Context.getCanonicalType(T2) == Context.OverloadTy) {
+    FunctionDecl *Fn = ResolveAddressOfOverloadedFunction(Init, DeclType,
+                                                          ICS != 0);
+    if (Fn) {
+      // Since we're performing this reference-initialization for
+      // real, update the initializer with the resulting function.
+      if (!ICS) {
+        if (DiagnoseUseOfDecl(Fn, DeclLoc))
+          return true; 
+
+        Init = FixOverloadedFunctionReference(Init, Fn);
+      }
+
+      T2 = Fn->getType();
+    }
+  }
+
+  // Compute some basic properties of the types and the initializer.
+  bool isRValRef = DeclType->isRValueReferenceType();
+  bool DerivedToBase = false;
+  Expr::isLvalueResult InitLvalue = ForceRValue ? Expr::LV_InvalidExpression :
+                                                  Init->isLvalue(Context);
+  ReferenceCompareResult RefRelationship
+    = CompareReferenceRelationship(DeclLoc, T1, T2, DerivedToBase);
+
+  // Most paths end in a failed conversion.
+  if (ICS) {
+    ICS->setBad();
+    ICS->Bad.init(BadConversionSequence::no_conversion, Init, DeclType);
+  }
+
+  // C++ [dcl.init.ref]p5:
+  //   A reference to type "cv1 T1" is initialized by an expression
+  //   of type "cv2 T2" as follows:
+
+  //     -- If the initializer expression
+
+  // Rvalue references cannot bind to lvalues (N2812).
+  // There is absolutely no situation where they can. In particular, note that
+  // this is ill-formed, even if B has a user-defined conversion to A&&:
+  //   B b;
+  //   A&& r = b;
+  if (isRValRef && InitLvalue == Expr::LV_Valid) {
+    if (!ICS)
+      Diag(DeclLoc, diag::err_lvalue_to_rvalue_ref)
+        << Init->getSourceRange();
+    return true;
+  }
+
+  bool BindsDirectly = false;
+  //       -- is an lvalue (but is not a bit-field), and "cv1 T1" is
+  //          reference-compatible with "cv2 T2," or
+  //
+  // Note that the bit-field check is skipped if we are just computing
+  // the implicit conversion sequence (C++ [over.best.ics]p2).
+  if (InitLvalue == Expr::LV_Valid && (ICS || !Init->getBitField()) &&
+      RefRelationship >= Ref_Compatible_With_Added_Qualification) {
+    BindsDirectly = true;
+
+    if (ICS) {
+      // C++ [over.ics.ref]p1:
+      //   When a parameter of reference type binds directly (8.5.3)
+      //   to an argument expression, the implicit conversion sequence
+      //   is the identity conversion, unless the argument expression
+      //   has a type that is a derived class of the parameter type,
+      //   in which case the implicit conversion sequence is a
+      //   derived-to-base Conversion (13.3.3.1).
+      ICS->setStandard();
+      ICS->Standard.First = ICK_Identity;
+      ICS->Standard.Second = DerivedToBase? ICK_Derived_To_Base : ICK_Identity;
+      ICS->Standard.Third = ICK_Identity;
+      ICS->Standard.FromTypePtr = T2.getAsOpaquePtr();
+      ICS->Standard.setToType(0, T2);
+      ICS->Standard.setToType(1, T1);
+      ICS->Standard.setToType(2, T1);
+      ICS->Standard.ReferenceBinding = true;
+      ICS->Standard.DirectBinding = true;
+      ICS->Standard.RRefBinding = false;
+      ICS->Standard.CopyConstructor = 0;
+
+      // Nothing more to do: the inaccessibility/ambiguity check for
+      // derived-to-base conversions is suppressed when we're
+      // computing the implicit conversion sequence (C++
+      // [over.best.ics]p2).
+      return false;
+    } else {
+      // Perform the conversion.
+      CastExpr::CastKind CK = CastExpr::CK_NoOp;
+      if (DerivedToBase)
+        CK = CastExpr::CK_DerivedToBase;
+      else if(CheckExceptionSpecCompatibility(Init, T1))
+        return true;
+      ImpCastExprToType(Init, T1, CK, /*isLvalue=*/true);
+    }
+  }
+
+  //       -- has a class type (i.e., T2 is a class type) and can be
+  //          implicitly converted to an lvalue of type "cv3 T3,"
+  //          where "cv1 T1" is reference-compatible with "cv3 T3"
+  //          92) (this conversion is selected by enumerating the
+  //          applicable conversion functions (13.3.1.6) and choosing
+  //          the best one through overload resolution (13.3)),
+  if (!isRValRef && !SuppressUserConversions && T2->isRecordType() &&
+      !RequireCompleteType(DeclLoc, T2, 0)) {
+    CXXRecordDecl *T2RecordDecl
+      = dyn_cast<CXXRecordDecl>(T2->getAs<RecordType>()->getDecl());
+
+    OverloadCandidateSet CandidateSet(DeclLoc);
+    const UnresolvedSetImpl *Conversions
+      = T2RecordDecl->getVisibleConversionFunctions();
+    for (UnresolvedSetImpl::iterator I = Conversions->begin(),
+           E = Conversions->end(); I != E; ++I) {
+      NamedDecl *D = *I;
+      CXXRecordDecl *ActingDC = cast<CXXRecordDecl>(D->getDeclContext());
+      if (isa<UsingShadowDecl>(D))
+        D = cast<UsingShadowDecl>(D)->getTargetDecl();
+
+      FunctionTemplateDecl *ConvTemplate
+        = dyn_cast<FunctionTemplateDecl>(D);
+      CXXConversionDecl *Conv;
+      if (ConvTemplate)
+        Conv = cast<CXXConversionDecl>(ConvTemplate->getTemplatedDecl());
+      else
+        Conv = cast<CXXConversionDecl>(D);
+      
+      // If the conversion function doesn't return a reference type,
+      // it can't be considered for this conversion.
+      if (Conv->getConversionType()->isLValueReferenceType() &&
+          (AllowExplicit || !Conv->isExplicit())) {
+        if (ConvTemplate)
+          AddTemplateConversionCandidate(ConvTemplate, I.getAccess(), ActingDC,
+                                         Init, DeclType, CandidateSet);
+        else
+          AddConversionCandidate(Conv, I.getAccess(), ActingDC, Init,
+                                 DeclType, CandidateSet);
+      }
+    }
+
+    OverloadCandidateSet::iterator Best;
+    switch (BestViableFunction(CandidateSet, DeclLoc, Best)) {
+    case OR_Success:
+      // This is a direct binding.
+      BindsDirectly = true;
+
+      if (ICS) {
+        // C++ [over.ics.ref]p1:
+        //
+        //   [...] If the parameter binds directly to the result of
+        //   applying a conversion function to the argument
+        //   expression, the implicit conversion sequence is a
+        //   user-defined conversion sequence (13.3.3.1.2), with the
+        //   second standard conversion sequence either an identity
+        //   conversion or, if the conversion function returns an
+        //   entity of a type that is a derived class of the parameter
+        //   type, a derived-to-base Conversion.
+        ICS->setUserDefined();
+        ICS->UserDefined.Before = Best->Conversions[0].Standard;
+        ICS->UserDefined.After = Best->FinalConversion;
+        ICS->UserDefined.ConversionFunction = Best->Function;
+        ICS->UserDefined.EllipsisConversion = false;
+        assert(ICS->UserDefined.After.ReferenceBinding &&
+               ICS->UserDefined.After.DirectBinding &&
+               "Expected a direct reference binding!");
+        return false;
+      } else {
+        OwningExprResult InitConversion =
+          BuildCXXCastArgument(DeclLoc, QualType(),
+                               CastExpr::CK_UserDefinedConversion,
+                               cast<CXXMethodDecl>(Best->Function), 
+                               Owned(Init));
+        Init = InitConversion.takeAs<Expr>();
+
+        if (CheckExceptionSpecCompatibility(Init, T1))
+          return true;
+        ImpCastExprToType(Init, T1, CastExpr::CK_UserDefinedConversion, 
+                          /*isLvalue=*/true);
+      }
+      break;
+
+    case OR_Ambiguous:
+      if (ICS) {
+        ICS->setAmbiguous();
+        for (OverloadCandidateSet::iterator Cand = CandidateSet.begin();
+             Cand != CandidateSet.end(); ++Cand)
+          if (Cand->Viable)
+            ICS->Ambiguous.addConversion(Cand->Function);
+        break;
+      }
+      Diag(DeclLoc, diag::err_ref_init_ambiguous) << DeclType << Init->getType()
+            << Init->getSourceRange();
+      PrintOverloadCandidates(CandidateSet, OCD_ViableCandidates, &Init, 1);
+      return true;
+
+    case OR_No_Viable_Function:
+    case OR_Deleted:
+      // There was no suitable conversion, or we found a deleted
+      // conversion; continue with other checks.
+      break;
+    }
+  }
+
+  if (BindsDirectly) {
+    // C++ [dcl.init.ref]p4:
+    //   [...] In all cases where the reference-related or
+    //   reference-compatible relationship of two types is used to
+    //   establish the validity of a reference binding, and T1 is a
+    //   base class of T2, a program that necessitates such a binding
+    //   is ill-formed if T1 is an inaccessible (clause 11) or
+    //   ambiguous (10.2) base class of T2.
+    //
+    // Note that we only check this condition when we're allowed to
+    // complain about errors, because we should not be checking for
+    // ambiguity (or inaccessibility) unless the reference binding
+    // actually happens.
+    if (DerivedToBase)
+      return CheckDerivedToBaseConversion(T2, T1, DeclLoc,
+                                          Init->getSourceRange(),
+                                          IgnoreBaseAccess);
+    else
+      return false;
+  }
+
+  //     -- Otherwise, the reference shall be to a non-volatile const
+  //        type (i.e., cv1 shall be const), or the reference shall be an
+  //        rvalue reference and the initializer expression shall be an rvalue.
+  if (!isRValRef && T1.getCVRQualifiers() != Qualifiers::Const) {
+    if (!ICS)
+      Diag(DeclLoc, diag::err_not_reference_to_const_init)
+        << T1.isVolatileQualified()
+        << T1 << int(InitLvalue != Expr::LV_Valid)
+        << T2 << Init->getSourceRange();
+    return true;
+  }
+
+  //       -- If the initializer expression is an rvalue, with T2 a
+  //          class type, and "cv1 T1" is reference-compatible with
+  //          "cv2 T2," the reference is bound in one of the
+  //          following ways (the choice is implementation-defined):
+  //
+  //          -- The reference is bound to the object represented by
+  //             the rvalue (see 3.10) or to a sub-object within that
+  //             object.
+  //
+  //          -- A temporary of type "cv1 T2" [sic] is created, and
+  //             a constructor is called to copy the entire rvalue
+  //             object into the temporary. The reference is bound to
+  //             the temporary or to a sub-object within the
+  //             temporary.
+  //
+  //          The constructor that would be used to make the copy
+  //          shall be callable whether or not the copy is actually
+  //          done.
+  //
+  // Note that C++0x [dcl.init.ref]p5 takes away this implementation
+  // freedom, so we will always take the first option and never build
+  // a temporary in this case. FIXME: We will, however, have to check
+  // for the presence of a copy constructor in C++98/03 mode.
+  if (InitLvalue != Expr::LV_Valid && T2->isRecordType() &&
+      RefRelationship >= Ref_Compatible_With_Added_Qualification) {
+    if (ICS) {
+      ICS->setStandard();
+      ICS->Standard.First = ICK_Identity;
+      ICS->Standard.Second = DerivedToBase? ICK_Derived_To_Base : ICK_Identity;
+      ICS->Standard.Third = ICK_Identity;
+      ICS->Standard.FromTypePtr = T2.getAsOpaquePtr();
+      ICS->Standard.setToType(0, T2);
+      ICS->Standard.setToType(1, T1);
+      ICS->Standard.setToType(2, T1);
+      ICS->Standard.ReferenceBinding = true;
+      ICS->Standard.DirectBinding = false;
+      ICS->Standard.RRefBinding = isRValRef;
+      ICS->Standard.CopyConstructor = 0;
+    } else {
+      CastExpr::CastKind CK = CastExpr::CK_NoOp;
+      if (DerivedToBase)
+        CK = CastExpr::CK_DerivedToBase;
+      else if(CheckExceptionSpecCompatibility(Init, T1))
+        return true;
+      ImpCastExprToType(Init, T1, CK, /*isLvalue=*/false);
+    }
+    return false;
+  }
+
+  //       -- Otherwise, a temporary of type "cv1 T1" is created and
+  //          initialized from the initializer expression using the
+  //          rules for a non-reference copy initialization (8.5). The
+  //          reference is then bound to the temporary. If T1 is
+  //          reference-related to T2, cv1 must be the same
+  //          cv-qualification as, or greater cv-qualification than,
+  //          cv2; otherwise, the program is ill-formed.
+  if (RefRelationship == Ref_Related) {
+    // If cv1 == cv2 or cv1 is a greater cv-qualified than cv2, then
+    // we would be reference-compatible or reference-compatible with
+    // added qualification. But that wasn't the case, so the reference
+    // initialization fails.
+    if (!ICS)
+      Diag(DeclLoc, diag::err_reference_init_drops_quals)
+        << T1 << int(InitLvalue != Expr::LV_Valid)
+        << T2 << Init->getSourceRange();
+    return true;
+  }
+
+  // If at least one of the types is a class type, the types are not
+  // related, and we aren't allowed any user conversions, the
+  // reference binding fails. This case is important for breaking
+  // recursion, since TryImplicitConversion below will attempt to
+  // create a temporary through the use of a copy constructor.
+  if (SuppressUserConversions && RefRelationship == Ref_Incompatible &&
+      (T1->isRecordType() || T2->isRecordType())) {
+    if (!ICS)
+      Diag(DeclLoc, diag::err_typecheck_convert_incompatible)
+        << DeclType << Init->getType() << AA_Initializing << Init->getSourceRange();
+    return true;
+  }
+
+  // Actually try to convert the initializer to T1.
+  if (ICS) {
+    // C++ [over.ics.ref]p2:
+    //
+    //   When a parameter of reference type is not bound directly to
+    //   an argument expression, the conversion sequence is the one
+    //   required to convert the argument expression to the
+    //   underlying type of the reference according to
+    //   13.3.3.1. Conceptually, this conversion sequence corresponds
+    //   to copy-initializing a temporary of the underlying type with
+    //   the argument expression. Any difference in top-level
+    //   cv-qualification is subsumed by the initialization itself
+    //   and does not constitute a conversion.
+    *ICS = TryImplicitConversion(Init, T1, SuppressUserConversions,
+                                 /*AllowExplicit=*/false,
+                                 /*ForceRValue=*/false,
+                                 /*InOverloadResolution=*/false);
+
+    // Of course, that's still a reference binding.
+    if (ICS->isStandard()) {
+      ICS->Standard.ReferenceBinding = true;
+      ICS->Standard.RRefBinding = isRValRef;
+    } else if (ICS->isUserDefined()) {
+      ICS->UserDefined.After.ReferenceBinding = true;
+      ICS->UserDefined.After.RRefBinding = isRValRef;
+    }
+    return ICS->isBad();
+  } else {
+    ImplicitConversionSequence Conversions;
+    bool badConversion = PerformImplicitConversion(Init, T1, AA_Initializing, 
+                                                   false, false, 
+                                                   Conversions);
+    if (badConversion) {
+      if (Conversions.isAmbiguous()) {
+        Diag(DeclLoc, 
+             diag::err_lvalue_to_rvalue_ambig_ref) << Init->getSourceRange();
+        for (int j = Conversions.Ambiguous.conversions().size()-1; 
+             j >= 0; j--) {
+          FunctionDecl *Func = Conversions.Ambiguous.conversions()[j];
+          NoteOverloadCandidate(Func);
+        }
+      }
+      else {
+        if (isRValRef)
+          Diag(DeclLoc, diag::err_lvalue_to_rvalue_ref) 
+            << Init->getSourceRange();
+        else
+          Diag(DeclLoc, diag::err_invalid_initialization)
+            << DeclType << Init->getType() << Init->getSourceRange();
+      }
+    }
+    return badConversion;
+  }
+}
+
+static inline bool
+CheckOperatorNewDeleteDeclarationScope(Sema &SemaRef, 
+                                       const FunctionDecl *FnDecl) {
+  const DeclContext *DC = FnDecl->getDeclContext()->getLookupContext();
+  if (isa<NamespaceDecl>(DC)) {
+    return SemaRef.Diag(FnDecl->getLocation(), 
+                        diag::err_operator_new_delete_declared_in_namespace)
+      << FnDecl->getDeclName();
+  }
+  
+  if (isa<TranslationUnitDecl>(DC) && 
+      FnDecl->getStorageClass() == FunctionDecl::Static) {
+    return SemaRef.Diag(FnDecl->getLocation(),
+                        diag::err_operator_new_delete_declared_static)
+      << FnDecl->getDeclName();
+  }
+  
+  return false;
+}
+
+static inline bool
+CheckOperatorNewDeleteTypes(Sema &SemaRef, const FunctionDecl *FnDecl,
+                            CanQualType ExpectedResultType,
+                            CanQualType ExpectedFirstParamType,
+                            unsigned DependentParamTypeDiag,
+                            unsigned InvalidParamTypeDiag) {
+  QualType ResultType = 
+    FnDecl->getType()->getAs<FunctionType>()->getResultType();
+
+  // Check that the result type is not dependent.
+  if (ResultType->isDependentType())
+    return SemaRef.Diag(FnDecl->getLocation(),
+                        diag::err_operator_new_delete_dependent_result_type)
+    << FnDecl->getDeclName() << ExpectedResultType;
+
+  // Check that the result type is what we expect.
+  if (SemaRef.Context.getCanonicalType(ResultType) != ExpectedResultType)
+    return SemaRef.Diag(FnDecl->getLocation(),
+                        diag::err_operator_new_delete_invalid_result_type) 
+    << FnDecl->getDeclName() << ExpectedResultType;
+  
+  // A function template must have at least 2 parameters.
+  if (FnDecl->getDescribedFunctionTemplate() && FnDecl->getNumParams() < 2)
+    return SemaRef.Diag(FnDecl->getLocation(),
+                      diag::err_operator_new_delete_template_too_few_parameters)
+        << FnDecl->getDeclName();
+  
+  // The function decl must have at least 1 parameter.
+  if (FnDecl->getNumParams() == 0)
+    return SemaRef.Diag(FnDecl->getLocation(),
+                        diag::err_operator_new_delete_too_few_parameters)
+      << FnDecl->getDeclName();
+ 
+  // Check the the first parameter type is not dependent.
+  QualType FirstParamType = FnDecl->getParamDecl(0)->getType();
+  if (FirstParamType->isDependentType())
+    return SemaRef.Diag(FnDecl->getLocation(), DependentParamTypeDiag)
+      << FnDecl->getDeclName() << ExpectedFirstParamType;
+
+  // Check that the first parameter type is what we expect.
+  if (SemaRef.Context.getCanonicalType(FirstParamType).getUnqualifiedType() != 
+      ExpectedFirstParamType)
+    return SemaRef.Diag(FnDecl->getLocation(), InvalidParamTypeDiag)
+    << FnDecl->getDeclName() << ExpectedFirstParamType;
+  
+  return false;
+}
+
+static bool
+CheckOperatorNewDeclaration(Sema &SemaRef, const FunctionDecl *FnDecl) {
+  // C++ [basic.stc.dynamic.allocation]p1:
+  //   A program is ill-formed if an allocation function is declared in a
+  //   namespace scope other than global scope or declared static in global 
+  //   scope.
+  if (CheckOperatorNewDeleteDeclarationScope(SemaRef, FnDecl))
+    return true;
+
+  CanQualType SizeTy = 
+    SemaRef.Context.getCanonicalType(SemaRef.Context.getSizeType());
+
+  // C++ [basic.stc.dynamic.allocation]p1:
+  //  The return type shall be void*. The first parameter shall have type 
+  //  std::size_t.
+  if (CheckOperatorNewDeleteTypes(SemaRef, FnDecl, SemaRef.Context.VoidPtrTy, 
+                                  SizeTy,
+                                  diag::err_operator_new_dependent_param_type,
+                                  diag::err_operator_new_param_type))
+    return true;
+
+  // C++ [basic.stc.dynamic.allocation]p1:
+  //  The first parameter shall not have an associated default argument.
+  if (FnDecl->getParamDecl(0)->hasDefaultArg())
+    return SemaRef.Diag(FnDecl->getLocation(),
+                        diag::err_operator_new_default_arg)
+      << FnDecl->getDeclName() << FnDecl->getParamDecl(0)->getDefaultArgRange();
+
+  return false;
+}
+
+static bool
+CheckOperatorDeleteDeclaration(Sema &SemaRef, const FunctionDecl *FnDecl) {
+  // C++ [basic.stc.dynamic.deallocation]p1:
+  //   A program is ill-formed if deallocation functions are declared in a
+  //   namespace scope other than global scope or declared static in global 
+  //   scope.
+  if (CheckOperatorNewDeleteDeclarationScope(SemaRef, FnDecl))
+    return true;
+
+  // C++ [basic.stc.dynamic.deallocation]p2:
+  //   Each deallocation function shall return void and its first parameter 
+  //   shall be void*.
+  if (CheckOperatorNewDeleteTypes(SemaRef, FnDecl, SemaRef.Context.VoidTy, 
+                                  SemaRef.Context.VoidPtrTy,
+                                 diag::err_operator_delete_dependent_param_type,
+                                 diag::err_operator_delete_param_type))
+    return true;
+
+  QualType FirstParamType = FnDecl->getParamDecl(0)->getType();
+  if (FirstParamType->isDependentType())
+    return SemaRef.Diag(FnDecl->getLocation(),
+                        diag::err_operator_delete_dependent_param_type)
+    << FnDecl->getDeclName() << SemaRef.Context.VoidPtrTy;
+
+  if (SemaRef.Context.getCanonicalType(FirstParamType) != 
+      SemaRef.Context.VoidPtrTy)
+    return SemaRef.Diag(FnDecl->getLocation(),
+                        diag::err_operator_delete_param_type)
+      << FnDecl->getDeclName() << SemaRef.Context.VoidPtrTy;
+  
+  return false;
+}
+
+/// CheckOverloadedOperatorDeclaration - Check whether the declaration
+/// of this overloaded operator is well-formed. If so, returns false;
+/// otherwise, emits appropriate diagnostics and returns true.
+bool Sema::CheckOverloadedOperatorDeclaration(FunctionDecl *FnDecl) {
+  assert(FnDecl && FnDecl->isOverloadedOperator() &&
+         "Expected an overloaded operator declaration");
+
+  OverloadedOperatorKind Op = FnDecl->getOverloadedOperator();
+
+  // C++ [over.oper]p5:
+  //   The allocation and deallocation functions, operator new,
+  //   operator new[], operator delete and operator delete[], are
+  //   described completely in 3.7.3. The attributes and restrictions
+  //   found in the rest of this subclause do not apply to them unless
+  //   explicitly stated in 3.7.3.
+  if (Op == OO_Delete || Op == OO_Array_Delete)
+    return CheckOperatorDeleteDeclaration(*this, FnDecl);
+  
+  if (Op == OO_New || Op == OO_Array_New)
+    return CheckOperatorNewDeclaration(*this, FnDecl);
+
+  // C++ [over.oper]p6:
+  //   An operator function shall either be a non-static member
+  //   function or be a non-member function and have at least one
+  //   parameter whose type is a class, a reference to a class, an
+  //   enumeration, or a reference to an enumeration.
+  if (CXXMethodDecl *MethodDecl = dyn_cast<CXXMethodDecl>(FnDecl)) {
+    if (MethodDecl->isStatic())
+      return Diag(FnDecl->getLocation(),
+                  diag::err_operator_overload_static) << FnDecl->getDeclName();
+  } else {
+    bool ClassOrEnumParam = false;
+    for (FunctionDecl::param_iterator Param = FnDecl->param_begin(),
+                                   ParamEnd = FnDecl->param_end();
+         Param != ParamEnd; ++Param) {
+      QualType ParamType = (*Param)->getType().getNonReferenceType();
+      if (ParamType->isDependentType() || ParamType->isRecordType() ||
+          ParamType->isEnumeralType()) {
+        ClassOrEnumParam = true;
+        break;
+      }
+    }
+
+    if (!ClassOrEnumParam)
+      return Diag(FnDecl->getLocation(),
+                  diag::err_operator_overload_needs_class_or_enum)
+        << FnDecl->getDeclName();
+  }
+
+  // C++ [over.oper]p8:
+  //   An operator function cannot have default arguments (8.3.6),
+  //   except where explicitly stated below.
+  //
+  // Only the function-call operator allows default arguments
+  // (C++ [over.call]p1).
+  if (Op != OO_Call) {
+    for (FunctionDecl::param_iterator Param = FnDecl->param_begin();
+         Param != FnDecl->param_end(); ++Param) {
+      if ((*Param)->hasDefaultArg())
+        return Diag((*Param)->getLocation(),
+                    diag::err_operator_overload_default_arg)
+          << FnDecl->getDeclName() << (*Param)->getDefaultArgRange();
+    }
+  }
+
+  static const bool OperatorUses[NUM_OVERLOADED_OPERATORS][3] = {
+    { false, false, false }
+#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \
+    , { Unary, Binary, MemberOnly }
+#include "clang/Basic/OperatorKinds.def"
+  };
+
+  bool CanBeUnaryOperator = OperatorUses[Op][0];
+  bool CanBeBinaryOperator = OperatorUses[Op][1];
+  bool MustBeMemberOperator = OperatorUses[Op][2];
+
+  // C++ [over.oper]p8:
+  //   [...] Operator functions cannot have more or fewer parameters
+  //   than the number required for the corresponding operator, as
+  //   described in the rest of this subclause.
+  unsigned NumParams = FnDecl->getNumParams()
+                     + (isa<CXXMethodDecl>(FnDecl)? 1 : 0);
+  if (Op != OO_Call &&
+      ((NumParams == 1 && !CanBeUnaryOperator) ||
+       (NumParams == 2 && !CanBeBinaryOperator) ||
+       (NumParams < 1) || (NumParams > 2))) {
+    // We have the wrong number of parameters.
+    unsigned ErrorKind;
+    if (CanBeUnaryOperator && CanBeBinaryOperator) {
+      ErrorKind = 2;  // 2 -> unary or binary.
+    } else if (CanBeUnaryOperator) {
+      ErrorKind = 0;  // 0 -> unary
+    } else {
+      assert(CanBeBinaryOperator &&
+             "All non-call overloaded operators are unary or binary!");
+      ErrorKind = 1;  // 1 -> binary
+    }
+
+    return Diag(FnDecl->getLocation(), diag::err_operator_overload_must_be)
+      << FnDecl->getDeclName() << NumParams << ErrorKind;
+  }
+
+  // Overloaded operators other than operator() cannot be variadic.
+  if (Op != OO_Call &&
+      FnDecl->getType()->getAs<FunctionProtoType>()->isVariadic()) {
+    return Diag(FnDecl->getLocation(), diag::err_operator_overload_variadic)
+      << FnDecl->getDeclName();
+  }
+
+  // Some operators must be non-static member functions.
+  if (MustBeMemberOperator && !isa<CXXMethodDecl>(FnDecl)) {
+    return Diag(FnDecl->getLocation(),
+                diag::err_operator_overload_must_be_member)
+      << FnDecl->getDeclName();
+  }
+
+  // C++ [over.inc]p1:
+  //   The user-defined function called operator++ implements the
+  //   prefix and postfix ++ operator. If this function is a member
+  //   function with no parameters, or a non-member function with one
+  //   parameter of class or enumeration type, it defines the prefix
+  //   increment operator ++ for objects of that type. If the function
+  //   is a member function with one parameter (which shall be of type
+  //   int) or a non-member function with two parameters (the second
+  //   of which shall be of type int), it defines the postfix
+  //   increment operator ++ for objects of that type.
+  if ((Op == OO_PlusPlus || Op == OO_MinusMinus) && NumParams == 2) {
+    ParmVarDecl *LastParam = FnDecl->getParamDecl(FnDecl->getNumParams() - 1);
+    bool ParamIsInt = false;
+    if (const BuiltinType *BT = LastParam->getType()->getAs<BuiltinType>())
+      ParamIsInt = BT->getKind() == BuiltinType::Int;
+
+    if (!ParamIsInt)
+      return Diag(LastParam->getLocation(),
+                  diag::err_operator_overload_post_incdec_must_be_int)
+        << LastParam->getType() << (Op == OO_MinusMinus);
+  }
+
+  // Notify the class if it got an assignment operator.
+  if (Op == OO_Equal) {
+    // Would have returned earlier otherwise.
+    assert(isa<CXXMethodDecl>(FnDecl) &&
+      "Overloaded = not member, but not filtered.");
+    CXXMethodDecl *Method = cast<CXXMethodDecl>(FnDecl);
+    Method->getParent()->addedAssignmentOperator(Context, Method);
+  }
+
+  return false;
+}
+
+/// CheckLiteralOperatorDeclaration - Check whether the declaration
+/// of this literal operator function is well-formed. If so, returns
+/// false; otherwise, emits appropriate diagnostics and returns true.
+bool Sema::CheckLiteralOperatorDeclaration(FunctionDecl *FnDecl) {
+  DeclContext *DC = FnDecl->getDeclContext();
+  Decl::Kind Kind = DC->getDeclKind();
+  if (Kind != Decl::TranslationUnit && Kind != Decl::Namespace &&
+      Kind != Decl::LinkageSpec) {
+    Diag(FnDecl->getLocation(), diag::err_literal_operator_outside_namespace)
+      << FnDecl->getDeclName();
+    return true;
+  }
+
+  bool Valid = false;
+
+  // FIXME: Check for the one valid template signature
+  // template <char...> type operator "" name();
+
+  if (FunctionDecl::param_iterator Param = FnDecl->param_begin()) {
+    // Check the first parameter
+    QualType T = (*Param)->getType();
+
+    // unsigned long long int and long double are allowed, but only
+    // alone.
+    // We also allow any character type; their omission seems to be a bug
+    // in n3000
+    if (Context.hasSameType(T, Context.UnsignedLongLongTy) ||
+        Context.hasSameType(T, Context.LongDoubleTy) ||
+        Context.hasSameType(T, Context.CharTy) ||
+        Context.hasSameType(T, Context.WCharTy) ||
+        Context.hasSameType(T, Context.Char16Ty) ||
+        Context.hasSameType(T, Context.Char32Ty)) {
+      if (++Param == FnDecl->param_end())
+        Valid = true;
+      goto FinishedParams;
+    }
+
+    // Otherwise it must be a pointer to const; let's strip those.
+    const PointerType *PT = T->getAs<PointerType>();
+    if (!PT)
+      goto FinishedParams;
+    T = PT->getPointeeType();
+    if (!T.isConstQualified())
+      goto FinishedParams;
+    T = T.getUnqualifiedType();
+
+    // Move on to the second parameter;
+    ++Param;
+
+    // If there is no second parameter, the first must be a const char *
+    if (Param == FnDecl->param_end()) {
+      if (Context.hasSameType(T, Context.CharTy))
+        Valid = true;
+      goto FinishedParams;
+    }
+
+    // const char *, const wchar_t*, const char16_t*, and const char32_t*
+    // are allowed as the first parameter to a two-parameter function
+    if (!(Context.hasSameType(T, Context.CharTy) ||
+          Context.hasSameType(T, Context.WCharTy) ||
+          Context.hasSameType(T, Context.Char16Ty) ||
+          Context.hasSameType(T, Context.Char32Ty)))
+      goto FinishedParams;
+
+    // The second and final parameter must be an std::size_t
+    T = (*Param)->getType().getUnqualifiedType();
+    if (Context.hasSameType(T, Context.getSizeType()) &&
+        ++Param == FnDecl->param_end())
+      Valid = true;
+  }
+
+  // FIXME: This diagnostic is absolutely terrible.
+FinishedParams:
+  if (!Valid) {
+    Diag(FnDecl->getLocation(), diag::err_literal_operator_params)
+      << FnDecl->getDeclName();
+    return true;
+  }
+
+  return false;
+}
+
+/// ActOnStartLinkageSpecification - Parsed the beginning of a C++
+/// linkage specification, including the language and (if present)
+/// the '{'. ExternLoc is the location of the 'extern', LangLoc is
+/// the location of the language string literal, which is provided
+/// by Lang/StrSize. LBraceLoc, if valid, provides the location of
+/// the '{' brace. Otherwise, this linkage specification does not
+/// have any braces.
+Sema::DeclPtrTy Sema::ActOnStartLinkageSpecification(Scope *S,
+                                                     SourceLocation ExternLoc,
+                                                     SourceLocation LangLoc,
+                                                     const char *Lang,
+                                                     unsigned StrSize,
+                                                     SourceLocation LBraceLoc) {
+  LinkageSpecDecl::LanguageIDs Language;
+  if (strncmp(Lang, "\"C\"", StrSize) == 0)
+    Language = LinkageSpecDecl::lang_c;
+  else if (strncmp(Lang, "\"C++\"", StrSize) == 0)
+    Language = LinkageSpecDecl::lang_cxx;
+  else {
+    Diag(LangLoc, diag::err_bad_language);
+    return DeclPtrTy();
+  }
+
+  // FIXME: Add all the various semantics of linkage specifications
+
+  LinkageSpecDecl *D = LinkageSpecDecl::Create(Context, CurContext,
+                                               LangLoc, Language,
+                                               LBraceLoc.isValid());
+  CurContext->addDecl(D);
+  PushDeclContext(S, D);
+  return DeclPtrTy::make(D);
+}
+
+/// ActOnFinishLinkageSpecification - Completely the definition of
+/// the C++ linkage specification LinkageSpec. If RBraceLoc is
+/// valid, it's the position of the closing '}' brace in a linkage
+/// specification that uses braces.
+Sema::DeclPtrTy Sema::ActOnFinishLinkageSpecification(Scope *S,
+                                                      DeclPtrTy LinkageSpec,
+                                                      SourceLocation RBraceLoc) {
+  if (LinkageSpec)
+    PopDeclContext();
+  return LinkageSpec;
+}
+
+/// \brief Perform semantic analysis for the variable declaration that
+/// occurs within a C++ catch clause, returning the newly-created
+/// variable.
+VarDecl *Sema::BuildExceptionDeclaration(Scope *S, QualType ExDeclType,
+                                         TypeSourceInfo *TInfo,
+                                         IdentifierInfo *Name,
+                                         SourceLocation Loc,
+                                         SourceRange Range) {
+  bool Invalid = false;
+
+  // Arrays and functions decay.
+  if (ExDeclType->isArrayType())
+    ExDeclType = Context.getArrayDecayedType(ExDeclType);
+  else if (ExDeclType->isFunctionType())
+    ExDeclType = Context.getPointerType(ExDeclType);
+
+  // C++ 15.3p1: The exception-declaration shall not denote an incomplete type.
+  // The exception-declaration shall not denote a pointer or reference to an
+  // incomplete type, other than [cv] void*.
+  // N2844 forbids rvalue references.
+  if (!ExDeclType->isDependentType() && ExDeclType->isRValueReferenceType()) {
+    Diag(Loc, diag::err_catch_rvalue_ref) << Range;
+    Invalid = true;
+  }
+
+  QualType BaseType = ExDeclType;
+  int Mode = 0; // 0 for direct type, 1 for pointer, 2 for reference
+  unsigned DK = diag::err_catch_incomplete;
+  if (const PointerType *Ptr = BaseType->getAs<PointerType>()) {
+    BaseType = Ptr->getPointeeType();
+    Mode = 1;
+    DK = diag::err_catch_incomplete_ptr;
+  } else if (const ReferenceType *Ref = BaseType->getAs<ReferenceType>()) {
+    // For the purpose of error recovery, we treat rvalue refs like lvalue refs.
+    BaseType = Ref->getPointeeType();
+    Mode = 2;
+    DK = diag::err_catch_incomplete_ref;
+  }
+  if (!Invalid && (Mode == 0 || !BaseType->isVoidType()) &&
+      !BaseType->isDependentType() && RequireCompleteType(Loc, BaseType, DK))
+    Invalid = true;
+
+  if (!Invalid && !ExDeclType->isDependentType() &&
+      RequireNonAbstractType(Loc, ExDeclType,
+                             diag::err_abstract_type_in_decl,
+                             AbstractVariableType))
+    Invalid = true;
+
+  // FIXME: Need to test for ability to copy-construct and destroy the
+  // exception variable.
+
+  // FIXME: Need to check for abstract classes.
+
+  VarDecl *ExDecl = VarDecl::Create(Context, CurContext, Loc,
+                                    Name, ExDeclType, TInfo, VarDecl::None);
+
+  if (Invalid)
+    ExDecl->setInvalidDecl();
+
+  return ExDecl;
+}
+
+/// ActOnExceptionDeclarator - Parsed the exception-declarator in a C++ catch
+/// handler.
+Sema::DeclPtrTy Sema::ActOnExceptionDeclarator(Scope *S, Declarator &D) {
+  TypeSourceInfo *TInfo = 0;
+  QualType ExDeclType = GetTypeForDeclarator(D, S, &TInfo);
+
+  bool Invalid = D.isInvalidType();
+  IdentifierInfo *II = D.getIdentifier();
+  if (NamedDecl *PrevDecl = LookupSingleName(S, II, LookupOrdinaryName)) {
+    // The scope should be freshly made just for us. There is just no way
+    // it contains any previous declaration.
+    assert(!S->isDeclScope(DeclPtrTy::make(PrevDecl)));
+    if (PrevDecl->isTemplateParameter()) {
+      // Maybe we will complain about the shadowed template parameter.
+      DiagnoseTemplateParameterShadow(D.getIdentifierLoc(), PrevDecl);
+    }
+  }
+
+  if (D.getCXXScopeSpec().isSet() && !Invalid) {
+    Diag(D.getIdentifierLoc(), diag::err_qualified_catch_declarator)
+      << D.getCXXScopeSpec().getRange();
+    Invalid = true;
+  }
+
+  VarDecl *ExDecl = BuildExceptionDeclaration(S, ExDeclType, TInfo,
+                                              D.getIdentifier(),
+                                              D.getIdentifierLoc(),
+                                            D.getDeclSpec().getSourceRange());
+
+  if (Invalid)
+    ExDecl->setInvalidDecl();
+
+  // Add the exception declaration into this scope.
+  if (II)
+    PushOnScopeChains(ExDecl, S);
+  else
+    CurContext->addDecl(ExDecl);
+
+  ProcessDeclAttributes(S, ExDecl, D);
+  return DeclPtrTy::make(ExDecl);
+}
+
+Sema::DeclPtrTy Sema::ActOnStaticAssertDeclaration(SourceLocation AssertLoc,
+                                                   ExprArg assertexpr,
+                                                   ExprArg assertmessageexpr) {
+  Expr *AssertExpr = (Expr *)assertexpr.get();
+  StringLiteral *AssertMessage =
+    cast<StringLiteral>((Expr *)assertmessageexpr.get());
+
+  if (!AssertExpr->isTypeDependent() && !AssertExpr->isValueDependent()) {
+    llvm::APSInt Value(32);
+    if (!AssertExpr->isIntegerConstantExpr(Value, Context)) {
+      Diag(AssertLoc, diag::err_static_assert_expression_is_not_constant) <<
+        AssertExpr->getSourceRange();
+      return DeclPtrTy();
+    }
+
+    if (Value == 0) {
+      Diag(AssertLoc, diag::err_static_assert_failed)
+        << AssertMessage->getString() << AssertExpr->getSourceRange();
+    }
+  }
+
+  assertexpr.release();
+  assertmessageexpr.release();
+  Decl *Decl = StaticAssertDecl::Create(Context, CurContext, AssertLoc,
+                                        AssertExpr, AssertMessage);
+
+  CurContext->addDecl(Decl);
+  return DeclPtrTy::make(Decl);
+}
+
+/// Handle a friend type declaration.  This works in tandem with
+/// ActOnTag.
+///
+/// Notes on friend class templates:
+///
+/// We generally treat friend class declarations as if they were
+/// declaring a class.  So, for example, the elaborated type specifier
+/// in a friend declaration is required to obey the restrictions of a
+/// class-head (i.e. no typedefs in the scope chain), template
+/// parameters are required to match up with simple template-ids, &c.
+/// However, unlike when declaring a template specialization, it's
+/// okay to refer to a template specialization without an empty
+/// template parameter declaration, e.g.
+///   friend class A<T>::B<unsigned>;
+/// We permit this as a special case; if there are any template
+/// parameters present at all, require proper matching, i.e.
+///   template <> template <class T> friend class A<int>::B;
+Sema::DeclPtrTy Sema::ActOnFriendTypeDecl(Scope *S, const DeclSpec &DS,
+                                          MultiTemplateParamsArg TempParams) {
+  SourceLocation Loc = DS.getSourceRange().getBegin();
+
+  assert(DS.isFriendSpecified());
+  assert(DS.getStorageClassSpec() == DeclSpec::SCS_unspecified);
+
+  // Try to convert the decl specifier to a type.  This works for
+  // friend templates because ActOnTag never produces a ClassTemplateDecl
+  // for a TUK_Friend.
+  Declarator TheDeclarator(DS, Declarator::MemberContext);
+  QualType T = GetTypeForDeclarator(TheDeclarator, S);
+  if (TheDeclarator.isInvalidType())
+    return DeclPtrTy();
+
+  // This is definitely an error in C++98.  It's probably meant to
+  // be forbidden in C++0x, too, but the specification is just
+  // poorly written.
+  //
+  // The problem is with declarations like the following:
+  //   template <T> friend A<T>::foo;
+  // where deciding whether a class C is a friend or not now hinges
+  // on whether there exists an instantiation of A that causes
+  // 'foo' to equal C.  There are restrictions on class-heads
+  // (which we declare (by fiat) elaborated friend declarations to
+  // be) that makes this tractable.
+  //
+  // FIXME: handle "template <> friend class A<T>;", which
+  // is possibly well-formed?  Who even knows?
+  if (TempParams.size() && !isa<ElaboratedType>(T)) {
+    Diag(Loc, diag::err_tagless_friend_type_template)
+      << DS.getSourceRange();
+    return DeclPtrTy();
+  }
+
+  // C++ [class.friend]p2:
+  //   An elaborated-type-specifier shall be used in a friend declaration
+  //   for a class.*
+  //   * The class-key of the elaborated-type-specifier is required.
+  // This is one of the rare places in Clang where it's legitimate to
+  // ask about the "spelling" of the type.
+  if (!getLangOptions().CPlusPlus0x && !isa<ElaboratedType>(T)) {
+    // If we evaluated the type to a record type, suggest putting
+    // a tag in front.
+    if (const RecordType *RT = T->getAs<RecordType>()) {
+      RecordDecl *RD = RT->getDecl();
+
+      std::string InsertionText = std::string(" ") + RD->getKindName();
+
+      Diag(DS.getTypeSpecTypeLoc(), diag::err_unelaborated_friend_type)
+        << (unsigned) RD->getTagKind()
+        << T
+        << SourceRange(DS.getFriendSpecLoc())
+        << CodeModificationHint::CreateInsertion(DS.getTypeSpecTypeLoc(),
+                                                 InsertionText);
+      return DeclPtrTy();
+    }else {
+      Diag(DS.getFriendSpecLoc(), diag::err_unexpected_friend)
+          << DS.getSourceRange();
+      return DeclPtrTy();
+    }
+  }
+
+  // Enum types cannot be friends.
+  if (T->getAs<EnumType>()) {
+    Diag(DS.getTypeSpecTypeLoc(), diag::err_enum_friend)
+      << SourceRange(DS.getFriendSpecLoc());
+    return DeclPtrTy();
+  }
+
+  // C++98 [class.friend]p1: A friend of a class is a function
+  //   or class that is not a member of the class . . .
+  // This is fixed in DR77, which just barely didn't make the C++03
+  // deadline.  It's also a very silly restriction that seriously
+  // affects inner classes and which nobody else seems to implement;
+  // thus we never diagnose it, not even in -pedantic.
+
+  Decl *D;
+  if (TempParams.size())
+    D = FriendTemplateDecl::Create(Context, CurContext, Loc,
+                                   TempParams.size(),
+                                 (TemplateParameterList**) TempParams.release(),
+                                   T.getTypePtr(),
+                                   DS.getFriendSpecLoc());
+  else
+    D = FriendDecl::Create(Context, CurContext, Loc, T.getTypePtr(),
+                           DS.getFriendSpecLoc());
+  D->setAccess(AS_public);
+  CurContext->addDecl(D);
+
+  return DeclPtrTy::make(D);
+}
+
+Sema::DeclPtrTy
+Sema::ActOnFriendFunctionDecl(Scope *S,
+                              Declarator &D,
+                              bool IsDefinition,
+                              MultiTemplateParamsArg TemplateParams) {
+  const DeclSpec &DS = D.getDeclSpec();
+
+  assert(DS.isFriendSpecified());
+  assert(DS.getStorageClassSpec() == DeclSpec::SCS_unspecified);
+
+  SourceLocation Loc = D.getIdentifierLoc();
+  TypeSourceInfo *TInfo = 0;
+  QualType T = GetTypeForDeclarator(D, S, &TInfo);
+
+  // C++ [class.friend]p1
+  //   A friend of a class is a function or class....
+  // Note that this sees through typedefs, which is intended.
+  // It *doesn't* see through dependent types, which is correct
+  // according to [temp.arg.type]p3:
+  //   If a declaration acquires a function type through a
+  //   type dependent on a template-parameter and this causes
+  //   a declaration that does not use the syntactic form of a
+  //   function declarator to have a function type, the program
+  //   is ill-formed.
+  if (!T->isFunctionType()) {
+    Diag(Loc, diag::err_unexpected_friend);
+
+    // It might be worthwhile to try to recover by creating an
+    // appropriate declaration.
+    return DeclPtrTy();
+  }
+
+  // C++ [namespace.memdef]p3
+  //  - If a friend declaration in a non-local class first declares a
+  //    class or function, the friend class or function is a member
+  //    of the innermost enclosing namespace.
+  //  - The name of the friend is not found by simple name lookup
+  //    until a matching declaration is provided in that namespace
+  //    scope (either before or after the class declaration granting
+  //    friendship).
+  //  - If a friend function is called, its name may be found by the
+  //    name lookup that considers functions from namespaces and
+  //    classes associated with the types of the function arguments.
+  //  - When looking for a prior declaration of a class or a function
+  //    declared as a friend, scopes outside the innermost enclosing
+  //    namespace scope are not considered.
+
+  CXXScopeSpec &ScopeQual = D.getCXXScopeSpec();
+  DeclarationName Name = GetNameForDeclarator(D);
+  assert(Name);
+
+  // The context we found the declaration in, or in which we should
+  // create the declaration.
+  DeclContext *DC;
+
+  // FIXME: handle local classes
+
+  // Recover from invalid scope qualifiers as if they just weren't there.
+  LookupResult Previous(*this, Name, D.getIdentifierLoc(), LookupOrdinaryName,
+                        ForRedeclaration);
+  if (!ScopeQual.isInvalid() && ScopeQual.isSet()) {
+    // FIXME: RequireCompleteDeclContext
+    DC = computeDeclContext(ScopeQual);
+
+    // FIXME: handle dependent contexts
+    if (!DC) return DeclPtrTy();
+
+    LookupQualifiedName(Previous, DC);
+
+    // If searching in that context implicitly found a declaration in
+    // a different context, treat it like it wasn't found at all.
+    // TODO: better diagnostics for this case.  Suggesting the right
+    // qualified scope would be nice...
+    // FIXME: getRepresentativeDecl() is not right here at all
+    if (Previous.empty() ||
+        !Previous.getRepresentativeDecl()->getDeclContext()->Equals(DC)) {
+      D.setInvalidType();
+      Diag(Loc, diag::err_qualified_friend_not_found) << Name << T;
+      return DeclPtrTy();
+    }
+
+    // C++ [class.friend]p1: A friend of a class is a function or
+    //   class that is not a member of the class . . .
+    if (DC->Equals(CurContext))
+      Diag(DS.getFriendSpecLoc(), diag::err_friend_is_member);
+
+  // Otherwise walk out to the nearest namespace scope looking for matches.
+  } else {
+    // TODO: handle local class contexts.
+
+    DC = CurContext;
+    while (true) {
+      // Skip class contexts.  If someone can cite chapter and verse
+      // for this behavior, that would be nice --- it's what GCC and
+      // EDG do, and it seems like a reasonable intent, but the spec
+      // really only says that checks for unqualified existing
+      // declarations should stop at the nearest enclosing namespace,
+      // not that they should only consider the nearest enclosing
+      // namespace.
+      while (DC->isRecord()) 
+        DC = DC->getParent();
+
+      LookupQualifiedName(Previous, DC);
+
+      // TODO: decide what we think about using declarations.
+      if (!Previous.empty())
+        break;
+      
+      if (DC->isFileContext()) break;
+      DC = DC->getParent();
+    }
+
+    // C++ [class.friend]p1: A friend of a class is a function or
+    //   class that is not a member of the class . . .
+    // C++0x changes this for both friend types and functions.
+    // Most C++ 98 compilers do seem to give an error here, so
+    // we do, too.
+    if (!Previous.empty() && DC->Equals(CurContext)
+        && !getLangOptions().CPlusPlus0x)
+      Diag(DS.getFriendSpecLoc(), diag::err_friend_is_member);
+  }
+
+  if (DC->isFileContext()) {
+    // This implies that it has to be an operator or function.
+    if (D.getName().getKind() == UnqualifiedId::IK_ConstructorName ||
+        D.getName().getKind() == UnqualifiedId::IK_DestructorName ||
+        D.getName().getKind() == UnqualifiedId::IK_ConversionFunctionId) {
+      Diag(Loc, diag::err_introducing_special_friend) <<
+        (D.getName().getKind() == UnqualifiedId::IK_ConstructorName ? 0 :
+         D.getName().getKind() == UnqualifiedId::IK_DestructorName ? 1 : 2);
+      return DeclPtrTy();
+    }
+  }
+
+  bool Redeclaration = false;
+  NamedDecl *ND = ActOnFunctionDeclarator(S, D, DC, T, TInfo, Previous,
+                                          move(TemplateParams),
+                                          IsDefinition,
+                                          Redeclaration);
+  if (!ND) return DeclPtrTy();
+
+  assert(ND->getDeclContext() == DC);
+  assert(ND->getLexicalDeclContext() == CurContext);
+
+  // Add the function declaration to the appropriate lookup tables,
+  // adjusting the redeclarations list as necessary.  We don't
+  // want to do this yet if the friending class is dependent.
+  //
+  // Also update the scope-based lookup if the target context's
+  // lookup context is in lexical scope.
+  if (!CurContext->isDependentContext()) {
+    DC = DC->getLookupContext();
+    DC->makeDeclVisibleInContext(ND, /* Recoverable=*/ false);
+    if (Scope *EnclosingScope = getScopeForDeclContext(S, DC))
+      PushOnScopeChains(ND, EnclosingScope, /*AddToContext=*/ false);
+  }
+
+  FriendDecl *FrD = FriendDecl::Create(Context, CurContext,
+                                       D.getIdentifierLoc(), ND,
+                                       DS.getFriendSpecLoc());
+  FrD->setAccess(AS_public);
+  CurContext->addDecl(FrD);
+
+  if (D.getName().getKind() == UnqualifiedId::IK_TemplateId)
+    FrD->setSpecialization(true);
+
+  return DeclPtrTy::make(ND);
+}
+
+void Sema::SetDeclDeleted(DeclPtrTy dcl, SourceLocation DelLoc) {
+  AdjustDeclIfTemplate(dcl);
+
+  Decl *Dcl = dcl.getAs<Decl>();
+  FunctionDecl *Fn = dyn_cast<FunctionDecl>(Dcl);
+  if (!Fn) {
+    Diag(DelLoc, diag::err_deleted_non_function);
+    return;
+  }
+  if (const FunctionDecl *Prev = Fn->getPreviousDeclaration()) {
+    Diag(DelLoc, diag::err_deleted_decl_not_first);
+    Diag(Prev->getLocation(), diag::note_previous_declaration);
+    // If the declaration wasn't the first, we delete the function anyway for
+    // recovery.
+  }
+  Fn->setDeleted();
+}
+
+static void SearchForReturnInStmt(Sema &Self, Stmt *S) {
+  for (Stmt::child_iterator CI = S->child_begin(), E = S->child_end(); CI != E;
+       ++CI) {
+    Stmt *SubStmt = *CI;
+    if (!SubStmt)
+      continue;
+    if (isa<ReturnStmt>(SubStmt))
+      Self.Diag(SubStmt->getSourceRange().getBegin(),
+           diag::err_return_in_constructor_handler);
+    if (!isa<Expr>(SubStmt))
+      SearchForReturnInStmt(Self, SubStmt);
+  }
+}
+
+void Sema::DiagnoseReturnInConstructorExceptionHandler(CXXTryStmt *TryBlock) {
+  for (unsigned I = 0, E = TryBlock->getNumHandlers(); I != E; ++I) {
+    CXXCatchStmt *Handler = TryBlock->getHandler(I);
+    SearchForReturnInStmt(*this, Handler);
+  }
+}
+
+bool Sema::CheckOverridingFunctionReturnType(const CXXMethodDecl *New,
+                                             const CXXMethodDecl *Old) {
+  QualType NewTy = New->getType()->getAs<FunctionType>()->getResultType();
+  QualType OldTy = Old->getType()->getAs<FunctionType>()->getResultType();
+
+  if (Context.hasSameType(NewTy, OldTy))
+    return false;
+
+  // Check if the return types are covariant
+  QualType NewClassTy, OldClassTy;
+
+  /// Both types must be pointers or references to classes.
+  if (const PointerType *NewPT = NewTy->getAs<PointerType>()) {
+    if (const PointerType *OldPT = OldTy->getAs<PointerType>()) {
+      NewClassTy = NewPT->getPointeeType();
+      OldClassTy = OldPT->getPointeeType();
+    }
+  } else if (const ReferenceType *NewRT = NewTy->getAs<ReferenceType>()) {
+    if (const ReferenceType *OldRT = OldTy->getAs<ReferenceType>()) {
+      if (NewRT->getTypeClass() == OldRT->getTypeClass()) {
+        NewClassTy = NewRT->getPointeeType();
+        OldClassTy = OldRT->getPointeeType();
+      }
+    }
+  }
+
+  // The return types aren't either both pointers or references to a class type.
+  if (NewClassTy.isNull()) {
+    Diag(New->getLocation(),
+         diag::err_different_return_type_for_overriding_virtual_function)
+      << New->getDeclName() << NewTy << OldTy;
+    Diag(Old->getLocation(), diag::note_overridden_virtual_function);
+
+    return true;
+  }
+
+  // C++ [class.virtual]p6:
+  //   If the return type of D::f differs from the return type of B::f, the 
+  //   class type in the return type of D::f shall be complete at the point of
+  //   declaration of D::f or shall be the class type D.
+  if (const RecordType *RT = NewClassTy->getAs<RecordType>()) {
+    if (!RT->isBeingDefined() &&
+        RequireCompleteType(New->getLocation(), NewClassTy, 
+                            PDiag(diag::err_covariant_return_incomplete)
+                              << New->getDeclName()))
+    return true;
+  }
+
+  if (!Context.hasSameUnqualifiedType(NewClassTy, OldClassTy)) {
+    // Check if the new class derives from the old class.
+    if (!IsDerivedFrom(NewClassTy, OldClassTy)) {
+      Diag(New->getLocation(),
+           diag::err_covariant_return_not_derived)
+      << New->getDeclName() << NewTy << OldTy;
+      Diag(Old->getLocation(), diag::note_overridden_virtual_function);
+      return true;
+    }
+
+    // Check if we the conversion from derived to base is valid.
+    if (CheckDerivedToBaseConversion(NewClassTy, OldClassTy, ADK_covariance,
+                      diag::err_covariant_return_ambiguous_derived_to_base_conv,
+                      // FIXME: Should this point to the return type?
+                      New->getLocation(), SourceRange(), New->getDeclName())) {
+      Diag(Old->getLocation(), diag::note_overridden_virtual_function);
+      return true;
+    }
+  }
+
+  // The qualifiers of the return types must be the same.
+  if (NewTy.getLocalCVRQualifiers() != OldTy.getLocalCVRQualifiers()) {
+    Diag(New->getLocation(),
+         diag::err_covariant_return_type_different_qualifications)
+    << New->getDeclName() << NewTy << OldTy;
+    Diag(Old->getLocation(), diag::note_overridden_virtual_function);
+    return true;
+  };
+
+
+  // The new class type must have the same or less qualifiers as the old type.
+  if (NewClassTy.isMoreQualifiedThan(OldClassTy)) {
+    Diag(New->getLocation(),
+         diag::err_covariant_return_type_class_type_more_qualified)
+    << New->getDeclName() << NewTy << OldTy;
+    Diag(Old->getLocation(), diag::note_overridden_virtual_function);
+    return true;
+  };
+
+  return false;
+}
+
+bool Sema::CheckOverridingFunctionAttributes(const CXXMethodDecl *New,
+                                             const CXXMethodDecl *Old)
+{
+  if (Old->hasAttr<FinalAttr>()) {
+    Diag(New->getLocation(), diag::err_final_function_overridden)
+      << New->getDeclName();
+    Diag(Old->getLocation(), diag::note_overridden_virtual_function);
+    return true;
+  }
+
+  return false;
+}
+
+/// \brief Mark the given method pure.
+///
+/// \param Method the method to be marked pure.
+///
+/// \param InitRange the source range that covers the "0" initializer.
+bool Sema::CheckPureMethod(CXXMethodDecl *Method, SourceRange InitRange) {
+  if (Method->isVirtual() || Method->getParent()->isDependentContext()) {
+    Method->setPure();
+    
+    // A class is abstract if at least one function is pure virtual.
+    Method->getParent()->setAbstract(true);
+    return false;
+  } 
+
+  if (!Method->isInvalidDecl())
+    Diag(Method->getLocation(), diag::err_non_virtual_pure)
+      << Method->getDeclName() << InitRange;
+  return true;
+}
+
+/// ActOnCXXEnterDeclInitializer - Invoked when we are about to parse
+/// an initializer for the out-of-line declaration 'Dcl'.  The scope
+/// is a fresh scope pushed for just this purpose.
+///
+/// After this method is called, according to [C++ 3.4.1p13], if 'Dcl' is a
+/// static data member of class X, names should be looked up in the scope of
+/// class X.
+void Sema::ActOnCXXEnterDeclInitializer(Scope *S, DeclPtrTy Dcl) {
+  // If there is no declaration, there was an error parsing it.
+  Decl *D = Dcl.getAs<Decl>();
+  if (D == 0) return;
+
+  // We should only get called for declarations with scope specifiers, like:
+  //   int foo::bar;
+  assert(D->isOutOfLine());
+  EnterDeclaratorContext(S, D->getDeclContext());
+}
+
+/// ActOnCXXExitDeclInitializer - Invoked after we are finished parsing an
+/// initializer for the out-of-line declaration 'Dcl'.
+void Sema::ActOnCXXExitDeclInitializer(Scope *S, DeclPtrTy Dcl) {
+  // If there is no declaration, there was an error parsing it.
+  Decl *D = Dcl.getAs<Decl>();
+  if (D == 0) return;
+
+  assert(D->isOutOfLine());
+  ExitDeclaratorContext(S);
+}
+
+/// ActOnCXXConditionDeclarationExpr - Parsed a condition declaration of a
+/// C++ if/switch/while/for statement.
+/// e.g: "if (int x = f()) {...}"
+Action::DeclResult
+Sema::ActOnCXXConditionDeclaration(Scope *S, Declarator &D) {
+  // C++ 6.4p2:
+  // The declarator shall not specify a function or an array.
+  // The type-specifier-seq shall not contain typedef and shall not declare a
+  // new class or enumeration.
+  assert(D.getDeclSpec().getStorageClassSpec() != DeclSpec::SCS_typedef &&
+         "Parser allowed 'typedef' as storage class of condition decl.");
+  
+  TypeSourceInfo *TInfo = 0;
+  TagDecl *OwnedTag = 0;
+  QualType Ty = GetTypeForDeclarator(D, S, &TInfo, &OwnedTag);
+  
+  if (Ty->isFunctionType()) { // The declarator shall not specify a function...
+                              // We exit without creating a CXXConditionDeclExpr because a FunctionDecl
+                              // would be created and CXXConditionDeclExpr wants a VarDecl.
+    Diag(D.getIdentifierLoc(), diag::err_invalid_use_of_function_type)
+      << D.getSourceRange();
+    return DeclResult();
+  } else if (OwnedTag && OwnedTag->isDefinition()) {
+    // The type-specifier-seq shall not declare a new class or enumeration.
+    Diag(OwnedTag->getLocation(), diag::err_type_defined_in_condition);
+  }
+  
+  DeclPtrTy Dcl = ActOnDeclarator(S, D);
+  if (!Dcl)
+    return DeclResult();
+
+  VarDecl *VD = cast<VarDecl>(Dcl.getAs<Decl>());
+  VD->setDeclaredInCondition(true);
+  return Dcl;
+}
+
+void Sema::MaybeMarkVirtualMembersReferenced(SourceLocation Loc,
+                                             CXXMethodDecl *MD) {
+  // Ignore dependent types.
+  if (MD->isDependentContext())
+    return;
+  
+  CXXRecordDecl *RD = MD->getParent();
+  
+  // Ignore classes without a vtable.
+  if (!RD->isDynamicClass())
+    return;
+
+  // Ignore declarations that are not definitions.
+  if (!MD->isThisDeclarationADefinition())
+    return;
+  
+  if (isa<CXXConstructorDecl>(MD)) {
+    switch (MD->getParent()->getTemplateSpecializationKind()) {
+    case TSK_Undeclared:
+    case TSK_ExplicitSpecialization:
+      // Classes that aren't instantiations of templates don't need their
+      // virtual methods marked until we see the definition of the key 
+      // function.
+      return;
+        
+    case TSK_ImplicitInstantiation:
+    case TSK_ExplicitInstantiationDeclaration:
+    case TSK_ExplicitInstantiationDefinition:
+      // This is a constructor of a class template; mark all of the virtual
+      // members as referenced to ensure that they get instantiatied.
+      break;
+    }
+  } else if (!MD->isOutOfLine()) {
+    // Consider only out-of-line definitions of member functions. When we see
+    // an inline definition, it's too early to compute the key function.
+    return;
+  } else if (const CXXMethodDecl *KeyFunction = Context.getKeyFunction(RD)) {
+    // If this is not the key function, we don't need to mark virtual members.
+    if (KeyFunction->getCanonicalDecl() != MD->getCanonicalDecl())
+      return;
+  } else {
+    // The class has no key function, so we've already noted that we need to
+    // mark the virtual members of this class.
+    return;
+  }
+  
+  // We will need to mark all of the virtual members as referenced to build the
+  // vtable.
+  ClassesWithUnmarkedVirtualMembers.push_back(std::make_pair(RD, Loc));
+}
+
+bool Sema::ProcessPendingClassesWithUnmarkedVirtualMembers() {
+  if (ClassesWithUnmarkedVirtualMembers.empty())
+    return false;
+  
+  while (!ClassesWithUnmarkedVirtualMembers.empty()) {
+    CXXRecordDecl *RD = ClassesWithUnmarkedVirtualMembers.back().first;
+    SourceLocation Loc = ClassesWithUnmarkedVirtualMembers.back().second;
+    ClassesWithUnmarkedVirtualMembers.pop_back();
+    MarkVirtualMembersReferenced(Loc, RD);
+  }
+  
+  return true;
+}
+
+void Sema::MarkVirtualMembersReferenced(SourceLocation Loc, CXXRecordDecl *RD) {
+  for (CXXRecordDecl::method_iterator i = RD->method_begin(), 
+       e = RD->method_end(); i != e; ++i) {
+    CXXMethodDecl *MD = *i;
+
+    // C++ [basic.def.odr]p2:
+    //   [...] A virtual member function is used if it is not pure. [...]
+    if (MD->isVirtual() && !MD->isPure())
+      MarkDeclarationReferenced(Loc, MD);
+  }
+}
+
diff --git a/lib/Sema/SemaDeclObjC.cpp b/lib/Sema/SemaDeclObjC.cpp
new file mode 100644
index 0000000..13eeb6c
--- /dev/null
+++ b/lib/Sema/SemaDeclObjC.cpp
@@ -0,0 +1,2559 @@
+//===--- SemaDeclObjC.cpp - Semantic Analysis for ObjC Declarations -------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+//  This file implements semantic analysis for Objective C declarations.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Sema.h"
+#include "Lookup.h"
+#include "clang/Sema/ExternalSemaSource.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/Parse/DeclSpec.h"
+using namespace clang;
+
+bool Sema::DiagnosePropertyAccessorMismatch(ObjCPropertyDecl *property,
+                                            ObjCMethodDecl *GetterMethod,
+                                            SourceLocation Loc) {
+  if (GetterMethod &&
+      GetterMethod->getResultType() != property->getType()) {
+    AssignConvertType result = Incompatible;
+    if (property->getType()->isObjCObjectPointerType())
+      result = CheckAssignmentConstraints(GetterMethod->getResultType(), property->getType());
+    if (result != Compatible) {
+      Diag(Loc, diag::warn_accessor_property_type_mismatch)
+        << property->getDeclName()
+        << GetterMethod->getSelector();
+      Diag(GetterMethod->getLocation(), diag::note_declared_at);
+      return true;
+    }
+  }
+  return false;
+}
+
+/// ActOnStartOfObjCMethodDef - This routine sets up parameters; invisible
+/// and user declared, in the method definition's AST.
+void Sema::ActOnStartOfObjCMethodDef(Scope *FnBodyScope, DeclPtrTy D) {
+  assert(getCurMethodDecl() == 0 && "Method parsing confused");
+  ObjCMethodDecl *MDecl = dyn_cast_or_null<ObjCMethodDecl>(D.getAs<Decl>());
+
+  // If we don't have a valid method decl, simply return.
+  if (!MDecl)
+    return;
+
+  CurFunctionNeedsScopeChecking = false;
+
+  // Allow the rest of sema to find private method decl implementations.
+  if (MDecl->isInstanceMethod())
+    AddInstanceMethodToGlobalPool(MDecl);
+  else
+    AddFactoryMethodToGlobalPool(MDecl);
+
+  // Allow all of Sema to see that we are entering a method definition.
+  PushDeclContext(FnBodyScope, MDecl);
+
+  // Create Decl objects for each parameter, entrring them in the scope for
+  // binding to their use.
+
+  // Insert the invisible arguments, self and _cmd!
+  MDecl->createImplicitParams(Context, MDecl->getClassInterface());
+
+  PushOnScopeChains(MDecl->getSelfDecl(), FnBodyScope);
+  PushOnScopeChains(MDecl->getCmdDecl(), FnBodyScope);
+
+  // Introduce all of the other parameters into this scope.
+  for (ObjCMethodDecl::param_iterator PI = MDecl->param_begin(),
+       E = MDecl->param_end(); PI != E; ++PI)
+    if ((*PI)->getIdentifier())
+      PushOnScopeChains(*PI, FnBodyScope);
+}
+
+Sema::DeclPtrTy Sema::
+ActOnStartClassInterface(SourceLocation AtInterfaceLoc,
+                         IdentifierInfo *ClassName, SourceLocation ClassLoc,
+                         IdentifierInfo *SuperName, SourceLocation SuperLoc,
+                         const DeclPtrTy *ProtoRefs, unsigned NumProtoRefs,
+                         const SourceLocation *ProtoLocs, 
+                         SourceLocation EndProtoLoc, AttributeList *AttrList) {
+  assert(ClassName && "Missing class identifier");
+
+  // Check for another declaration kind with the same name.
+  NamedDecl *PrevDecl = LookupSingleName(TUScope, ClassName, LookupOrdinaryName);
+  if (PrevDecl && PrevDecl->isTemplateParameter()) {
+    // Maybe we will complain about the shadowed template parameter.
+    DiagnoseTemplateParameterShadow(ClassLoc, PrevDecl);
+    // Just pretend that we didn't see the previous declaration.
+    PrevDecl = 0;
+  }
+
+  if (PrevDecl && !isa<ObjCInterfaceDecl>(PrevDecl)) {
+    Diag(ClassLoc, diag::err_redefinition_different_kind) << ClassName;
+    Diag(PrevDecl->getLocation(), diag::note_previous_definition);
+  }
+
+  ObjCInterfaceDecl* IDecl = dyn_cast_or_null<ObjCInterfaceDecl>(PrevDecl);
+  if (IDecl) {
+    // Class already seen. Is it a forward declaration?
+    if (!IDecl->isForwardDecl()) {
+      IDecl->setInvalidDecl();
+      Diag(AtInterfaceLoc, diag::err_duplicate_class_def)<<IDecl->getDeclName();
+      Diag(IDecl->getLocation(), diag::note_previous_definition);
+
+      // Return the previous class interface.
+      // FIXME: don't leak the objects passed in!
+      return DeclPtrTy::make(IDecl);
+    } else {
+      IDecl->setLocation(AtInterfaceLoc);
+      IDecl->setForwardDecl(false);
+      IDecl->setClassLoc(ClassLoc);
+      
+      // Since this ObjCInterfaceDecl was created by a forward declaration,
+      // we now add it to the DeclContext since it wasn't added before
+      // (see ActOnForwardClassDeclaration).
+      CurContext->addDecl(IDecl);
+      
+      if (AttrList)
+        ProcessDeclAttributeList(TUScope, IDecl, AttrList);
+    }
+  } else {
+    IDecl = ObjCInterfaceDecl::Create(Context, CurContext, AtInterfaceLoc,
+                                      ClassName, ClassLoc);
+    if (AttrList)
+      ProcessDeclAttributeList(TUScope, IDecl, AttrList);
+
+    PushOnScopeChains(IDecl, TUScope);
+  }
+
+  if (SuperName) {
+    // Check if a different kind of symbol declared in this scope.
+    PrevDecl = LookupSingleName(TUScope, SuperName, LookupOrdinaryName);
+
+    if (!PrevDecl) {
+      // Try to correct for a typo in the superclass name.
+      LookupResult R(*this, SuperName, SuperLoc, LookupOrdinaryName);
+      if (CorrectTypo(R, TUScope, 0) &&
+          (PrevDecl = R.getAsSingle<ObjCInterfaceDecl>())) {
+        Diag(SuperLoc, diag::err_undef_superclass_suggest)
+          << SuperName << ClassName << PrevDecl->getDeclName();
+        Diag(PrevDecl->getLocation(), diag::note_previous_decl)
+          << PrevDecl->getDeclName();
+      }
+    }
+
+    if (PrevDecl == IDecl) {
+      Diag(SuperLoc, diag::err_recursive_superclass)
+        << SuperName << ClassName << SourceRange(AtInterfaceLoc, ClassLoc);
+      IDecl->setLocEnd(ClassLoc);
+    } else {
+      ObjCInterfaceDecl *SuperClassDecl =
+                                dyn_cast_or_null<ObjCInterfaceDecl>(PrevDecl);
+
+      // Diagnose classes that inherit from deprecated classes.
+      if (SuperClassDecl)
+        (void)DiagnoseUseOfDecl(SuperClassDecl, SuperLoc);
+
+      if (PrevDecl && SuperClassDecl == 0) {
+        // The previous declaration was not a class decl. Check if we have a
+        // typedef. If we do, get the underlying class type.
+        if (const TypedefDecl *TDecl = dyn_cast_or_null<TypedefDecl>(PrevDecl)) {
+          QualType T = TDecl->getUnderlyingType();
+          if (T->isObjCInterfaceType()) {
+            if (NamedDecl *IDecl = T->getAs<ObjCInterfaceType>()->getDecl())
+              SuperClassDecl = dyn_cast<ObjCInterfaceDecl>(IDecl);
+          }
+        }
+
+        // This handles the following case:
+        //
+        // typedef int SuperClass;
+        // @interface MyClass : SuperClass {} @end
+        //
+        if (!SuperClassDecl) {
+          Diag(SuperLoc, diag::err_redefinition_different_kind) << SuperName;
+          Diag(PrevDecl->getLocation(), diag::note_previous_definition);
+        }
+      }
+
+      if (!dyn_cast_or_null<TypedefDecl>(PrevDecl)) {
+        if (!SuperClassDecl)
+          Diag(SuperLoc, diag::err_undef_superclass)
+            << SuperName << ClassName << SourceRange(AtInterfaceLoc, ClassLoc);
+        else if (SuperClassDecl->isForwardDecl())
+          Diag(SuperLoc, diag::err_undef_superclass)
+            << SuperClassDecl->getDeclName() << ClassName
+            << SourceRange(AtInterfaceLoc, ClassLoc);
+      }
+      IDecl->setSuperClass(SuperClassDecl);
+      IDecl->setSuperClassLoc(SuperLoc);
+      IDecl->setLocEnd(SuperLoc);
+    }
+  } else { // we have a root class.
+    IDecl->setLocEnd(ClassLoc);
+  }
+
+  /// Check then save referenced protocols.
+  if (NumProtoRefs) {
+    IDecl->setProtocolList((ObjCProtocolDecl**)ProtoRefs, NumProtoRefs,
+                           ProtoLocs, Context);
+    IDecl->setLocEnd(EndProtoLoc);
+  }
+
+  CheckObjCDeclScope(IDecl);
+  return DeclPtrTy::make(IDecl);
+}
+
+/// ActOnCompatiblityAlias - this action is called after complete parsing of
+/// @compatibility_alias declaration. It sets up the alias relationships.
+Sema::DeclPtrTy Sema::ActOnCompatiblityAlias(SourceLocation AtLoc,
+                                             IdentifierInfo *AliasName,
+                                             SourceLocation AliasLocation,
+                                             IdentifierInfo *ClassName,
+                                             SourceLocation ClassLocation) {
+  // Look for previous declaration of alias name
+  NamedDecl *ADecl = LookupSingleName(TUScope, AliasName, LookupOrdinaryName);
+  if (ADecl) {
+    if (isa<ObjCCompatibleAliasDecl>(ADecl))
+      Diag(AliasLocation, diag::warn_previous_alias_decl);
+    else
+      Diag(AliasLocation, diag::err_conflicting_aliasing_type) << AliasName;
+    Diag(ADecl->getLocation(), diag::note_previous_declaration);
+    return DeclPtrTy();
+  }
+  // Check for class declaration
+  NamedDecl *CDeclU = LookupSingleName(TUScope, ClassName, LookupOrdinaryName);
+  if (const TypedefDecl *TDecl = dyn_cast_or_null<TypedefDecl>(CDeclU)) {
+    QualType T = TDecl->getUnderlyingType();
+    if (T->isObjCInterfaceType()) {
+      if (NamedDecl *IDecl = T->getAs<ObjCInterfaceType>()->getDecl()) {
+        ClassName = IDecl->getIdentifier();
+        CDeclU = LookupSingleName(TUScope, ClassName, LookupOrdinaryName);
+      }
+    }
+  }
+  ObjCInterfaceDecl *CDecl = dyn_cast_or_null<ObjCInterfaceDecl>(CDeclU);
+  if (CDecl == 0) {
+    Diag(ClassLocation, diag::warn_undef_interface) << ClassName;
+    if (CDeclU)
+      Diag(CDeclU->getLocation(), diag::note_previous_declaration);
+    return DeclPtrTy();
+  }
+
+  // Everything checked out, instantiate a new alias declaration AST.
+  ObjCCompatibleAliasDecl *AliasDecl =
+    ObjCCompatibleAliasDecl::Create(Context, CurContext, AtLoc, AliasName, CDecl);
+
+  if (!CheckObjCDeclScope(AliasDecl))
+    PushOnScopeChains(AliasDecl, TUScope);
+
+  return DeclPtrTy::make(AliasDecl);
+}
+
+void Sema::CheckForwardProtocolDeclarationForCircularDependency(
+  IdentifierInfo *PName,
+  SourceLocation &Ploc, SourceLocation PrevLoc,
+  const ObjCList<ObjCProtocolDecl> &PList) {
+  for (ObjCList<ObjCProtocolDecl>::iterator I = PList.begin(),
+       E = PList.end(); I != E; ++I) {
+
+    if (ObjCProtocolDecl *PDecl = LookupProtocol((*I)->getIdentifier())) {
+      if (PDecl->getIdentifier() == PName) {
+        Diag(Ploc, diag::err_protocol_has_circular_dependency);
+        Diag(PrevLoc, diag::note_previous_definition);
+      }
+      CheckForwardProtocolDeclarationForCircularDependency(PName, Ploc,
+        PDecl->getLocation(), PDecl->getReferencedProtocols());
+    }
+  }
+}
+
+Sema::DeclPtrTy
+Sema::ActOnStartProtocolInterface(SourceLocation AtProtoInterfaceLoc,
+                                  IdentifierInfo *ProtocolName,
+                                  SourceLocation ProtocolLoc,
+                                  const DeclPtrTy *ProtoRefs,
+                                  unsigned NumProtoRefs,
+                                  const SourceLocation *ProtoLocs,
+                                  SourceLocation EndProtoLoc,
+                                  AttributeList *AttrList) {
+  // FIXME: Deal with AttrList.
+  assert(ProtocolName && "Missing protocol identifier");
+  ObjCProtocolDecl *PDecl = LookupProtocol(ProtocolName);
+  if (PDecl) {
+    // Protocol already seen. Better be a forward protocol declaration
+    if (!PDecl->isForwardDecl()) {
+      Diag(ProtocolLoc, diag::warn_duplicate_protocol_def) << ProtocolName;
+      Diag(PDecl->getLocation(), diag::note_previous_definition);
+      // Just return the protocol we already had.
+      // FIXME: don't leak the objects passed in!
+      return DeclPtrTy::make(PDecl);
+    }
+    ObjCList<ObjCProtocolDecl> PList;
+    PList.set((ObjCProtocolDecl *const*)ProtoRefs, NumProtoRefs, Context);
+    CheckForwardProtocolDeclarationForCircularDependency(
+      ProtocolName, ProtocolLoc, PDecl->getLocation(), PList);
+    PList.Destroy(Context);
+
+    // Make sure the cached decl gets a valid start location.
+    PDecl->setLocation(AtProtoInterfaceLoc);
+    PDecl->setForwardDecl(false);
+  } else {
+    PDecl = ObjCProtocolDecl::Create(Context, CurContext,
+                                     AtProtoInterfaceLoc,ProtocolName);
+    PushOnScopeChains(PDecl, TUScope);
+    PDecl->setForwardDecl(false);
+  }
+  if (AttrList)
+    ProcessDeclAttributeList(TUScope, PDecl, AttrList);
+  if (NumProtoRefs) {
+    /// Check then save referenced protocols.
+    PDecl->setProtocolList((ObjCProtocolDecl**)ProtoRefs, NumProtoRefs,
+                           ProtoLocs, Context);
+    PDecl->setLocEnd(EndProtoLoc);
+  }
+
+  CheckObjCDeclScope(PDecl);
+  return DeclPtrTy::make(PDecl);
+}
+
+/// FindProtocolDeclaration - This routine looks up protocols and
+/// issues an error if they are not declared. It returns list of
+/// protocol declarations in its 'Protocols' argument.
+void
+Sema::FindProtocolDeclaration(bool WarnOnDeclarations,
+                              const IdentifierLocPair *ProtocolId,
+                              unsigned NumProtocols,
+                              llvm::SmallVectorImpl<DeclPtrTy> &Protocols) {
+  for (unsigned i = 0; i != NumProtocols; ++i) {
+    ObjCProtocolDecl *PDecl = LookupProtocol(ProtocolId[i].first);
+    if (!PDecl) {
+      LookupResult R(*this, ProtocolId[i].first, ProtocolId[i].second,
+                     LookupObjCProtocolName);
+      if (CorrectTypo(R, TUScope, 0) &&
+          (PDecl = R.getAsSingle<ObjCProtocolDecl>())) {
+        Diag(ProtocolId[i].second, diag::err_undeclared_protocol_suggest)
+          << ProtocolId[i].first << R.getLookupName();
+        Diag(PDecl->getLocation(), diag::note_previous_decl)
+          << PDecl->getDeclName();
+      }
+    }
+
+    if (!PDecl) {
+      Diag(ProtocolId[i].second, diag::err_undeclared_protocol)
+        << ProtocolId[i].first;
+      continue;
+    }
+
+    (void)DiagnoseUseOfDecl(PDecl, ProtocolId[i].second);
+
+    // If this is a forward declaration and we are supposed to warn in this
+    // case, do it.
+    if (WarnOnDeclarations && PDecl->isForwardDecl())
+      Diag(ProtocolId[i].second, diag::warn_undef_protocolref)
+        << ProtocolId[i].first;
+    Protocols.push_back(DeclPtrTy::make(PDecl));
+  }
+}
+
+/// DiagnosePropertyMismatch - Compares two properties for their
+/// attributes and types and warns on a variety of inconsistencies.
+///
+void
+Sema::DiagnosePropertyMismatch(ObjCPropertyDecl *Property,
+                               ObjCPropertyDecl *SuperProperty,
+                               const IdentifierInfo *inheritedName) {
+  ObjCPropertyDecl::PropertyAttributeKind CAttr =
+  Property->getPropertyAttributes();
+  ObjCPropertyDecl::PropertyAttributeKind SAttr =
+  SuperProperty->getPropertyAttributes();
+  if ((CAttr & ObjCPropertyDecl::OBJC_PR_readonly)
+      && (SAttr & ObjCPropertyDecl::OBJC_PR_readwrite))
+    Diag(Property->getLocation(), diag::warn_readonly_property)
+      << Property->getDeclName() << inheritedName;
+  if ((CAttr & ObjCPropertyDecl::OBJC_PR_copy)
+      != (SAttr & ObjCPropertyDecl::OBJC_PR_copy))
+    Diag(Property->getLocation(), diag::warn_property_attribute)
+      << Property->getDeclName() << "copy" << inheritedName;
+  else if ((CAttr & ObjCPropertyDecl::OBJC_PR_retain)
+           != (SAttr & ObjCPropertyDecl::OBJC_PR_retain))
+    Diag(Property->getLocation(), diag::warn_property_attribute)
+      << Property->getDeclName() << "retain" << inheritedName;
+
+  if ((CAttr & ObjCPropertyDecl::OBJC_PR_nonatomic)
+      != (SAttr & ObjCPropertyDecl::OBJC_PR_nonatomic))
+    Diag(Property->getLocation(), diag::warn_property_attribute)
+      << Property->getDeclName() << "atomic" << inheritedName;
+  if (Property->getSetterName() != SuperProperty->getSetterName())
+    Diag(Property->getLocation(), diag::warn_property_attribute)
+      << Property->getDeclName() << "setter" << inheritedName;
+  if (Property->getGetterName() != SuperProperty->getGetterName())
+    Diag(Property->getLocation(), diag::warn_property_attribute)
+      << Property->getDeclName() << "getter" << inheritedName;
+
+  QualType LHSType =
+    Context.getCanonicalType(SuperProperty->getType());
+  QualType RHSType =
+    Context.getCanonicalType(Property->getType());
+
+  if (!Context.typesAreCompatible(LHSType, RHSType)) {
+    // FIXME: Incorporate this test with typesAreCompatible.
+    if (LHSType->isObjCQualifiedIdType() && RHSType->isObjCQualifiedIdType())
+      if (Context.ObjCQualifiedIdTypesAreCompatible(LHSType, RHSType, false))
+        return;
+    Diag(Property->getLocation(), diag::warn_property_types_are_incompatible)
+      << Property->getType() << SuperProperty->getType() << inheritedName;
+  }
+}
+
+/// ComparePropertiesInBaseAndSuper - This routine compares property
+/// declarations in base and its super class, if any, and issues
+/// diagnostics in a variety of inconsistant situations.
+///
+void Sema::ComparePropertiesInBaseAndSuper(ObjCInterfaceDecl *IDecl) {
+  ObjCInterfaceDecl *SDecl = IDecl->getSuperClass();
+  if (!SDecl)
+    return;
+  // FIXME: O(N^2)
+  for (ObjCInterfaceDecl::prop_iterator S = SDecl->prop_begin(),
+       E = SDecl->prop_end(); S != E; ++S) {
+    ObjCPropertyDecl *SuperPDecl = (*S);
+    // Does property in super class has declaration in current class?
+    for (ObjCInterfaceDecl::prop_iterator I = IDecl->prop_begin(),
+         E = IDecl->prop_end(); I != E; ++I) {
+      ObjCPropertyDecl *PDecl = (*I);
+      if (SuperPDecl->getIdentifier() == PDecl->getIdentifier())
+          DiagnosePropertyMismatch(PDecl, SuperPDecl,
+                                   SDecl->getIdentifier());
+    }
+  }
+}
+
+/// MatchOneProtocolPropertiesInClass - This routine goes thru the list
+/// of properties declared in a protocol and compares their attribute against
+/// the same property declared in the class or category.
+void
+Sema::MatchOneProtocolPropertiesInClass(Decl *CDecl,
+                                          ObjCProtocolDecl *PDecl) {
+  ObjCInterfaceDecl *IDecl = dyn_cast_or_null<ObjCInterfaceDecl>(CDecl);
+  if (!IDecl) {
+    // Category
+    ObjCCategoryDecl *CatDecl = static_cast<ObjCCategoryDecl*>(CDecl);
+    assert (CatDecl && "MatchOneProtocolPropertiesInClass");
+    for (ObjCProtocolDecl::prop_iterator P = PDecl->prop_begin(),
+         E = PDecl->prop_end(); P != E; ++P) {
+      ObjCPropertyDecl *Pr = (*P);
+      ObjCCategoryDecl::prop_iterator CP, CE;
+      // Is this property already in  category's list of properties?
+      for (CP = CatDecl->prop_begin(), CE = CatDecl->prop_end(); CP != CE; ++CP)
+        if ((*CP)->getIdentifier() == Pr->getIdentifier())
+          break;
+      if (CP != CE)
+        // Property protocol already exist in class. Diagnose any mismatch.
+        DiagnosePropertyMismatch((*CP), Pr, PDecl->getIdentifier());
+    }
+    return;
+  }
+  for (ObjCProtocolDecl::prop_iterator P = PDecl->prop_begin(),
+       E = PDecl->prop_end(); P != E; ++P) {
+    ObjCPropertyDecl *Pr = (*P);
+    ObjCInterfaceDecl::prop_iterator CP, CE;
+    // Is this property already in  class's list of properties?
+    for (CP = IDecl->prop_begin(), CE = IDecl->prop_end(); CP != CE; ++CP)
+      if ((*CP)->getIdentifier() == Pr->getIdentifier())
+        break;
+    if (CP != CE)
+      // Property protocol already exist in class. Diagnose any mismatch.
+      DiagnosePropertyMismatch((*CP), Pr, PDecl->getIdentifier());
+    }
+}
+
+/// CompareProperties - This routine compares properties
+/// declared in 'ClassOrProtocol' objects (which can be a class or an
+/// inherited protocol with the list of properties for class/category 'CDecl'
+///
+void Sema::CompareProperties(Decl *CDecl,
+                             DeclPtrTy ClassOrProtocol) {
+  Decl *ClassDecl = ClassOrProtocol.getAs<Decl>();
+  ObjCInterfaceDecl *IDecl = dyn_cast_or_null<ObjCInterfaceDecl>(CDecl);
+
+  if (!IDecl) {
+    // Category
+    ObjCCategoryDecl *CatDecl = static_cast<ObjCCategoryDecl*>(CDecl);
+    assert (CatDecl && "CompareProperties");
+    if (ObjCCategoryDecl *MDecl = dyn_cast<ObjCCategoryDecl>(ClassDecl)) {
+      for (ObjCCategoryDecl::protocol_iterator P = MDecl->protocol_begin(),
+           E = MDecl->protocol_end(); P != E; ++P)
+      // Match properties of category with those of protocol (*P)
+      MatchOneProtocolPropertiesInClass(CatDecl, *P);
+
+      // Go thru the list of protocols for this category and recursively match
+      // their properties with those in the category.
+      for (ObjCCategoryDecl::protocol_iterator P = CatDecl->protocol_begin(),
+           E = CatDecl->protocol_end(); P != E; ++P)
+        CompareProperties(CatDecl, DeclPtrTy::make(*P));
+    } else {
+      ObjCProtocolDecl *MD = cast<ObjCProtocolDecl>(ClassDecl);
+      for (ObjCProtocolDecl::protocol_iterator P = MD->protocol_begin(),
+           E = MD->protocol_end(); P != E; ++P)
+        MatchOneProtocolPropertiesInClass(CatDecl, *P);
+    }
+    return;
+  }
+
+  if (ObjCInterfaceDecl *MDecl = dyn_cast<ObjCInterfaceDecl>(ClassDecl)) {
+    for (ObjCInterfaceDecl::protocol_iterator P = MDecl->protocol_begin(),
+         E = MDecl->protocol_end(); P != E; ++P)
+      // Match properties of class IDecl with those of protocol (*P).
+      MatchOneProtocolPropertiesInClass(IDecl, *P);
+
+    // Go thru the list of protocols for this class and recursively match
+    // their properties with those declared in the class.
+    for (ObjCInterfaceDecl::protocol_iterator P = IDecl->protocol_begin(),
+         E = IDecl->protocol_end(); P != E; ++P)
+      CompareProperties(IDecl, DeclPtrTy::make(*P));
+  } else {
+    ObjCProtocolDecl *MD = cast<ObjCProtocolDecl>(ClassDecl);
+    for (ObjCProtocolDecl::protocol_iterator P = MD->protocol_begin(),
+         E = MD->protocol_end(); P != E; ++P)
+      MatchOneProtocolPropertiesInClass(IDecl, *P);
+  }
+}
+
+/// DiagnoseClassExtensionDupMethods - Check for duplicate declaration of
+/// a class method in its extension.
+///
+void Sema::DiagnoseClassExtensionDupMethods(ObjCCategoryDecl *CAT,
+                                            ObjCInterfaceDecl *ID) {
+  if (!ID)
+    return;  // Possibly due to previous error
+
+  llvm::DenseMap<Selector, const ObjCMethodDecl*> MethodMap;
+  for (ObjCInterfaceDecl::method_iterator i = ID->meth_begin(),
+       e =  ID->meth_end(); i != e; ++i) {
+    ObjCMethodDecl *MD = *i;
+    MethodMap[MD->getSelector()] = MD;
+  }
+
+  if (MethodMap.empty())
+    return;
+  for (ObjCCategoryDecl::method_iterator i = CAT->meth_begin(),
+       e =  CAT->meth_end(); i != e; ++i) {
+    ObjCMethodDecl *Method = *i;
+    const ObjCMethodDecl *&PrevMethod = MethodMap[Method->getSelector()];
+    if (PrevMethod && !MatchTwoMethodDeclarations(Method, PrevMethod)) {
+      Diag(Method->getLocation(), diag::err_duplicate_method_decl)
+            << Method->getDeclName();
+      Diag(PrevMethod->getLocation(), diag::note_previous_declaration);
+    }
+  }
+}
+
+/// ActOnForwardProtocolDeclaration - Handle @protocol foo;
+Action::DeclPtrTy
+Sema::ActOnForwardProtocolDeclaration(SourceLocation AtProtocolLoc,
+                                      const IdentifierLocPair *IdentList,
+                                      unsigned NumElts,
+                                      AttributeList *attrList) {
+  llvm::SmallVector<ObjCProtocolDecl*, 32> Protocols;
+  llvm::SmallVector<SourceLocation, 8> ProtoLocs;
+
+  for (unsigned i = 0; i != NumElts; ++i) {
+    IdentifierInfo *Ident = IdentList[i].first;
+    ObjCProtocolDecl *PDecl = LookupProtocol(Ident);
+    if (PDecl == 0) { // Not already seen?
+      PDecl = ObjCProtocolDecl::Create(Context, CurContext,
+                                       IdentList[i].second, Ident);
+      PushOnScopeChains(PDecl, TUScope);
+    }
+    if (attrList)
+      ProcessDeclAttributeList(TUScope, PDecl, attrList);
+    Protocols.push_back(PDecl);
+    ProtoLocs.push_back(IdentList[i].second);
+  }
+
+  ObjCForwardProtocolDecl *PDecl =
+    ObjCForwardProtocolDecl::Create(Context, CurContext, AtProtocolLoc,
+                                    Protocols.data(), Protocols.size(),
+                                    ProtoLocs.data());
+  CurContext->addDecl(PDecl);
+  CheckObjCDeclScope(PDecl);
+  return DeclPtrTy::make(PDecl);
+}
+
+Sema::DeclPtrTy Sema::
+ActOnStartCategoryInterface(SourceLocation AtInterfaceLoc,
+                            IdentifierInfo *ClassName, SourceLocation ClassLoc,
+                            IdentifierInfo *CategoryName,
+                            SourceLocation CategoryLoc,
+                            const DeclPtrTy *ProtoRefs,
+                            unsigned NumProtoRefs,
+                            const SourceLocation *ProtoLocs,
+                            SourceLocation EndProtoLoc) {
+  ObjCCategoryDecl *CDecl =
+    ObjCCategoryDecl::Create(Context, CurContext, AtInterfaceLoc, ClassLoc,
+                             CategoryLoc, CategoryName);
+  // FIXME: PushOnScopeChains?
+  CurContext->addDecl(CDecl);
+
+  ObjCInterfaceDecl *IDecl = getObjCInterfaceDecl(ClassName, ClassLoc);
+  /// Check that class of this category is already completely declared.
+  if (!IDecl || IDecl->isForwardDecl()) {
+    CDecl->setInvalidDecl();
+    Diag(ClassLoc, diag::err_undef_interface) << ClassName;
+    return DeclPtrTy::make(CDecl);
+  }
+
+  CDecl->setClassInterface(IDecl);
+
+  // If the interface is deprecated, warn about it.
+  (void)DiagnoseUseOfDecl(IDecl, ClassLoc);
+
+  /// Check for duplicate interface declaration for this category
+  ObjCCategoryDecl *CDeclChain;
+  for (CDeclChain = IDecl->getCategoryList(); CDeclChain;
+       CDeclChain = CDeclChain->getNextClassCategory()) {
+    if (CategoryName && CDeclChain->getIdentifier() == CategoryName) {
+      Diag(CategoryLoc, diag::warn_dup_category_def)
+      << ClassName << CategoryName;
+      Diag(CDeclChain->getLocation(), diag::note_previous_definition);
+      break;
+    }
+  }
+  if (!CDeclChain)
+    CDecl->insertNextClassCategory();
+
+  if (NumProtoRefs) {
+    CDecl->setProtocolList((ObjCProtocolDecl**)ProtoRefs, NumProtoRefs, 
+                           ProtoLocs, Context);
+    // Protocols in the class extension belong to the class.
+    if (!CDecl->getIdentifier())
+     IDecl->mergeClassExtensionProtocolList((ObjCProtocolDecl**)ProtoRefs, 
+                                            NumProtoRefs, ProtoLocs,
+                                            Context); 
+  }
+
+  CheckObjCDeclScope(CDecl);
+  return DeclPtrTy::make(CDecl);
+}
+
+/// ActOnStartCategoryImplementation - Perform semantic checks on the
+/// category implementation declaration and build an ObjCCategoryImplDecl
+/// object.
+Sema::DeclPtrTy Sema::ActOnStartCategoryImplementation(
+                      SourceLocation AtCatImplLoc,
+                      IdentifierInfo *ClassName, SourceLocation ClassLoc,
+                      IdentifierInfo *CatName, SourceLocation CatLoc) {
+  ObjCInterfaceDecl *IDecl = getObjCInterfaceDecl(ClassName, ClassLoc);
+  ObjCCategoryDecl *CatIDecl = 0;
+  if (IDecl) {
+    CatIDecl = IDecl->FindCategoryDeclaration(CatName);
+    if (!CatIDecl) {
+      // Category @implementation with no corresponding @interface.
+      // Create and install one.
+      CatIDecl = ObjCCategoryDecl::Create(Context, CurContext, SourceLocation(),
+                                          SourceLocation(), SourceLocation(),
+                                          CatName);
+      CatIDecl->setClassInterface(IDecl);
+      CatIDecl->insertNextClassCategory();
+    }
+  }
+
+  ObjCCategoryImplDecl *CDecl =
+    ObjCCategoryImplDecl::Create(Context, CurContext, AtCatImplLoc, CatName,
+                                 IDecl);
+  /// Check that class of this category is already completely declared.
+  if (!IDecl || IDecl->isForwardDecl())
+    Diag(ClassLoc, diag::err_undef_interface) << ClassName;
+
+  // FIXME: PushOnScopeChains?
+  CurContext->addDecl(CDecl);
+
+  /// Check that CatName, category name, is not used in another implementation.
+  if (CatIDecl) {
+    if (CatIDecl->getImplementation()) {
+      Diag(ClassLoc, diag::err_dup_implementation_category) << ClassName
+        << CatName;
+      Diag(CatIDecl->getImplementation()->getLocation(),
+           diag::note_previous_definition);
+    } else
+      CatIDecl->setImplementation(CDecl);
+  }
+
+  CheckObjCDeclScope(CDecl);
+  return DeclPtrTy::make(CDecl);
+}
+
+Sema::DeclPtrTy Sema::ActOnStartClassImplementation(
+                      SourceLocation AtClassImplLoc,
+                      IdentifierInfo *ClassName, SourceLocation ClassLoc,
+                      IdentifierInfo *SuperClassname,
+                      SourceLocation SuperClassLoc) {
+  ObjCInterfaceDecl* IDecl = 0;
+  // Check for another declaration kind with the same name.
+  NamedDecl *PrevDecl
+    = LookupSingleName(TUScope, ClassName, LookupOrdinaryName);
+  if (PrevDecl && !isa<ObjCInterfaceDecl>(PrevDecl)) {
+    Diag(ClassLoc, diag::err_redefinition_different_kind) << ClassName;
+    Diag(PrevDecl->getLocation(), diag::note_previous_definition);
+  } else if ((IDecl = dyn_cast_or_null<ObjCInterfaceDecl>(PrevDecl))) {
+    // If this is a forward declaration of an interface, warn.
+    if (IDecl->isForwardDecl()) {
+      Diag(ClassLoc, diag::warn_undef_interface) << ClassName;
+      IDecl = 0;
+    }
+  } else {
+    // We did not find anything with the name ClassName; try to correct for 
+    // typos in the class name.
+    LookupResult R(*this, ClassName, ClassLoc, LookupOrdinaryName);
+    if (CorrectTypo(R, TUScope, 0) &&
+        (IDecl = R.getAsSingle<ObjCInterfaceDecl>())) {
+      // Suggest the (potentially) correct interface name. However, put the
+      // fix-it hint itself in a separate note, since changing the name in 
+      // the warning would make the fix-it change semantics.However, don't
+      // provide a code-modification hint or use the typo name for recovery,
+      // because this is just a warning. The program may actually be correct.
+      Diag(ClassLoc, diag::warn_undef_interface_suggest)
+        << ClassName << R.getLookupName();
+      Diag(IDecl->getLocation(), diag::note_previous_decl)
+        << R.getLookupName()
+        << CodeModificationHint::CreateReplacement(ClassLoc,
+                                               R.getLookupName().getAsString());
+      IDecl = 0;
+    } else {
+      Diag(ClassLoc, diag::warn_undef_interface) << ClassName;
+    }
+  }
+
+  // Check that super class name is valid class name
+  ObjCInterfaceDecl* SDecl = 0;
+  if (SuperClassname) {
+    // Check if a different kind of symbol declared in this scope.
+    PrevDecl = LookupSingleName(TUScope, SuperClassname, LookupOrdinaryName);
+    if (PrevDecl && !isa<ObjCInterfaceDecl>(PrevDecl)) {
+      Diag(SuperClassLoc, diag::err_redefinition_different_kind)
+        << SuperClassname;
+      Diag(PrevDecl->getLocation(), diag::note_previous_definition);
+    } else {
+      SDecl = dyn_cast_or_null<ObjCInterfaceDecl>(PrevDecl);
+      if (!SDecl)
+        Diag(SuperClassLoc, diag::err_undef_superclass)
+          << SuperClassname << ClassName;
+      else if (IDecl && IDecl->getSuperClass() != SDecl) {
+        // This implementation and its interface do not have the same
+        // super class.
+        Diag(SuperClassLoc, diag::err_conflicting_super_class)
+          << SDecl->getDeclName();
+        Diag(SDecl->getLocation(), diag::note_previous_definition);
+      }
+    }
+  }
+
+  if (!IDecl) {
+    // Legacy case of @implementation with no corresponding @interface.
+    // Build, chain & install the interface decl into the identifier.
+
+    // FIXME: Do we support attributes on the @implementation? If so we should
+    // copy them over.
+    IDecl = ObjCInterfaceDecl::Create(Context, CurContext, AtClassImplLoc,
+                                      ClassName, ClassLoc, false, true);
+    IDecl->setSuperClass(SDecl);
+    IDecl->setLocEnd(ClassLoc);
+
+    PushOnScopeChains(IDecl, TUScope);
+  } else {
+    // Mark the interface as being completed, even if it was just as
+    //   @class ....;
+    // declaration; the user cannot reopen it.
+    IDecl->setForwardDecl(false);
+  }
+
+  ObjCImplementationDecl* IMPDecl =
+    ObjCImplementationDecl::Create(Context, CurContext, AtClassImplLoc,
+                                   IDecl, SDecl);
+
+  if (CheckObjCDeclScope(IMPDecl))
+    return DeclPtrTy::make(IMPDecl);
+
+  // Check that there is no duplicate implementation of this class.
+  if (IDecl->getImplementation()) {
+    // FIXME: Don't leak everything!
+    Diag(ClassLoc, diag::err_dup_implementation_class) << ClassName;
+    Diag(IDecl->getImplementation()->getLocation(),
+         diag::note_previous_definition);
+  } else { // add it to the list.
+    IDecl->setImplementation(IMPDecl);
+    PushOnScopeChains(IMPDecl, TUScope);
+  }
+  return DeclPtrTy::make(IMPDecl);
+}
+
+void Sema::CheckImplementationIvars(ObjCImplementationDecl *ImpDecl,
+                                    ObjCIvarDecl **ivars, unsigned numIvars,
+                                    SourceLocation RBrace) {
+  assert(ImpDecl && "missing implementation decl");
+  ObjCInterfaceDecl* IDecl = ImpDecl->getClassInterface();
+  if (!IDecl)
+    return;
+  /// Check case of non-existing @interface decl.
+  /// (legacy objective-c @implementation decl without an @interface decl).
+  /// Add implementations's ivar to the synthesize class's ivar list.
+  if (IDecl->isImplicitInterfaceDecl()) {
+    IDecl->setIVarList(ivars, numIvars, Context);
+    IDecl->setLocEnd(RBrace);
+    return;
+  }
+  // If implementation has empty ivar list, just return.
+  if (numIvars == 0)
+    return;
+
+  assert(ivars && "missing @implementation ivars");
+
+  // Check interface's Ivar list against those in the implementation.
+  // names and types must match.
+  //
+  unsigned j = 0;
+  ObjCInterfaceDecl::ivar_iterator
+    IVI = IDecl->ivar_begin(), IVE = IDecl->ivar_end();
+  for (; numIvars > 0 && IVI != IVE; ++IVI) {
+    ObjCIvarDecl* ImplIvar = ivars[j++];
+    ObjCIvarDecl* ClsIvar = *IVI;
+    assert (ImplIvar && "missing implementation ivar");
+    assert (ClsIvar && "missing class ivar");
+
+    // First, make sure the types match.
+    if (Context.getCanonicalType(ImplIvar->getType()) !=
+        Context.getCanonicalType(ClsIvar->getType())) {
+      Diag(ImplIvar->getLocation(), diag::err_conflicting_ivar_type)
+        << ImplIvar->getIdentifier()
+        << ImplIvar->getType() << ClsIvar->getType();
+      Diag(ClsIvar->getLocation(), diag::note_previous_definition);
+    } else if (ImplIvar->isBitField() && ClsIvar->isBitField()) {
+      Expr *ImplBitWidth = ImplIvar->getBitWidth();
+      Expr *ClsBitWidth = ClsIvar->getBitWidth();
+      if (ImplBitWidth->EvaluateAsInt(Context).getZExtValue() !=
+          ClsBitWidth->EvaluateAsInt(Context).getZExtValue()) {
+        Diag(ImplBitWidth->getLocStart(), diag::err_conflicting_ivar_bitwidth)
+          << ImplIvar->getIdentifier();
+        Diag(ClsBitWidth->getLocStart(), diag::note_previous_definition);
+      }
+    }
+    // Make sure the names are identical.
+    if (ImplIvar->getIdentifier() != ClsIvar->getIdentifier()) {
+      Diag(ImplIvar->getLocation(), diag::err_conflicting_ivar_name)
+        << ImplIvar->getIdentifier() << ClsIvar->getIdentifier();
+      Diag(ClsIvar->getLocation(), diag::note_previous_definition);
+    }
+    --numIvars;
+  }
+
+  if (numIvars > 0)
+    Diag(ivars[j]->getLocation(), diag::err_inconsistant_ivar_count);
+  else if (IVI != IVE)
+    Diag((*IVI)->getLocation(), diag::err_inconsistant_ivar_count);
+}
+
+void Sema::WarnUndefinedMethod(SourceLocation ImpLoc, ObjCMethodDecl *method,
+                               bool &IncompleteImpl) {
+  if (!IncompleteImpl) {
+    Diag(ImpLoc, diag::warn_incomplete_impl);
+    IncompleteImpl = true;
+  }
+  Diag(ImpLoc, diag::warn_undef_method_impl) << method->getDeclName();
+}
+
+void Sema::WarnConflictingTypedMethods(ObjCMethodDecl *ImpMethodDecl,
+                                       ObjCMethodDecl *IntfMethodDecl) {
+  if (!Context.typesAreCompatible(IntfMethodDecl->getResultType(),
+                                  ImpMethodDecl->getResultType()) &&
+      !Context.QualifiedIdConformsQualifiedId(IntfMethodDecl->getResultType(),
+                                              ImpMethodDecl->getResultType())) {
+    Diag(ImpMethodDecl->getLocation(), diag::warn_conflicting_ret_types)
+      << ImpMethodDecl->getDeclName() << IntfMethodDecl->getResultType()
+      << ImpMethodDecl->getResultType();
+    Diag(IntfMethodDecl->getLocation(), diag::note_previous_definition);
+  }
+
+  for (ObjCMethodDecl::param_iterator IM = ImpMethodDecl->param_begin(),
+       IF = IntfMethodDecl->param_begin(), EM = ImpMethodDecl->param_end();
+       IM != EM; ++IM, ++IF) {
+    QualType ParmDeclTy = (*IF)->getType().getUnqualifiedType();
+    QualType ParmImpTy = (*IM)->getType().getUnqualifiedType();
+    if (Context.typesAreCompatible(ParmDeclTy, ParmImpTy) ||
+        Context.QualifiedIdConformsQualifiedId(ParmDeclTy, ParmImpTy))
+      continue;
+
+    Diag((*IM)->getLocation(), diag::warn_conflicting_param_types)
+      << ImpMethodDecl->getDeclName() << (*IF)->getType()
+      << (*IM)->getType();
+    Diag((*IF)->getLocation(), diag::note_previous_definition);
+  }
+}
+
+/// isPropertyReadonly - Return true if property is readonly, by searching
+/// for the property in the class and in its categories and implementations
+///
+bool Sema::isPropertyReadonly(ObjCPropertyDecl *PDecl,
+                              ObjCInterfaceDecl *IDecl) {
+  // by far the most common case.
+  if (!PDecl->isReadOnly())
+    return false;
+  // Even if property is ready only, if interface has a user defined setter,
+  // it is not considered read only.
+  if (IDecl->getInstanceMethod(PDecl->getSetterName()))
+    return false;
+
+  // Main class has the property as 'readonly'. Must search
+  // through the category list to see if the property's
+  // attribute has been over-ridden to 'readwrite'.
+  for (ObjCCategoryDecl *Category = IDecl->getCategoryList();
+       Category; Category = Category->getNextClassCategory()) {
+    // Even if property is ready only, if a category has a user defined setter,
+    // it is not considered read only.
+    if (Category->getInstanceMethod(PDecl->getSetterName()))
+      return false;
+    ObjCPropertyDecl *P =
+      Category->FindPropertyDeclaration(PDecl->getIdentifier());
+    if (P && !P->isReadOnly())
+      return false;
+  }
+
+  // Also, check for definition of a setter method in the implementation if
+  // all else failed.
+  if (ObjCMethodDecl *OMD = dyn_cast<ObjCMethodDecl>(CurContext)) {
+    if (ObjCImplementationDecl *IMD =
+        dyn_cast<ObjCImplementationDecl>(OMD->getDeclContext())) {
+      if (IMD->getInstanceMethod(PDecl->getSetterName()))
+        return false;
+    } else if (ObjCCategoryImplDecl *CIMD =
+               dyn_cast<ObjCCategoryImplDecl>(OMD->getDeclContext())) {
+      if (CIMD->getInstanceMethod(PDecl->getSetterName()))
+        return false;
+    }
+  }
+  // Lastly, look through the implementation (if one is in scope).
+  if (ObjCImplementationDecl *ImpDecl = IDecl->getImplementation())
+    if (ImpDecl->getInstanceMethod(PDecl->getSetterName()))
+      return false;
+  // If all fails, look at the super class.
+  if (ObjCInterfaceDecl *SIDecl = IDecl->getSuperClass())
+    return isPropertyReadonly(PDecl, SIDecl);
+  return true;
+}
+
+/// FIXME: Type hierarchies in Objective-C can be deep. We could most likely
+/// improve the efficiency of selector lookups and type checking by associating
+/// with each protocol / interface / category the flattened instance tables. If
+/// we used an immutable set to keep the table then it wouldn't add significant
+/// memory cost and it would be handy for lookups.
+
+/// CheckProtocolMethodDefs - This routine checks unimplemented methods
+/// Declared in protocol, and those referenced by it.
+void Sema::CheckProtocolMethodDefs(SourceLocation ImpLoc,
+                                   ObjCProtocolDecl *PDecl,
+                                   bool& IncompleteImpl,
+                                   const llvm::DenseSet<Selector> &InsMap,
+                                   const llvm::DenseSet<Selector> &ClsMap,
+                                   ObjCInterfaceDecl *IDecl) {
+  ObjCInterfaceDecl *Super = IDecl->getSuperClass();
+  ObjCInterfaceDecl *NSIDecl = 0;
+  if (getLangOptions().NeXTRuntime) {
+    // check to see if class implements forwardInvocation method and objects
+    // of this class are derived from 'NSProxy' so that to forward requests
+    // from one object to another.
+    // Under such conditions, which means that every method possible is
+    // implemented in the class, we should not issue "Method definition not
+    // found" warnings.
+    // FIXME: Use a general GetUnarySelector method for this.
+    IdentifierInfo* II = &Context.Idents.get("forwardInvocation");
+    Selector fISelector = Context.Selectors.getSelector(1, &II);
+    if (InsMap.count(fISelector))
+      // Is IDecl derived from 'NSProxy'? If so, no instance methods
+      // need be implemented in the implementation.
+      NSIDecl = IDecl->lookupInheritedClass(&Context.Idents.get("NSProxy"));
+  }
+
+  // If a method lookup fails locally we still need to look and see if
+  // the method was implemented by a base class or an inherited
+  // protocol. This lookup is slow, but occurs rarely in correct code
+  // and otherwise would terminate in a warning.
+
+  // check unimplemented instance methods.
+  if (!NSIDecl)
+    for (ObjCProtocolDecl::instmeth_iterator I = PDecl->instmeth_begin(),
+         E = PDecl->instmeth_end(); I != E; ++I) {
+      ObjCMethodDecl *method = *I;
+      if (method->getImplementationControl() != ObjCMethodDecl::Optional &&
+          !method->isSynthesized() && !InsMap.count(method->getSelector()) &&
+          (!Super ||
+           !Super->lookupInstanceMethod(method->getSelector()))) {
+            // Ugly, but necessary. Method declared in protcol might have
+            // have been synthesized due to a property declared in the class which
+            // uses the protocol.
+            ObjCMethodDecl *MethodInClass =
+            IDecl->lookupInstanceMethod(method->getSelector());
+            if (!MethodInClass || !MethodInClass->isSynthesized())
+              WarnUndefinedMethod(ImpLoc, method, IncompleteImpl);
+          }
+    }
+  // check unimplemented class methods
+  for (ObjCProtocolDecl::classmeth_iterator
+         I = PDecl->classmeth_begin(), E = PDecl->classmeth_end();
+       I != E; ++I) {
+    ObjCMethodDecl *method = *I;
+    if (method->getImplementationControl() != ObjCMethodDecl::Optional &&
+        !ClsMap.count(method->getSelector()) &&
+        (!Super || !Super->lookupClassMethod(method->getSelector())))
+      WarnUndefinedMethod(ImpLoc, method, IncompleteImpl);
+  }
+  // Check on this protocols's referenced protocols, recursively.
+  for (ObjCProtocolDecl::protocol_iterator PI = PDecl->protocol_begin(),
+       E = PDecl->protocol_end(); PI != E; ++PI)
+    CheckProtocolMethodDefs(ImpLoc, *PI, IncompleteImpl, InsMap, ClsMap, IDecl);
+}
+
+/// MatchAllMethodDeclarations - Check methods declaraed in interface or
+/// or protocol against those declared in their implementations.
+///
+void Sema::MatchAllMethodDeclarations(const llvm::DenseSet<Selector> &InsMap,
+                                      const llvm::DenseSet<Selector> &ClsMap,
+                                      llvm::DenseSet<Selector> &InsMapSeen,
+                                      llvm::DenseSet<Selector> &ClsMapSeen,
+                                      ObjCImplDecl* IMPDecl,
+                                      ObjCContainerDecl* CDecl,
+                                      bool &IncompleteImpl,
+                                      bool ImmediateClass) {
+  // Check and see if instance methods in class interface have been
+  // implemented in the implementation class. If so, their types match.
+  for (ObjCInterfaceDecl::instmeth_iterator I = CDecl->instmeth_begin(),
+       E = CDecl->instmeth_end(); I != E; ++I) {
+    if (InsMapSeen.count((*I)->getSelector()))
+        continue;
+    InsMapSeen.insert((*I)->getSelector());
+    if (!(*I)->isSynthesized() &&
+        !InsMap.count((*I)->getSelector())) {
+      if (ImmediateClass)
+        WarnUndefinedMethod(IMPDecl->getLocation(), *I, IncompleteImpl);
+      continue;
+    } else {
+      ObjCMethodDecl *ImpMethodDecl =
+      IMPDecl->getInstanceMethod((*I)->getSelector());
+      ObjCMethodDecl *IntfMethodDecl =
+      CDecl->getInstanceMethod((*I)->getSelector());
+      assert(IntfMethodDecl &&
+             "IntfMethodDecl is null in ImplMethodsVsClassMethods");
+      // ImpMethodDecl may be null as in a @dynamic property.
+      if (ImpMethodDecl)
+        WarnConflictingTypedMethods(ImpMethodDecl, IntfMethodDecl);
+    }
+  }
+
+  // Check and see if class methods in class interface have been
+  // implemented in the implementation class. If so, their types match.
+   for (ObjCInterfaceDecl::classmeth_iterator
+       I = CDecl->classmeth_begin(), E = CDecl->classmeth_end(); I != E; ++I) {
+     if (ClsMapSeen.count((*I)->getSelector()))
+       continue;
+     ClsMapSeen.insert((*I)->getSelector());
+    if (!ClsMap.count((*I)->getSelector())) {
+      if (ImmediateClass)
+        WarnUndefinedMethod(IMPDecl->getLocation(), *I, IncompleteImpl);
+    } else {
+      ObjCMethodDecl *ImpMethodDecl =
+        IMPDecl->getClassMethod((*I)->getSelector());
+      ObjCMethodDecl *IntfMethodDecl =
+        CDecl->getClassMethod((*I)->getSelector());
+      WarnConflictingTypedMethods(ImpMethodDecl, IntfMethodDecl);
+    }
+  }
+  if (ObjCInterfaceDecl *I = dyn_cast<ObjCInterfaceDecl> (CDecl)) {
+    // Check for any implementation of a methods declared in protocol.
+    for (ObjCInterfaceDecl::protocol_iterator PI = I->protocol_begin(),
+         E = I->protocol_end(); PI != E; ++PI)
+      MatchAllMethodDeclarations(InsMap, ClsMap, InsMapSeen, ClsMapSeen,
+                                 IMPDecl,
+                                 (*PI), IncompleteImpl, false);
+    if (I->getSuperClass())
+      MatchAllMethodDeclarations(InsMap, ClsMap, InsMapSeen, ClsMapSeen,
+                                 IMPDecl,
+                                 I->getSuperClass(), IncompleteImpl, false);
+  }
+}
+
+/// CollectImmediateProperties - This routine collects all properties in
+/// the class and its conforming protocols; but not those it its super class.
+void Sema::CollectImmediateProperties(ObjCContainerDecl *CDecl,
+                llvm::DenseMap<IdentifierInfo *, ObjCPropertyDecl*>& PropMap) {
+  if (ObjCInterfaceDecl *IDecl = dyn_cast<ObjCInterfaceDecl>(CDecl)) {
+    for (ObjCContainerDecl::prop_iterator P = IDecl->prop_begin(),
+         E = IDecl->prop_end(); P != E; ++P) {
+      ObjCPropertyDecl *Prop = (*P);
+      PropMap[Prop->getIdentifier()] = Prop;
+    }
+    // scan through class's protocols.
+    for (ObjCInterfaceDecl::protocol_iterator PI = IDecl->protocol_begin(),
+         E = IDecl->protocol_end(); PI != E; ++PI)
+      CollectImmediateProperties((*PI), PropMap);
+  }
+  if (ObjCCategoryDecl *CATDecl = dyn_cast<ObjCCategoryDecl>(CDecl)) {
+    for (ObjCContainerDecl::prop_iterator P = CATDecl->prop_begin(),
+         E = CATDecl->prop_end(); P != E; ++P) {
+      ObjCPropertyDecl *Prop = (*P);
+      PropMap[Prop->getIdentifier()] = Prop;
+    }
+    // scan through class's protocols.
+    for (ObjCInterfaceDecl::protocol_iterator PI = CATDecl->protocol_begin(),
+         E = CATDecl->protocol_end(); PI != E; ++PI)
+      CollectImmediateProperties((*PI), PropMap);
+  }  
+  else if (ObjCProtocolDecl *PDecl = dyn_cast<ObjCProtocolDecl>(CDecl)) {
+    for (ObjCProtocolDecl::prop_iterator P = PDecl->prop_begin(),
+         E = PDecl->prop_end(); P != E; ++P) {
+      ObjCPropertyDecl *Prop = (*P);
+      ObjCPropertyDecl *&PropEntry = PropMap[Prop->getIdentifier()];
+      if (!PropEntry)
+        PropEntry = Prop;
+    }
+    // scan through protocol's protocols.
+    for (ObjCProtocolDecl::protocol_iterator PI = PDecl->protocol_begin(),
+         E = PDecl->protocol_end(); PI != E; ++PI)
+      CollectImmediateProperties((*PI), PropMap);
+  }
+}
+
+/// LookupPropertyDecl - Looks up a property in the current class and all
+/// its protocols.
+ObjCPropertyDecl *Sema::LookupPropertyDecl(const ObjCContainerDecl *CDecl, 
+                                     IdentifierInfo *II) {
+  if (const ObjCInterfaceDecl *IDecl = 
+        dyn_cast<ObjCInterfaceDecl>(CDecl)) {
+    for (ObjCContainerDecl::prop_iterator P = IDecl->prop_begin(),
+         E = IDecl->prop_end(); P != E; ++P) {
+      ObjCPropertyDecl *Prop = (*P);
+      if (Prop->getIdentifier() == II)
+        return Prop;
+    }
+    // scan through class's protocols.
+    for (ObjCInterfaceDecl::protocol_iterator PI = IDecl->protocol_begin(),
+         E = IDecl->protocol_end(); PI != E; ++PI) {
+      ObjCPropertyDecl *Prop = LookupPropertyDecl((*PI), II);
+      if (Prop)
+        return Prop;
+    }
+  }
+  else if (const ObjCProtocolDecl *PDecl = 
+            dyn_cast<ObjCProtocolDecl>(CDecl)) {
+    for (ObjCProtocolDecl::prop_iterator P = PDecl->prop_begin(),
+         E = PDecl->prop_end(); P != E; ++P) {
+      ObjCPropertyDecl *Prop = (*P);
+      if (Prop->getIdentifier() == II)
+        return Prop;
+    }
+    // scan through protocol's protocols.
+    for (ObjCProtocolDecl::protocol_iterator PI = PDecl->protocol_begin(),
+         E = PDecl->protocol_end(); PI != E; ++PI) {
+      ObjCPropertyDecl *Prop = LookupPropertyDecl((*PI), II);
+      if (Prop)
+        return Prop;
+    }
+  }
+  return 0;
+}
+
+
+void Sema::DiagnoseUnimplementedProperties(ObjCImplDecl* IMPDecl,
+                                      ObjCContainerDecl *CDecl,
+                                      const llvm::DenseSet<Selector>& InsMap) {
+  llvm::DenseMap<IdentifierInfo *, ObjCPropertyDecl*> PropMap;
+  CollectImmediateProperties(CDecl, PropMap);
+  if (PropMap.empty())
+    return;
+  
+  llvm::DenseSet<ObjCPropertyDecl *> PropImplMap;
+  for (ObjCImplDecl::propimpl_iterator
+       I = IMPDecl->propimpl_begin(),
+       EI = IMPDecl->propimpl_end(); I != EI; ++I)
+    PropImplMap.insert((*I)->getPropertyDecl());
+  
+  for (llvm::DenseMap<IdentifierInfo *, ObjCPropertyDecl*>::iterator 
+       P = PropMap.begin(), E = PropMap.end(); P != E; ++P) {
+    ObjCPropertyDecl *Prop = P->second;
+    // Is there a matching propery synthesize/dynamic?
+    if (Prop->isInvalidDecl() ||
+        Prop->getPropertyImplementation() == ObjCPropertyDecl::Optional ||
+        PropImplMap.count(Prop))
+      continue;
+    if (LangOpts.ObjCNonFragileABI2) {
+      ActOnPropertyImplDecl(IMPDecl->getLocation(),
+                            SourceLocation(),
+                            true, DeclPtrTy::make(IMPDecl), 
+                            Prop->getIdentifier(),
+                            Prop->getIdentifier());
+      continue;
+    }
+    if (!InsMap.count(Prop->getGetterName())) {
+      Diag(Prop->getLocation(),
+           isa<ObjCCategoryDecl>(CDecl) ? 
+            diag::warn_setter_getter_impl_required_in_category : 
+            diag::warn_setter_getter_impl_required)
+      << Prop->getDeclName() << Prop->getGetterName();
+      Diag(IMPDecl->getLocation(),
+           diag::note_property_impl_required);
+    }
+    
+    if (!Prop->isReadOnly() && !InsMap.count(Prop->getSetterName())) {
+      Diag(Prop->getLocation(),
+           isa<ObjCCategoryDecl>(CDecl) ? 
+           diag::warn_setter_getter_impl_required_in_category :
+           diag::warn_setter_getter_impl_required)
+      << Prop->getDeclName() << Prop->getSetterName();
+      Diag(IMPDecl->getLocation(),
+           diag::note_property_impl_required);
+    }    
+  }
+}
+
+void Sema::ImplMethodsVsClassMethods(ObjCImplDecl* IMPDecl,
+                                     ObjCContainerDecl* CDecl,
+                                     bool IncompleteImpl) {
+  llvm::DenseSet<Selector> InsMap;
+  // Check and see if instance methods in class interface have been
+  // implemented in the implementation class.
+  for (ObjCImplementationDecl::instmeth_iterator
+         I = IMPDecl->instmeth_begin(), E = IMPDecl->instmeth_end(); I!=E; ++I)
+    InsMap.insert((*I)->getSelector());
+
+  // Check and see if properties declared in the interface have either 1)
+  // an implementation or 2) there is a @synthesize/@dynamic implementation
+  // of the property in the @implementation.
+  if (isa<ObjCInterfaceDecl>(CDecl))
+    DiagnoseUnimplementedProperties(IMPDecl, CDecl, InsMap);
+      
+  llvm::DenseSet<Selector> ClsMap;
+  for (ObjCImplementationDecl::classmeth_iterator
+       I = IMPDecl->classmeth_begin(),
+       E = IMPDecl->classmeth_end(); I != E; ++I)
+    ClsMap.insert((*I)->getSelector());
+
+  // Check for type conflict of methods declared in a class/protocol and
+  // its implementation; if any.
+  llvm::DenseSet<Selector> InsMapSeen, ClsMapSeen;
+  MatchAllMethodDeclarations(InsMap, ClsMap, InsMapSeen, ClsMapSeen,
+                             IMPDecl, CDecl,
+                             IncompleteImpl, true);
+
+  // Check the protocol list for unimplemented methods in the @implementation
+  // class.
+  // Check and see if class methods in class interface have been
+  // implemented in the implementation class.
+
+  if (ObjCInterfaceDecl *I = dyn_cast<ObjCInterfaceDecl> (CDecl)) {
+    for (ObjCInterfaceDecl::protocol_iterator PI = I->protocol_begin(),
+         E = I->protocol_end(); PI != E; ++PI)
+      CheckProtocolMethodDefs(IMPDecl->getLocation(), *PI, IncompleteImpl,
+                              InsMap, ClsMap, I);
+    // Check class extensions (unnamed categories)
+    for (ObjCCategoryDecl *Categories = I->getCategoryList();
+         Categories; Categories = Categories->getNextClassCategory()) {
+      if (!Categories->getIdentifier()) {
+        ImplMethodsVsClassMethods(IMPDecl, Categories, IncompleteImpl);
+        break;
+      }
+    }
+  } else if (ObjCCategoryDecl *C = dyn_cast<ObjCCategoryDecl>(CDecl)) {
+    // For extended class, unimplemented methods in its protocols will
+    // be reported in the primary class.
+    if (C->getIdentifier()) {
+      for (ObjCCategoryDecl::protocol_iterator PI = C->protocol_begin(),
+           E = C->protocol_end(); PI != E; ++PI)
+        CheckProtocolMethodDefs(IMPDecl->getLocation(), *PI, IncompleteImpl,
+                                InsMap, ClsMap, C->getClassInterface());
+      // Report unimplemented properties in the category as well.
+      // When reporting on missing setter/getters, do not report when
+      // setter/getter is implemented in category's primary class 
+      // implementation.
+      if (ObjCInterfaceDecl *ID = C->getClassInterface())
+        if (ObjCImplDecl *IMP = ID->getImplementation()) {
+          for (ObjCImplementationDecl::instmeth_iterator
+               I = IMP->instmeth_begin(), E = IMP->instmeth_end(); I!=E; ++I)
+            InsMap.insert((*I)->getSelector());
+        }
+      DiagnoseUnimplementedProperties(IMPDecl, CDecl, InsMap);      
+    } 
+  } else
+    assert(false && "invalid ObjCContainerDecl type.");
+}
+
+void
+Sema::AtomicPropertySetterGetterRules (ObjCImplDecl* IMPDecl,
+                                       ObjCContainerDecl* IDecl) {
+  // Rules apply in non-GC mode only
+  if (getLangOptions().getGCMode() != LangOptions::NonGC)
+    return;
+  for (ObjCContainerDecl::prop_iterator I = IDecl->prop_begin(),
+       E = IDecl->prop_end();
+       I != E; ++I) {
+    ObjCPropertyDecl *Property = (*I);
+    unsigned Attributes = Property->getPropertyAttributes();
+    // We only care about readwrite atomic property.
+    if ((Attributes & ObjCPropertyDecl::OBJC_PR_nonatomic) ||
+        !(Attributes & ObjCPropertyDecl::OBJC_PR_readwrite))
+      continue;
+    if (const ObjCPropertyImplDecl *PIDecl
+         = IMPDecl->FindPropertyImplDecl(Property->getIdentifier())) {
+      if (PIDecl->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic)
+        continue;
+      ObjCMethodDecl *GetterMethod =
+        IMPDecl->getInstanceMethod(Property->getGetterName());
+      ObjCMethodDecl *SetterMethod = 
+        IMPDecl->getInstanceMethod(Property->getSetterName());
+      if ((GetterMethod && !SetterMethod) || (!GetterMethod && SetterMethod)) {
+        SourceLocation MethodLoc = 
+          (GetterMethod ? GetterMethod->getLocation() 
+                        : SetterMethod->getLocation());
+        Diag(MethodLoc, diag::warn_atomic_property_rule)
+          << Property->getIdentifier();
+        Diag(Property->getLocation(), diag::note_property_declare);
+      }
+    }
+  }
+}
+
+/// ActOnForwardClassDeclaration -
+Action::DeclPtrTy
+Sema::ActOnForwardClassDeclaration(SourceLocation AtClassLoc,
+                                   IdentifierInfo **IdentList,
+                                   SourceLocation *IdentLocs,
+                                   unsigned NumElts) {
+  llvm::SmallVector<ObjCInterfaceDecl*, 32> Interfaces;
+
+  for (unsigned i = 0; i != NumElts; ++i) {
+    // Check for another declaration kind with the same name.
+    NamedDecl *PrevDecl
+      = LookupSingleName(TUScope, IdentList[i], LookupOrdinaryName);
+    if (PrevDecl && PrevDecl->isTemplateParameter()) {
+      // Maybe we will complain about the shadowed template parameter.
+      DiagnoseTemplateParameterShadow(AtClassLoc, PrevDecl);
+      // Just pretend that we didn't see the previous declaration.
+      PrevDecl = 0;
+    }
+
+    if (PrevDecl && !isa<ObjCInterfaceDecl>(PrevDecl)) {
+      // GCC apparently allows the following idiom:
+      //
+      // typedef NSObject < XCElementTogglerP > XCElementToggler;
+      // @class XCElementToggler;
+      //
+      // FIXME: Make an extension?
+      TypedefDecl *TDD = dyn_cast<TypedefDecl>(PrevDecl);
+      if (!TDD || !isa<ObjCInterfaceType>(TDD->getUnderlyingType())) {
+        Diag(AtClassLoc, diag::err_redefinition_different_kind) << IdentList[i];
+        Diag(PrevDecl->getLocation(), diag::note_previous_definition);
+      } else if (TDD) {
+        // a forward class declaration matching a typedef name of a class refers
+        // to the underlying class.
+        if (ObjCInterfaceType * OI =
+              dyn_cast<ObjCInterfaceType>(TDD->getUnderlyingType()))
+          PrevDecl = OI->getDecl();
+      }
+    }
+    ObjCInterfaceDecl *IDecl = dyn_cast_or_null<ObjCInterfaceDecl>(PrevDecl);
+    if (!IDecl) {  // Not already seen?  Make a forward decl.
+      IDecl = ObjCInterfaceDecl::Create(Context, CurContext, AtClassLoc,
+                                        IdentList[i], IdentLocs[i], true);
+      
+      // Push the ObjCInterfaceDecl on the scope chain but do *not* add it to
+      // the current DeclContext.  This prevents clients that walk DeclContext
+      // from seeing the imaginary ObjCInterfaceDecl until it is actually
+      // declared later (if at all).  We also take care to explicitly make
+      // sure this declaration is visible for name lookup.
+      PushOnScopeChains(IDecl, TUScope, false);
+      CurContext->makeDeclVisibleInContext(IDecl, true);
+    }
+
+    Interfaces.push_back(IDecl);
+  }
+
+  assert(Interfaces.size() == NumElts);
+  ObjCClassDecl *CDecl = ObjCClassDecl::Create(Context, CurContext, AtClassLoc,
+                                               Interfaces.data(), IdentLocs,
+                                               Interfaces.size());
+  CurContext->addDecl(CDecl);
+  CheckObjCDeclScope(CDecl);
+  return DeclPtrTy::make(CDecl);
+}
+
+
+/// MatchTwoMethodDeclarations - Checks that two methods have matching type and
+/// returns true, or false, accordingly.
+/// TODO: Handle protocol list; such as id<p1,p2> in type comparisons
+bool Sema::MatchTwoMethodDeclarations(const ObjCMethodDecl *Method,
+                                      const ObjCMethodDecl *PrevMethod,
+                                      bool matchBasedOnSizeAndAlignment) {
+  QualType T1 = Context.getCanonicalType(Method->getResultType());
+  QualType T2 = Context.getCanonicalType(PrevMethod->getResultType());
+
+  if (T1 != T2) {
+    // The result types are different.
+    if (!matchBasedOnSizeAndAlignment)
+      return false;
+    // Incomplete types don't have a size and alignment.
+    if (T1->isIncompleteType() || T2->isIncompleteType())
+      return false;
+    // Check is based on size and alignment.
+    if (Context.getTypeInfo(T1) != Context.getTypeInfo(T2))
+      return false;
+  }
+
+  ObjCMethodDecl::param_iterator ParamI = Method->param_begin(),
+       E = Method->param_end();
+  ObjCMethodDecl::param_iterator PrevI = PrevMethod->param_begin();
+
+  for (; ParamI != E; ++ParamI, ++PrevI) {
+    assert(PrevI != PrevMethod->param_end() && "Param mismatch");
+    T1 = Context.getCanonicalType((*ParamI)->getType());
+    T2 = Context.getCanonicalType((*PrevI)->getType());
+    if (T1 != T2) {
+      // The result types are different.
+      if (!matchBasedOnSizeAndAlignment)
+        return false;
+      // Incomplete types don't have a size and alignment.
+      if (T1->isIncompleteType() || T2->isIncompleteType())
+        return false;
+      // Check is based on size and alignment.
+      if (Context.getTypeInfo(T1) != Context.getTypeInfo(T2))
+        return false;
+    }
+  }
+  return true;
+}
+
+/// \brief Read the contents of the instance and factory method pools
+/// for a given selector from external storage.
+///
+/// This routine should only be called once, when neither the instance
+/// nor the factory method pool has an entry for this selector.
+Sema::MethodPool::iterator Sema::ReadMethodPool(Selector Sel,
+                                                bool isInstance) {
+  assert(ExternalSource && "We need an external AST source");
+  assert(InstanceMethodPool.find(Sel) == InstanceMethodPool.end() &&
+         "Selector data already loaded into the instance method pool");
+  assert(FactoryMethodPool.find(Sel) == FactoryMethodPool.end() &&
+         "Selector data already loaded into the factory method pool");
+
+  // Read the method list from the external source.
+  std::pair<ObjCMethodList, ObjCMethodList> Methods
+    = ExternalSource->ReadMethodPool(Sel);
+
+  if (isInstance) {
+    if (Methods.second.Method)
+      FactoryMethodPool[Sel] = Methods.second;
+    return InstanceMethodPool.insert(std::make_pair(Sel, Methods.first)).first;
+  }
+
+  if (Methods.first.Method)
+    InstanceMethodPool[Sel] = Methods.first;
+
+  return FactoryMethodPool.insert(std::make_pair(Sel, Methods.second)).first;
+}
+
+void Sema::AddInstanceMethodToGlobalPool(ObjCMethodDecl *Method) {
+  llvm::DenseMap<Selector, ObjCMethodList>::iterator Pos
+    = InstanceMethodPool.find(Method->getSelector());
+  if (Pos == InstanceMethodPool.end()) {
+    if (ExternalSource && !FactoryMethodPool.count(Method->getSelector()))
+      Pos = ReadMethodPool(Method->getSelector(), /*isInstance=*/true);
+    else
+      Pos = InstanceMethodPool.insert(std::make_pair(Method->getSelector(),
+                                                     ObjCMethodList())).first;
+  }
+
+  ObjCMethodList &Entry = Pos->second;
+  if (Entry.Method == 0) {
+    // Haven't seen a method with this selector name yet - add it.
+    Entry.Method = Method;
+    Entry.Next = 0;
+    return;
+  }
+
+  // We've seen a method with this name, see if we have already seen this type
+  // signature.
+  for (ObjCMethodList *List = &Entry; List; List = List->Next)
+    if (MatchTwoMethodDeclarations(Method, List->Method))
+      return;
+
+  // We have a new signature for an existing method - add it.
+  // This is extremely rare. Only 1% of Cocoa selectors are "overloaded".
+  Entry.Next = new ObjCMethodList(Method, Entry.Next);
+}
+
+// FIXME: Finish implementing -Wno-strict-selector-match.
+ObjCMethodDecl *Sema::LookupInstanceMethodInGlobalPool(Selector Sel,
+                                                       SourceRange R,
+                                                       bool warn) {
+  llvm::DenseMap<Selector, ObjCMethodList>::iterator Pos
+    = InstanceMethodPool.find(Sel);
+  if (Pos == InstanceMethodPool.end()) {
+    if (ExternalSource && !FactoryMethodPool.count(Sel))
+      Pos = ReadMethodPool(Sel, /*isInstance=*/true);
+    else
+      return 0;
+  }
+
+  ObjCMethodList &MethList = Pos->second;
+  bool issueWarning = false;
+
+  if (MethList.Method && MethList.Next) {
+    for (ObjCMethodList *Next = MethList.Next; Next; Next = Next->Next)
+      // This checks if the methods differ by size & alignment.
+      if (!MatchTwoMethodDeclarations(MethList.Method, Next->Method, true))
+        issueWarning = warn;
+  }
+  if (issueWarning && (MethList.Method && MethList.Next)) {
+    Diag(R.getBegin(), diag::warn_multiple_method_decl) << Sel << R;
+    Diag(MethList.Method->getLocStart(), diag::note_using)
+      << MethList.Method->getSourceRange();
+    for (ObjCMethodList *Next = MethList.Next; Next; Next = Next->Next)
+      Diag(Next->Method->getLocStart(), diag::note_also_found)
+        << Next->Method->getSourceRange();
+  }
+  return MethList.Method;
+}
+
+void Sema::AddFactoryMethodToGlobalPool(ObjCMethodDecl *Method) {
+  llvm::DenseMap<Selector, ObjCMethodList>::iterator Pos
+    = FactoryMethodPool.find(Method->getSelector());
+  if (Pos == FactoryMethodPool.end()) {
+    if (ExternalSource && !InstanceMethodPool.count(Method->getSelector()))
+      Pos = ReadMethodPool(Method->getSelector(), /*isInstance=*/false);
+    else
+      Pos = FactoryMethodPool.insert(std::make_pair(Method->getSelector(),
+                                                    ObjCMethodList())).first;
+  }
+
+  ObjCMethodList &FirstMethod = Pos->second;
+  if (!FirstMethod.Method) {
+    // Haven't seen a method with this selector name yet - add it.
+    FirstMethod.Method = Method;
+    FirstMethod.Next = 0;
+  } else {
+    // We've seen a method with this name, now check the type signature(s).
+    bool match = MatchTwoMethodDeclarations(Method, FirstMethod.Method);
+
+    for (ObjCMethodList *Next = FirstMethod.Next; !match && Next;
+         Next = Next->Next)
+      match = MatchTwoMethodDeclarations(Method, Next->Method);
+
+    if (!match) {
+      // We have a new signature for an existing method - add it.
+      // This is extremely rare. Only 1% of Cocoa selectors are "overloaded".
+      struct ObjCMethodList *OMI = new ObjCMethodList(Method, FirstMethod.Next);
+      FirstMethod.Next = OMI;
+    }
+  }
+}
+
+ObjCMethodDecl *Sema::LookupFactoryMethodInGlobalPool(Selector Sel,
+                                                      SourceRange R) {
+  llvm::DenseMap<Selector, ObjCMethodList>::iterator Pos
+    = FactoryMethodPool.find(Sel);
+  if (Pos == FactoryMethodPool.end()) {
+    if (ExternalSource && !InstanceMethodPool.count(Sel))
+      Pos = ReadMethodPool(Sel, /*isInstance=*/false);
+    else
+      return 0;
+  }
+
+  ObjCMethodList &MethList = Pos->second;
+  bool issueWarning = false;
+
+  if (MethList.Method && MethList.Next) {
+    for (ObjCMethodList *Next = MethList.Next; Next; Next = Next->Next)
+      // This checks if the methods differ by size & alignment.
+      if (!MatchTwoMethodDeclarations(MethList.Method, Next->Method, true))
+        issueWarning = true;
+  }
+  if (issueWarning && (MethList.Method && MethList.Next)) {
+    Diag(R.getBegin(), diag::warn_multiple_method_decl) << Sel << R;
+    Diag(MethList.Method->getLocStart(), diag::note_using)
+      << MethList.Method->getSourceRange();
+    for (ObjCMethodList *Next = MethList.Next; Next; Next = Next->Next)
+      Diag(Next->Method->getLocStart(), diag::note_also_found)
+        << Next->Method->getSourceRange();
+  }
+  return MethList.Method;
+}
+
+/// ProcessPropertyDecl - Make sure that any user-defined setter/getter methods
+/// have the property type and issue diagnostics if they don't.
+/// Also synthesize a getter/setter method if none exist (and update the
+/// appropriate lookup tables. FIXME: Should reconsider if adding synthesized
+/// methods is the "right" thing to do.
+void Sema::ProcessPropertyDecl(ObjCPropertyDecl *property,
+                               ObjCContainerDecl *CD) {
+  ObjCMethodDecl *GetterMethod, *SetterMethod;
+
+  GetterMethod = CD->getInstanceMethod(property->getGetterName());
+  SetterMethod = CD->getInstanceMethod(property->getSetterName());
+  DiagnosePropertyAccessorMismatch(property, GetterMethod,
+                                   property->getLocation());
+
+  if (SetterMethod) {
+    ObjCPropertyDecl::PropertyAttributeKind CAttr = 
+      property->getPropertyAttributes();
+    if ((!(CAttr & ObjCPropertyDecl::OBJC_PR_readonly)) &&
+        Context.getCanonicalType(SetterMethod->getResultType()) != 
+          Context.VoidTy)
+      Diag(SetterMethod->getLocation(), diag::err_setter_type_void);
+    if (SetterMethod->param_size() != 1 ||
+        ((*SetterMethod->param_begin())->getType() != property->getType())) {
+      Diag(property->getLocation(),
+           diag::warn_accessor_property_type_mismatch)
+        << property->getDeclName()
+        << SetterMethod->getSelector();
+      Diag(SetterMethod->getLocation(), diag::note_declared_at);
+    }
+  }
+
+  // Synthesize getter/setter methods if none exist.
+  // Find the default getter and if one not found, add one.
+  // FIXME: The synthesized property we set here is misleading. We almost always
+  // synthesize these methods unless the user explicitly provided prototypes
+  // (which is odd, but allowed). Sema should be typechecking that the
+  // declarations jive in that situation (which it is not currently).
+  if (!GetterMethod) {
+    // No instance method of same name as property getter name was found.
+    // Declare a getter method and add it to the list of methods
+    // for this class.
+    GetterMethod = ObjCMethodDecl::Create(Context, property->getLocation(),
+                             property->getLocation(), property->getGetterName(),
+                             property->getType(), CD, true, false, true,
+                             (property->getPropertyImplementation() ==
+                              ObjCPropertyDecl::Optional) ?
+                             ObjCMethodDecl::Optional :
+                             ObjCMethodDecl::Required);
+    CD->addDecl(GetterMethod);
+  } else
+    // A user declared getter will be synthesize when @synthesize of
+    // the property with the same name is seen in the @implementation
+    GetterMethod->setSynthesized(true);
+  property->setGetterMethodDecl(GetterMethod);
+
+  // Skip setter if property is read-only.
+  if (!property->isReadOnly()) {
+    // Find the default setter and if one not found, add one.
+    if (!SetterMethod) {
+      // No instance method of same name as property setter name was found.
+      // Declare a setter method and add it to the list of methods
+      // for this class.
+      SetterMethod = ObjCMethodDecl::Create(Context, property->getLocation(),
+                               property->getLocation(),
+                               property->getSetterName(),
+                               Context.VoidTy, CD, true, false, true,
+                               (property->getPropertyImplementation() ==
+                                ObjCPropertyDecl::Optional) ?
+                               ObjCMethodDecl::Optional :
+                               ObjCMethodDecl::Required);
+      // Invent the arguments for the setter. We don't bother making a
+      // nice name for the argument.
+      ParmVarDecl *Argument = ParmVarDecl::Create(Context, SetterMethod,
+                                                  property->getLocation(),
+                                                  property->getIdentifier(),
+                                                  property->getType(),
+                                                  /*TInfo=*/0,
+                                                  VarDecl::None,
+                                                  0);
+      SetterMethod->setMethodParams(Context, &Argument, 1);
+      CD->addDecl(SetterMethod);
+    } else
+      // A user declared setter will be synthesize when @synthesize of
+      // the property with the same name is seen in the @implementation
+      SetterMethod->setSynthesized(true);
+    property->setSetterMethodDecl(SetterMethod);
+  }
+  // Add any synthesized methods to the global pool. This allows us to
+  // handle the following, which is supported by GCC (and part of the design).
+  //
+  // @interface Foo
+  // @property double bar;
+  // @end
+  //
+  // void thisIsUnfortunate() {
+  //   id foo;
+  //   double bar = [foo bar];
+  // }
+  //
+  if (GetterMethod)
+    AddInstanceMethodToGlobalPool(GetterMethod);
+  if (SetterMethod)
+    AddInstanceMethodToGlobalPool(SetterMethod);
+}
+
+/// CompareMethodParamsInBaseAndSuper - This routine compares methods with
+/// identical selector names in current and its super classes and issues
+/// a warning if any of their argument types are incompatible.
+void Sema::CompareMethodParamsInBaseAndSuper(Decl *ClassDecl,
+                                             ObjCMethodDecl *Method,
+                                             bool IsInstance)  {
+  ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(ClassDecl);
+  if (ID == 0) return;
+
+  while (ObjCInterfaceDecl *SD = ID->getSuperClass()) {
+    ObjCMethodDecl *SuperMethodDecl =
+        SD->lookupMethod(Method->getSelector(), IsInstance);
+    if (SuperMethodDecl == 0) {
+      ID = SD;
+      continue;
+    }
+    ObjCMethodDecl::param_iterator ParamI = Method->param_begin(),
+      E = Method->param_end();
+    ObjCMethodDecl::param_iterator PrevI = SuperMethodDecl->param_begin();
+    for (; ParamI != E; ++ParamI, ++PrevI) {
+      // Number of parameters are the same and is guaranteed by selector match.
+      assert(PrevI != SuperMethodDecl->param_end() && "Param mismatch");
+      QualType T1 = Context.getCanonicalType((*ParamI)->getType());
+      QualType T2 = Context.getCanonicalType((*PrevI)->getType());
+      // If type of arguement of method in this class does not match its
+      // respective argument type in the super class method, issue warning;
+      if (!Context.typesAreCompatible(T1, T2)) {
+        Diag((*ParamI)->getLocation(), diag::ext_typecheck_base_super)
+          << T1 << T2;
+        Diag(SuperMethodDecl->getLocation(), diag::note_previous_declaration);
+        return;
+      }
+    }
+    ID = SD;
+  }
+}
+
+// Note: For class/category implemenations, allMethods/allProperties is
+// always null.
+void Sema::ActOnAtEnd(SourceRange AtEnd,
+                      DeclPtrTy classDecl,
+                      DeclPtrTy *allMethods, unsigned allNum,
+                      DeclPtrTy *allProperties, unsigned pNum,
+                      DeclGroupPtrTy *allTUVars, unsigned tuvNum) {
+  Decl *ClassDecl = classDecl.getAs<Decl>();
+
+  // FIXME: If we don't have a ClassDecl, we have an error. We should consider
+  // always passing in a decl. If the decl has an error, isInvalidDecl()
+  // should be true.
+  if (!ClassDecl)
+    return;
+  
+  bool isInterfaceDeclKind =
+        isa<ObjCInterfaceDecl>(ClassDecl) || isa<ObjCCategoryDecl>(ClassDecl)
+         || isa<ObjCProtocolDecl>(ClassDecl);
+  bool checkIdenticalMethods = isa<ObjCImplementationDecl>(ClassDecl);
+
+  if (!isInterfaceDeclKind && AtEnd.isInvalid()) {
+    // FIXME: This is wrong.  We shouldn't be pretending that there is
+    //  an '@end' in the declaration.
+    SourceLocation L = ClassDecl->getLocation();
+    AtEnd.setBegin(L);
+    AtEnd.setEnd(L);
+    Diag(L, diag::warn_missing_atend);
+  }
+  
+  DeclContext *DC = dyn_cast<DeclContext>(ClassDecl);
+
+  // FIXME: Remove these and use the ObjCContainerDecl/DeclContext.
+  llvm::DenseMap<Selector, const ObjCMethodDecl*> InsMap;
+  llvm::DenseMap<Selector, const ObjCMethodDecl*> ClsMap;
+
+  for (unsigned i = 0; i < allNum; i++ ) {
+    ObjCMethodDecl *Method =
+      cast_or_null<ObjCMethodDecl>(allMethods[i].getAs<Decl>());
+
+    if (!Method) continue;  // Already issued a diagnostic.
+    if (Method->isInstanceMethod()) {
+      /// Check for instance method of the same name with incompatible types
+      const ObjCMethodDecl *&PrevMethod = InsMap[Method->getSelector()];
+      bool match = PrevMethod ? MatchTwoMethodDeclarations(Method, PrevMethod)
+                              : false;
+      if ((isInterfaceDeclKind && PrevMethod && !match)
+          || (checkIdenticalMethods && match)) {
+          Diag(Method->getLocation(), diag::err_duplicate_method_decl)
+            << Method->getDeclName();
+          Diag(PrevMethod->getLocation(), diag::note_previous_declaration);
+      } else {
+        DC->addDecl(Method);
+        InsMap[Method->getSelector()] = Method;
+        /// The following allows us to typecheck messages to "id".
+        AddInstanceMethodToGlobalPool(Method);
+        // verify that the instance method conforms to the same definition of
+        // parent methods if it shadows one.
+        CompareMethodParamsInBaseAndSuper(ClassDecl, Method, true);
+      }
+    } else {
+      /// Check for class method of the same name with incompatible types
+      const ObjCMethodDecl *&PrevMethod = ClsMap[Method->getSelector()];
+      bool match = PrevMethod ? MatchTwoMethodDeclarations(Method, PrevMethod)
+                              : false;
+      if ((isInterfaceDeclKind && PrevMethod && !match)
+          || (checkIdenticalMethods && match)) {
+        Diag(Method->getLocation(), diag::err_duplicate_method_decl)
+          << Method->getDeclName();
+        Diag(PrevMethod->getLocation(), diag::note_previous_declaration);
+      } else {
+        DC->addDecl(Method);
+        ClsMap[Method->getSelector()] = Method;
+        /// The following allows us to typecheck messages to "Class".
+        AddFactoryMethodToGlobalPool(Method);
+        // verify that the class method conforms to the same definition of
+        // parent methods if it shadows one.
+        CompareMethodParamsInBaseAndSuper(ClassDecl, Method, false);
+      }
+    }
+  }
+  if (ObjCInterfaceDecl *I = dyn_cast<ObjCInterfaceDecl>(ClassDecl)) {
+    // Compares properties declared in this class to those of its
+    // super class.
+    ComparePropertiesInBaseAndSuper(I);
+    CompareProperties(I, DeclPtrTy::make(I));
+  } else if (ObjCCategoryDecl *C = dyn_cast<ObjCCategoryDecl>(ClassDecl)) {
+    // Categories are used to extend the class by declaring new methods.
+    // By the same token, they are also used to add new properties. No
+    // need to compare the added property to those in the class.
+
+    // Compare protocol properties with those in category
+    CompareProperties(C, DeclPtrTy::make(C));
+    if (C->getIdentifier() == 0)
+      DiagnoseClassExtensionDupMethods(C, C->getClassInterface());
+  }
+  if (ObjCContainerDecl *CDecl = dyn_cast<ObjCContainerDecl>(ClassDecl)) {
+    // ProcessPropertyDecl is responsible for diagnosing conflicts with any
+    // user-defined setter/getter. It also synthesizes setter/getter methods
+    // and adds them to the DeclContext and global method pools.
+    for (ObjCContainerDecl::prop_iterator I = CDecl->prop_begin(),
+                                          E = CDecl->prop_end();
+         I != E; ++I)
+      ProcessPropertyDecl(*I, CDecl);
+    CDecl->setAtEndRange(AtEnd);
+  }
+  if (ObjCImplementationDecl *IC=dyn_cast<ObjCImplementationDecl>(ClassDecl)) {
+    IC->setAtEndRange(AtEnd);
+    if (ObjCInterfaceDecl* IDecl = IC->getClassInterface()) {
+      ImplMethodsVsClassMethods(IC, IDecl);
+      AtomicPropertySetterGetterRules(IC, IDecl);
+    }
+  } else if (ObjCCategoryImplDecl* CatImplClass =
+                                   dyn_cast<ObjCCategoryImplDecl>(ClassDecl)) {
+    CatImplClass->setAtEndRange(AtEnd);
+
+    // Find category interface decl and then check that all methods declared
+    // in this interface are implemented in the category @implementation.
+    if (ObjCInterfaceDecl* IDecl = CatImplClass->getClassInterface()) {
+      for (ObjCCategoryDecl *Categories = IDecl->getCategoryList();
+           Categories; Categories = Categories->getNextClassCategory()) {
+        if (Categories->getIdentifier() == CatImplClass->getIdentifier()) {
+          ImplMethodsVsClassMethods(CatImplClass, Categories);
+          break;
+        }
+      }
+    }
+  }
+  if (isInterfaceDeclKind) {
+    // Reject invalid vardecls.
+    for (unsigned i = 0; i != tuvNum; i++) {
+      DeclGroupRef DG = allTUVars[i].getAsVal<DeclGroupRef>();
+      for (DeclGroupRef::iterator I = DG.begin(), E = DG.end(); I != E; ++I)
+        if (VarDecl *VDecl = dyn_cast<VarDecl>(*I)) {
+          if (!VDecl->hasExternalStorage())
+            Diag(VDecl->getLocation(), diag::err_objc_var_decl_inclass);
+        }
+    }
+  }
+}
+
+
+/// CvtQTToAstBitMask - utility routine to produce an AST bitmask for
+/// objective-c's type qualifier from the parser version of the same info.
+static Decl::ObjCDeclQualifier
+CvtQTToAstBitMask(ObjCDeclSpec::ObjCDeclQualifier PQTVal) {
+  Decl::ObjCDeclQualifier ret = Decl::OBJC_TQ_None;
+  if (PQTVal & ObjCDeclSpec::DQ_In)
+    ret = (Decl::ObjCDeclQualifier)(ret | Decl::OBJC_TQ_In);
+  if (PQTVal & ObjCDeclSpec::DQ_Inout)
+    ret = (Decl::ObjCDeclQualifier)(ret | Decl::OBJC_TQ_Inout);
+  if (PQTVal & ObjCDeclSpec::DQ_Out)
+    ret = (Decl::ObjCDeclQualifier)(ret | Decl::OBJC_TQ_Out);
+  if (PQTVal & ObjCDeclSpec::DQ_Bycopy)
+    ret = (Decl::ObjCDeclQualifier)(ret | Decl::OBJC_TQ_Bycopy);
+  if (PQTVal & ObjCDeclSpec::DQ_Byref)
+    ret = (Decl::ObjCDeclQualifier)(ret | Decl::OBJC_TQ_Byref);
+  if (PQTVal & ObjCDeclSpec::DQ_Oneway)
+    ret = (Decl::ObjCDeclQualifier)(ret | Decl::OBJC_TQ_Oneway);
+
+  return ret;
+}
+
+Sema::DeclPtrTy Sema::ActOnMethodDeclaration(
+    SourceLocation MethodLoc, SourceLocation EndLoc,
+    tok::TokenKind MethodType, DeclPtrTy classDecl,
+    ObjCDeclSpec &ReturnQT, TypeTy *ReturnType,
+    Selector Sel,
+    // optional arguments. The number of types/arguments is obtained
+    // from the Sel.getNumArgs().
+    ObjCArgInfo *ArgInfo,
+    llvm::SmallVectorImpl<Declarator> &Cdecls,
+    AttributeList *AttrList, tok::ObjCKeywordKind MethodDeclKind,
+    bool isVariadic) {
+  Decl *ClassDecl = classDecl.getAs<Decl>();
+
+  // Make sure we can establish a context for the method.
+  if (!ClassDecl) {
+    Diag(MethodLoc, diag::error_missing_method_context);
+    FunctionLabelMap.clear();
+    return DeclPtrTy();
+  }
+  QualType resultDeclType;
+
+  if (ReturnType) {
+    resultDeclType = GetTypeFromParser(ReturnType);
+
+    // Methods cannot return interface types. All ObjC objects are
+    // passed by reference.
+    if (resultDeclType->isObjCInterfaceType()) {
+      Diag(MethodLoc, diag::err_object_cannot_be_passed_returned_by_value)
+        << 0 << resultDeclType;
+      return DeclPtrTy();
+    }
+  } else // get the type for "id".
+    resultDeclType = Context.getObjCIdType();
+
+  ObjCMethodDecl* ObjCMethod =
+    ObjCMethodDecl::Create(Context, MethodLoc, EndLoc, Sel, resultDeclType,
+                           cast<DeclContext>(ClassDecl),
+                           MethodType == tok::minus, isVariadic,
+                           false,
+                           MethodDeclKind == tok::objc_optional ?
+                           ObjCMethodDecl::Optional :
+                           ObjCMethodDecl::Required);
+
+  llvm::SmallVector<ParmVarDecl*, 16> Params;
+
+  for (unsigned i = 0, e = Sel.getNumArgs(); i != e; ++i) {
+    QualType ArgType;
+    TypeSourceInfo *DI;
+
+    if (ArgInfo[i].Type == 0) {
+      ArgType = Context.getObjCIdType();
+      DI = 0;
+    } else {
+      ArgType = GetTypeFromParser(ArgInfo[i].Type, &DI);
+      // Perform the default array/function conversions (C99 6.7.5.3p[7,8]).
+      ArgType = adjustParameterType(ArgType);
+    }
+
+    ParmVarDecl* Param
+      = ParmVarDecl::Create(Context, ObjCMethod, ArgInfo[i].NameLoc,
+                            ArgInfo[i].Name, ArgType, DI,
+                            VarDecl::None, 0);
+
+    if (ArgType->isObjCInterfaceType()) {
+      Diag(ArgInfo[i].NameLoc,
+           diag::err_object_cannot_be_passed_returned_by_value)
+        << 1 << ArgType;
+      Param->setInvalidDecl();
+    }
+
+    Param->setObjCDeclQualifier(
+      CvtQTToAstBitMask(ArgInfo[i].DeclSpec.getObjCDeclQualifier()));
+
+    // Apply the attributes to the parameter.
+    ProcessDeclAttributeList(TUScope, Param, ArgInfo[i].ArgAttrs);
+
+    Params.push_back(Param);
+  }
+
+  ObjCMethod->setMethodParams(Context, Params.data(), Sel.getNumArgs());
+  ObjCMethod->setObjCDeclQualifier(
+    CvtQTToAstBitMask(ReturnQT.getObjCDeclQualifier()));
+  const ObjCMethodDecl *PrevMethod = 0;
+
+  if (AttrList)
+    ProcessDeclAttributeList(TUScope, ObjCMethod, AttrList);
+
+  const ObjCMethodDecl *InterfaceMD = 0;
+
+  // For implementations (which can be very "coarse grain"), we add the
+  // method now. This allows the AST to implement lookup methods that work
+  // incrementally (without waiting until we parse the @end). It also allows
+  // us to flag multiple declaration errors as they occur.
+  if (ObjCImplementationDecl *ImpDecl =
+        dyn_cast<ObjCImplementationDecl>(ClassDecl)) {
+    if (MethodType == tok::minus) {
+      PrevMethod = ImpDecl->getInstanceMethod(Sel);
+      ImpDecl->addInstanceMethod(ObjCMethod);
+    } else {
+      PrevMethod = ImpDecl->getClassMethod(Sel);
+      ImpDecl->addClassMethod(ObjCMethod);
+    }
+    InterfaceMD = ImpDecl->getClassInterface()->getMethod(Sel,
+                                                   MethodType == tok::minus);
+    if (AttrList)
+      Diag(EndLoc, diag::warn_attribute_method_def);
+  } else if (ObjCCategoryImplDecl *CatImpDecl =
+             dyn_cast<ObjCCategoryImplDecl>(ClassDecl)) {
+    if (MethodType == tok::minus) {
+      PrevMethod = CatImpDecl->getInstanceMethod(Sel);
+      CatImpDecl->addInstanceMethod(ObjCMethod);
+    } else {
+      PrevMethod = CatImpDecl->getClassMethod(Sel);
+      CatImpDecl->addClassMethod(ObjCMethod);
+    }
+    if (AttrList)
+      Diag(EndLoc, diag::warn_attribute_method_def);
+  }
+  if (PrevMethod) {
+    // You can never have two method definitions with the same name.
+    Diag(ObjCMethod->getLocation(), diag::err_duplicate_method_decl)
+      << ObjCMethod->getDeclName();
+    Diag(PrevMethod->getLocation(), diag::note_previous_declaration);
+  }
+
+  // If the interface declared this method, and it was deprecated there,
+  // mark it deprecated here.
+  if (InterfaceMD && InterfaceMD->hasAttr<DeprecatedAttr>())
+    ObjCMethod->addAttr(::new (Context) DeprecatedAttr());
+
+  return DeclPtrTy::make(ObjCMethod);
+}
+
+void Sema::CheckObjCPropertyAttributes(QualType PropertyTy,
+                                       SourceLocation Loc,
+                                       unsigned &Attributes) {
+  // FIXME: Improve the reported location.
+
+  // readonly and readwrite/assign/retain/copy conflict.
+  if ((Attributes & ObjCDeclSpec::DQ_PR_readonly) &&
+      (Attributes & (ObjCDeclSpec::DQ_PR_readwrite |
+                     ObjCDeclSpec::DQ_PR_assign |
+                     ObjCDeclSpec::DQ_PR_copy |
+                     ObjCDeclSpec::DQ_PR_retain))) {
+    const char * which = (Attributes & ObjCDeclSpec::DQ_PR_readwrite) ?
+                          "readwrite" :
+                         (Attributes & ObjCDeclSpec::DQ_PR_assign) ?
+                          "assign" :
+                         (Attributes & ObjCDeclSpec::DQ_PR_copy) ?
+                          "copy" : "retain";
+
+    Diag(Loc, (Attributes & (ObjCDeclSpec::DQ_PR_readwrite)) ?
+                 diag::err_objc_property_attr_mutually_exclusive :
+                 diag::warn_objc_property_attr_mutually_exclusive)
+      << "readonly" << which;
+  }
+
+  // Check for copy or retain on non-object types.
+  if ((Attributes & (ObjCDeclSpec::DQ_PR_copy | ObjCDeclSpec::DQ_PR_retain)) &&
+      !PropertyTy->isObjCObjectPointerType() &&
+      !PropertyTy->isBlockPointerType() &&
+      !Context.isObjCNSObjectType(PropertyTy)) {
+    Diag(Loc, diag::err_objc_property_requires_object)
+      << (Attributes & ObjCDeclSpec::DQ_PR_copy ? "copy" : "retain");
+    Attributes &= ~(ObjCDeclSpec::DQ_PR_copy | ObjCDeclSpec::DQ_PR_retain);
+  }
+
+  // Check for more than one of { assign, copy, retain }.
+  if (Attributes & ObjCDeclSpec::DQ_PR_assign) {
+    if (Attributes & ObjCDeclSpec::DQ_PR_copy) {
+      Diag(Loc, diag::err_objc_property_attr_mutually_exclusive)
+        << "assign" << "copy";
+      Attributes &= ~ObjCDeclSpec::DQ_PR_copy;
+    }
+    if (Attributes & ObjCDeclSpec::DQ_PR_retain) {
+      Diag(Loc, diag::err_objc_property_attr_mutually_exclusive)
+        << "assign" << "retain";
+      Attributes &= ~ObjCDeclSpec::DQ_PR_retain;
+    }
+  } else if (Attributes & ObjCDeclSpec::DQ_PR_copy) {
+    if (Attributes & ObjCDeclSpec::DQ_PR_retain) {
+      Diag(Loc, diag::err_objc_property_attr_mutually_exclusive)
+        << "copy" << "retain";
+      Attributes &= ~ObjCDeclSpec::DQ_PR_retain;
+    }
+  }
+
+  // Warn if user supplied no assignment attribute, property is
+  // readwrite, and this is an object type.
+  if (!(Attributes & (ObjCDeclSpec::DQ_PR_assign | ObjCDeclSpec::DQ_PR_copy |
+                      ObjCDeclSpec::DQ_PR_retain)) &&
+      !(Attributes & ObjCDeclSpec::DQ_PR_readonly) &&
+      PropertyTy->isObjCObjectPointerType()) {
+    // Skip this warning in gc-only mode.
+    if (getLangOptions().getGCMode() != LangOptions::GCOnly)
+      Diag(Loc, diag::warn_objc_property_no_assignment_attribute);
+
+    // If non-gc code warn that this is likely inappropriate.
+    if (getLangOptions().getGCMode() == LangOptions::NonGC)
+      Diag(Loc, diag::warn_objc_property_default_assign_on_object);
+
+    // FIXME: Implement warning dependent on NSCopying being
+    // implemented. See also:
+    // <rdar://5168496&4855821&5607453&5096644&4947311&5698469&4947014&5168496>
+    // (please trim this list while you are at it).
+  }
+
+  if (!(Attributes & ObjCDeclSpec::DQ_PR_copy)
+      && getLangOptions().getGCMode() == LangOptions::GCOnly
+      && PropertyTy->isBlockPointerType())
+    Diag(Loc, diag::warn_objc_property_copy_missing_on_block);
+}
+
+Sema::DeclPtrTy Sema::ActOnProperty(Scope *S, SourceLocation AtLoc,
+                                    FieldDeclarator &FD,
+                                    ObjCDeclSpec &ODS,
+                                    Selector GetterSel,
+                                    Selector SetterSel,
+                                    DeclPtrTy ClassCategory,
+                                    bool *isOverridingProperty,
+                                    tok::ObjCKeywordKind MethodImplKind) {
+  unsigned Attributes = ODS.getPropertyAttributes();
+  bool isReadWrite = ((Attributes & ObjCDeclSpec::DQ_PR_readwrite) ||
+                      // default is readwrite!
+                      !(Attributes & ObjCDeclSpec::DQ_PR_readonly));
+  // property is defaulted to 'assign' if it is readwrite and is
+  // not retain or copy
+  bool isAssign = ((Attributes & ObjCDeclSpec::DQ_PR_assign) ||
+                   (isReadWrite &&
+                    !(Attributes & ObjCDeclSpec::DQ_PR_retain) &&
+                    !(Attributes & ObjCDeclSpec::DQ_PR_copy)));
+  QualType T = GetTypeForDeclarator(FD.D, S);
+  if (T->isReferenceType()) {
+    Diag(AtLoc, diag::error_reference_property);
+    return DeclPtrTy();
+  }
+  Decl *ClassDecl = ClassCategory.getAs<Decl>();
+  ObjCInterfaceDecl *CCPrimary = 0; // continuation class's primary class
+  // May modify Attributes.
+  CheckObjCPropertyAttributes(T, AtLoc, Attributes);
+  if (ObjCCategoryDecl *CDecl = dyn_cast<ObjCCategoryDecl>(ClassDecl))
+    if (!CDecl->getIdentifier()) {
+      // This is a continuation class. property requires special
+      // handling.
+      if ((CCPrimary = CDecl->getClassInterface())) {
+        // Find the property in continuation class's primary class only.
+        IdentifierInfo *PropertyId = FD.D.getIdentifier();
+        if (ObjCPropertyDecl *PIDecl = 
+              CCPrimary->FindPropertyVisibleInPrimaryClass(PropertyId)) {
+          // property 'PIDecl's readonly attribute will be over-ridden
+          // with continuation class's readwrite property attribute!
+          unsigned PIkind = PIDecl->getPropertyAttributes();
+          if (isReadWrite && (PIkind & ObjCPropertyDecl::OBJC_PR_readonly)) {
+            unsigned retainCopyNonatomic = 
+              (ObjCPropertyDecl::OBJC_PR_retain |
+               ObjCPropertyDecl::OBJC_PR_copy |
+               ObjCPropertyDecl::OBJC_PR_nonatomic);
+            if ((Attributes & retainCopyNonatomic) !=
+                (PIkind & retainCopyNonatomic)) {
+              Diag(AtLoc, diag::warn_property_attr_mismatch);
+              Diag(PIDecl->getLocation(), diag::note_property_declare);
+            }
+            DeclContext *DC = dyn_cast<DeclContext>(CCPrimary);
+            assert(DC && "ClassDecl is not a DeclContext");
+            DeclContext::lookup_result Found = 
+              DC->lookup(PIDecl->getDeclName());
+            bool PropertyInPrimaryClass = false;
+            for (; Found.first != Found.second; ++Found.first)
+              if (isa<ObjCPropertyDecl>(*Found.first)) {
+                PropertyInPrimaryClass = true;
+                break;
+              }
+            if (!PropertyInPrimaryClass) {
+              // Protocol is not in the primary class. Must build one for it.
+              ObjCDeclSpec ProtocolPropertyODS;
+              // FIXME. Assuming that ObjCDeclSpec::ObjCPropertyAttributeKind and
+              // ObjCPropertyDecl::PropertyAttributeKind have identical values.
+              // Should consolidate both into one enum type.
+              ProtocolPropertyODS.setPropertyAttributes(
+                (ObjCDeclSpec::ObjCPropertyAttributeKind)PIkind);
+              DeclPtrTy ProtocolPtrTy = 
+                ActOnProperty(S, AtLoc, FD, ProtocolPropertyODS, 
+                              PIDecl->getGetterName(), 
+                              PIDecl->getSetterName(), 
+                              DeclPtrTy::make(CCPrimary), isOverridingProperty, 
+                              MethodImplKind);
+              PIDecl = ProtocolPtrTy.getAs<ObjCPropertyDecl>();
+            }
+            PIDecl->makeitReadWriteAttribute();
+            if (Attributes & ObjCDeclSpec::DQ_PR_retain)
+              PIDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_retain);
+            if (Attributes & ObjCDeclSpec::DQ_PR_copy)
+              PIDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_copy);
+            PIDecl->setSetterName(SetterSel);
+          } else {
+            Diag(AtLoc, diag::err_use_continuation_class)
+              << CCPrimary->getDeclName();
+            Diag(PIDecl->getLocation(), diag::note_property_declare);
+          }
+          *isOverridingProperty = true;
+          // Make sure setter decl is synthesized, and added to primary
+          // class's list.
+          ProcessPropertyDecl(PIDecl, CCPrimary);
+          return DeclPtrTy();
+        }
+        // No matching property found in the primary class. Just fall thru
+        // and add property to continuation class's primary class.
+        ClassDecl = CCPrimary;
+      } else {
+        Diag(CDecl->getLocation(), diag::err_continuation_class);
+        *isOverridingProperty = true;
+        return DeclPtrTy();
+      }
+    }
+
+  // Issue a warning if property is 'assign' as default and its object, which is
+  // gc'able conforms to NSCopying protocol
+  if (getLangOptions().getGCMode() != LangOptions::NonGC &&
+      isAssign && !(Attributes & ObjCDeclSpec::DQ_PR_assign))
+      if (T->isObjCObjectPointerType()) {
+        QualType InterfaceTy = T->getPointeeType();
+        if (const ObjCInterfaceType *OIT =
+              InterfaceTy->getAs<ObjCInterfaceType>()) {
+        ObjCInterfaceDecl *IDecl = OIT->getDecl();
+        if (IDecl)
+          if (ObjCProtocolDecl* PNSCopying =
+                LookupProtocol(&Context.Idents.get("NSCopying")))
+            if (IDecl->ClassImplementsProtocol(PNSCopying, true))
+              Diag(AtLoc, diag::warn_implements_nscopying)
+                << FD.D.getIdentifier();
+        }
+      }
+  if (T->isObjCInterfaceType())
+    Diag(FD.D.getIdentifierLoc(), diag::err_statically_allocated_object);
+
+  DeclContext *DC = dyn_cast<DeclContext>(ClassDecl);
+  assert(DC && "ClassDecl is not a DeclContext");
+  ObjCPropertyDecl *PDecl = ObjCPropertyDecl::Create(Context, DC,
+                                                     FD.D.getIdentifierLoc(),
+                                                     FD.D.getIdentifier(), 
+                                                     AtLoc, T);
+  DeclContext::lookup_result Found = DC->lookup(PDecl->getDeclName());
+  if (Found.first != Found.second && isa<ObjCPropertyDecl>(*Found.first)) {
+    Diag(PDecl->getLocation(), diag::err_duplicate_property);
+    Diag((*Found.first)->getLocation(), diag::note_property_declare);
+    PDecl->setInvalidDecl();
+  }
+  else
+    DC->addDecl(PDecl);
+
+  if (T->isArrayType() || T->isFunctionType()) {
+    Diag(AtLoc, diag::err_property_type) << T;
+    PDecl->setInvalidDecl();
+  }
+
+  ProcessDeclAttributes(S, PDecl, FD.D);
+
+  // Regardless of setter/getter attribute, we save the default getter/setter
+  // selector names in anticipation of declaration of setter/getter methods.
+  PDecl->setGetterName(GetterSel);
+  PDecl->setSetterName(SetterSel);
+
+  if (Attributes & ObjCDeclSpec::DQ_PR_readonly)
+    PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_readonly);
+
+  if (Attributes & ObjCDeclSpec::DQ_PR_getter)
+    PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_getter);
+
+  if (Attributes & ObjCDeclSpec::DQ_PR_setter)
+    PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_setter);
+
+  if (isReadWrite)
+    PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_readwrite);
+
+  if (Attributes & ObjCDeclSpec::DQ_PR_retain)
+    PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_retain);
+
+  if (Attributes & ObjCDeclSpec::DQ_PR_copy)
+    PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_copy);
+
+  if (isAssign)
+    PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_assign);
+
+  if (Attributes & ObjCDeclSpec::DQ_PR_nonatomic)
+    PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_nonatomic);
+
+  if (MethodImplKind == tok::objc_required)
+    PDecl->setPropertyImplementation(ObjCPropertyDecl::Required);
+  else if (MethodImplKind == tok::objc_optional)
+    PDecl->setPropertyImplementation(ObjCPropertyDecl::Optional);
+  // A case of continuation class adding a new property in the class. This
+  // is not what it was meant for. However, gcc supports it and so should we.
+  // Make sure setter/getters are declared here.
+  if (CCPrimary)
+    ProcessPropertyDecl(PDecl, CCPrimary);
+
+  return DeclPtrTy::make(PDecl);
+}
+
+ObjCIvarDecl* 
+Sema::SynthesizeNewPropertyIvar(ObjCInterfaceDecl *IDecl,
+                                IdentifierInfo *NameII) {
+  ObjCIvarDecl *Ivar = 0;
+  ObjCPropertyDecl *Prop = LookupPropertyDecl(IDecl, NameII);
+  if (Prop && !Prop->isInvalidDecl()) {
+    DeclContext *EnclosingContext = cast_or_null<DeclContext>(IDecl);
+    QualType PropType = Context.getCanonicalType(Prop->getType());
+    assert(EnclosingContext &&
+           "null DeclContext for synthesized ivar - SynthesizeNewPropertyIvar");
+    Ivar = ObjCIvarDecl::Create(Context, EnclosingContext, 
+                                              Prop->getLocation(),
+                                              NameII, PropType, /*Dinfo=*/0,
+                                              ObjCIvarDecl::Public,
+                                              (Expr *)0);
+    Ivar->setLexicalDeclContext(IDecl);
+    IDecl->addDecl(Ivar);
+    Prop->setPropertyIvarDecl(Ivar);
+  }
+  return Ivar;
+}
+
+/// ActOnPropertyImplDecl - This routine performs semantic checks and
+/// builds the AST node for a property implementation declaration; declared
+/// as @synthesize or @dynamic.
+///
+Sema::DeclPtrTy Sema::ActOnPropertyImplDecl(SourceLocation AtLoc,
+                                            SourceLocation PropertyLoc,
+                                            bool Synthesize,
+                                            DeclPtrTy ClassCatImpDecl,
+                                            IdentifierInfo *PropertyId,
+                                            IdentifierInfo *PropertyIvar) {
+  Decl *ClassImpDecl = ClassCatImpDecl.getAs<Decl>();
+  // Make sure we have a context for the property implementation declaration.
+  if (!ClassImpDecl) {
+    Diag(AtLoc, diag::error_missing_property_context);
+    return DeclPtrTy();
+  }
+  ObjCPropertyDecl *property = 0;
+  ObjCInterfaceDecl* IDecl = 0;
+  // Find the class or category class where this property must have
+  // a declaration.
+  ObjCImplementationDecl *IC = 0;
+  ObjCCategoryImplDecl* CatImplClass = 0;
+  if ((IC = dyn_cast<ObjCImplementationDecl>(ClassImpDecl))) {
+    IDecl = IC->getClassInterface();
+    // We always synthesize an interface for an implementation
+    // without an interface decl. So, IDecl is always non-zero.
+    assert(IDecl &&
+           "ActOnPropertyImplDecl - @implementation without @interface");
+
+    // Look for this property declaration in the @implementation's @interface
+    property = IDecl->FindPropertyDeclaration(PropertyId);
+    if (!property) {
+      Diag(PropertyLoc, diag::error_bad_property_decl) << IDecl->getDeclName();
+      return DeclPtrTy();
+    }
+    if (const ObjCCategoryDecl *CD = 
+        dyn_cast<ObjCCategoryDecl>(property->getDeclContext())) {
+      if (CD->getIdentifier()) {
+        Diag(PropertyLoc, diag::error_category_property) << CD->getDeclName();
+        Diag(property->getLocation(), diag::note_property_declare);
+        return DeclPtrTy();
+      }
+    }
+  } else if ((CatImplClass = dyn_cast<ObjCCategoryImplDecl>(ClassImpDecl))) {
+    if (Synthesize) {
+      Diag(AtLoc, diag::error_synthesize_category_decl);
+      return DeclPtrTy();
+    }
+    IDecl = CatImplClass->getClassInterface();
+    if (!IDecl) {
+      Diag(AtLoc, diag::error_missing_property_interface);
+      return DeclPtrTy();
+    }
+    ObjCCategoryDecl *Category =
+      IDecl->FindCategoryDeclaration(CatImplClass->getIdentifier());
+
+    // If category for this implementation not found, it is an error which
+    // has already been reported eralier.
+    if (!Category)
+      return DeclPtrTy();
+    // Look for this property declaration in @implementation's category
+    property = Category->FindPropertyDeclaration(PropertyId);
+    if (!property) {
+      Diag(PropertyLoc, diag::error_bad_category_property_decl)
+        << Category->getDeclName();
+      return DeclPtrTy();
+    }
+  } else {
+    Diag(AtLoc, diag::error_bad_property_context);
+    return DeclPtrTy();
+  }
+  ObjCIvarDecl *Ivar = 0;
+  // Check that we have a valid, previously declared ivar for @synthesize
+  if (Synthesize) {
+    // @synthesize
+    if (!PropertyIvar)
+      PropertyIvar = PropertyId;
+    QualType PropType = Context.getCanonicalType(property->getType());
+    // Check that this is a previously declared 'ivar' in 'IDecl' interface
+    ObjCInterfaceDecl *ClassDeclared;
+    Ivar = IDecl->lookupInstanceVariable(PropertyIvar, ClassDeclared);
+    if (!Ivar) {
+      DeclContext *EnclosingContext = cast_or_null<DeclContext>(IDecl);
+      assert(EnclosingContext &&
+             "null DeclContext for synthesized ivar - ActOnPropertyImplDecl");
+      Ivar = ObjCIvarDecl::Create(Context, EnclosingContext, PropertyLoc,
+                                  PropertyIvar, PropType, /*Dinfo=*/0,
+                                  ObjCIvarDecl::Public,
+                                  (Expr *)0);
+      Ivar->setLexicalDeclContext(IDecl);
+      IDecl->addDecl(Ivar);
+      property->setPropertyIvarDecl(Ivar);
+      if (!getLangOptions().ObjCNonFragileABI)
+        Diag(PropertyLoc, diag::error_missing_property_ivar_decl) << PropertyId;
+        // Note! I deliberately want it to fall thru so, we have a
+        // a property implementation and to avoid future warnings.
+    } else if (getLangOptions().ObjCNonFragileABI &&
+               ClassDeclared != IDecl) {
+      Diag(PropertyLoc, diag::error_ivar_in_superclass_use)
+        << property->getDeclName() << Ivar->getDeclName()
+        << ClassDeclared->getDeclName();
+      Diag(Ivar->getLocation(), diag::note_previous_access_declaration)
+        << Ivar << Ivar->getNameAsCString();
+      // Note! I deliberately want it to fall thru so more errors are caught.
+    }
+    QualType IvarType = Context.getCanonicalType(Ivar->getType());
+
+    // Check that type of property and its ivar are type compatible.
+    if (PropType != IvarType) {
+      if (CheckAssignmentConstraints(PropType, IvarType) != Compatible) {
+        Diag(PropertyLoc, diag::error_property_ivar_type)
+          << property->getDeclName() << Ivar->getDeclName();
+        // Note! I deliberately want it to fall thru so, we have a
+        // a property implementation and to avoid future warnings.
+      }
+
+      // FIXME! Rules for properties are somewhat different that those
+      // for assignments. Use a new routine to consolidate all cases;
+      // specifically for property redeclarations as well as for ivars.
+      QualType lhsType =Context.getCanonicalType(PropType).getUnqualifiedType();
+      QualType rhsType =Context.getCanonicalType(IvarType).getUnqualifiedType();
+      if (lhsType != rhsType &&
+          lhsType->isArithmeticType()) {
+        Diag(PropertyLoc, diag::error_property_ivar_type)
+        << property->getDeclName() << Ivar->getDeclName();
+        // Fall thru - see previous comment
+      }
+      // __weak is explicit. So it works on Canonical type.
+      if (PropType.isObjCGCWeak() && !IvarType.isObjCGCWeak() &&
+          getLangOptions().getGCMode() != LangOptions::NonGC) {
+        Diag(PropertyLoc, diag::error_weak_property)
+        << property->getDeclName() << Ivar->getDeclName();
+        // Fall thru - see previous comment
+      }
+      if ((property->getType()->isObjCObjectPointerType() ||
+           PropType.isObjCGCStrong()) && IvarType.isObjCGCWeak() &&
+           getLangOptions().getGCMode() != LangOptions::NonGC) {
+        Diag(PropertyLoc, diag::error_strong_property)
+        << property->getDeclName() << Ivar->getDeclName();
+        // Fall thru - see previous comment
+      }
+    }
+  } else if (PropertyIvar)
+      // @dynamic
+      Diag(PropertyLoc, diag::error_dynamic_property_ivar_decl);
+  assert (property && "ActOnPropertyImplDecl - property declaration missing");
+  ObjCPropertyImplDecl *PIDecl =
+    ObjCPropertyImplDecl::Create(Context, CurContext, AtLoc, PropertyLoc,
+                                 property,
+                                 (Synthesize ?
+                                  ObjCPropertyImplDecl::Synthesize
+                                  : ObjCPropertyImplDecl::Dynamic),
+                                 Ivar);
+  if (IC) {
+    if (Synthesize)
+      if (ObjCPropertyImplDecl *PPIDecl =
+          IC->FindPropertyImplIvarDecl(PropertyIvar)) {
+        Diag(PropertyLoc, diag::error_duplicate_ivar_use)
+          << PropertyId << PPIDecl->getPropertyDecl()->getIdentifier()
+          << PropertyIvar;
+        Diag(PPIDecl->getLocation(), diag::note_previous_use);
+      }
+
+    if (ObjCPropertyImplDecl *PPIDecl
+          = IC->FindPropertyImplDecl(PropertyId)) {
+      Diag(PropertyLoc, diag::error_property_implemented) << PropertyId;
+      Diag(PPIDecl->getLocation(), diag::note_previous_declaration);
+      return DeclPtrTy();
+    }
+    IC->addPropertyImplementation(PIDecl);
+  } else {
+    if (Synthesize)
+      if (ObjCPropertyImplDecl *PPIDecl =
+          CatImplClass->FindPropertyImplIvarDecl(PropertyIvar)) {
+        Diag(PropertyLoc, diag::error_duplicate_ivar_use)
+          << PropertyId << PPIDecl->getPropertyDecl()->getIdentifier()
+          << PropertyIvar;
+        Diag(PPIDecl->getLocation(), diag::note_previous_use);
+      }
+
+    if (ObjCPropertyImplDecl *PPIDecl =
+          CatImplClass->FindPropertyImplDecl(PropertyId)) {
+      Diag(PropertyLoc, diag::error_property_implemented) << PropertyId;
+      Diag(PPIDecl->getLocation(), diag::note_previous_declaration);
+      return DeclPtrTy();
+    }
+    CatImplClass->addPropertyImplementation(PIDecl);
+  }
+
+  return DeclPtrTy::make(PIDecl);
+}
+
+bool Sema::CheckObjCDeclScope(Decl *D) {
+  if (isa<TranslationUnitDecl>(CurContext->getLookupContext()))
+    return false;
+
+  Diag(D->getLocation(), diag::err_objc_decls_may_only_appear_in_global_scope);
+  D->setInvalidDecl();
+
+  return true;
+}
+
+/// Called whenever @defs(ClassName) is encountered in the source.  Inserts the
+/// instance variables of ClassName into Decls.
+void Sema::ActOnDefs(Scope *S, DeclPtrTy TagD, SourceLocation DeclStart,
+                     IdentifierInfo *ClassName,
+                     llvm::SmallVectorImpl<DeclPtrTy> &Decls) {
+  // Check that ClassName is a valid class
+  ObjCInterfaceDecl *Class = getObjCInterfaceDecl(ClassName);
+  if (!Class) {
+    Diag(DeclStart, diag::err_undef_interface) << ClassName;
+    return;
+  }
+  if (LangOpts.ObjCNonFragileABI) {
+    Diag(DeclStart, diag::err_atdef_nonfragile_interface);
+    return;
+  }
+
+  // Collect the instance variables
+  llvm::SmallVector<FieldDecl*, 32> RecFields;
+  Context.CollectObjCIvars(Class, RecFields);
+  // For each ivar, create a fresh ObjCAtDefsFieldDecl.
+  for (unsigned i = 0; i < RecFields.size(); i++) {
+    FieldDecl* ID = RecFields[i];
+    RecordDecl *Record = dyn_cast<RecordDecl>(TagD.getAs<Decl>());
+    Decl *FD = ObjCAtDefsFieldDecl::Create(Context, Record, ID->getLocation(),
+                                           ID->getIdentifier(), ID->getType(),
+                                           ID->getBitWidth());
+    Decls.push_back(Sema::DeclPtrTy::make(FD));
+  }
+
+  // Introduce all of these fields into the appropriate scope.
+  for (llvm::SmallVectorImpl<DeclPtrTy>::iterator D = Decls.begin();
+       D != Decls.end(); ++D) {
+    FieldDecl *FD = cast<FieldDecl>(D->getAs<Decl>());
+    if (getLangOptions().CPlusPlus)
+      PushOnScopeChains(cast<FieldDecl>(FD), S);
+    else if (RecordDecl *Record = dyn_cast<RecordDecl>(TagD.getAs<Decl>()))
+      Record->addDecl(FD);
+  }
+}
+
diff --git a/lib/Sema/SemaExceptionSpec.cpp b/lib/Sema/SemaExceptionSpec.cpp
new file mode 100644
index 0000000..d0718d0
--- /dev/null
+++ b/lib/Sema/SemaExceptionSpec.cpp
@@ -0,0 +1,343 @@
+//===--- SemaExceptionSpec.cpp - C++ Exception Specifications ---*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file provides Sema routines for C++ exception specification testing.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Sema.h"
+#include "clang/Basic/Diagnostic.h"
+#include "clang/AST/CXXInheritance.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/ExprCXX.h"
+#include "llvm/ADT/SmallPtrSet.h"
+
+namespace clang {
+
+static const FunctionProtoType *GetUnderlyingFunction(QualType T)
+{
+  if (const PointerType *PtrTy = T->getAs<PointerType>())
+    T = PtrTy->getPointeeType();
+  else if (const ReferenceType *RefTy = T->getAs<ReferenceType>())
+    T = RefTy->getPointeeType();
+  else if (const MemberPointerType *MPTy = T->getAs<MemberPointerType>())
+    T = MPTy->getPointeeType();
+  return T->getAs<FunctionProtoType>();
+}
+
+/// CheckSpecifiedExceptionType - Check if the given type is valid in an
+/// exception specification. Incomplete types, or pointers to incomplete types
+/// other than void are not allowed.
+bool Sema::CheckSpecifiedExceptionType(QualType T, const SourceRange &Range) {
+
+  // This check (and the similar one below) deals with issue 437, that changes
+  // C++ 9.2p2 this way:
+  // Within the class member-specification, the class is regarded as complete
+  // within function bodies, default arguments, exception-specifications, and
+  // constructor ctor-initializers (including such things in nested classes).
+  if (T->isRecordType() && T->getAs<RecordType>()->isBeingDefined())
+    return false;
+    
+  // C++ 15.4p2: A type denoted in an exception-specification shall not denote
+  //   an incomplete type.
+  if (RequireCompleteType(Range.getBegin(), T,
+      PDiag(diag::err_incomplete_in_exception_spec) << /*direct*/0 << Range))
+    return true;
+
+  // C++ 15.4p2: A type denoted in an exception-specification shall not denote
+  //   an incomplete type a pointer or reference to an incomplete type, other
+  //   than (cv) void*.
+  int kind;
+  if (const PointerType* IT = T->getAs<PointerType>()) {
+    T = IT->getPointeeType();
+    kind = 1;
+  } else if (const ReferenceType* IT = T->getAs<ReferenceType>()) {
+    T = IT->getPointeeType();
+    kind = 2;
+  } else
+    return false;
+
+  // Again as before
+  if (T->isRecordType() && T->getAs<RecordType>()->isBeingDefined())
+    return false;
+    
+  if (!T->isVoidType() && RequireCompleteType(Range.getBegin(), T,
+      PDiag(diag::err_incomplete_in_exception_spec) << kind << Range))
+    return true;
+
+  return false;
+}
+
+/// CheckDistantExceptionSpec - Check if the given type is a pointer or pointer
+/// to member to a function with an exception specification. This means that
+/// it is invalid to add another level of indirection.
+bool Sema::CheckDistantExceptionSpec(QualType T) {
+  if (const PointerType *PT = T->getAs<PointerType>())
+    T = PT->getPointeeType();
+  else if (const MemberPointerType *PT = T->getAs<MemberPointerType>())
+    T = PT->getPointeeType();
+  else
+    return false;
+
+  const FunctionProtoType *FnT = T->getAs<FunctionProtoType>();
+  if (!FnT)
+    return false;
+
+  return FnT->hasExceptionSpec();
+}
+
+/// CheckEquivalentExceptionSpec - Check if the two types have equivalent
+/// exception specifications. Exception specifications are equivalent if
+/// they allow exactly the same set of exception types. It does not matter how
+/// that is achieved. See C++ [except.spec]p2.
+bool Sema::CheckEquivalentExceptionSpec(
+    const FunctionProtoType *Old, SourceLocation OldLoc,
+    const FunctionProtoType *New, SourceLocation NewLoc) {
+  return CheckEquivalentExceptionSpec(diag::err_mismatched_exception_spec,
+                                      diag::note_previous_declaration,
+                                      Old, OldLoc, New, NewLoc);
+}
+
+/// CheckEquivalentExceptionSpec - Check if the two types have equivalent
+/// exception specifications. Exception specifications are equivalent if
+/// they allow exactly the same set of exception types. It does not matter how
+/// that is achieved. See C++ [except.spec]p2.
+bool Sema::CheckEquivalentExceptionSpec(
+    const PartialDiagnostic &DiagID, const PartialDiagnostic & NoteID,
+    const FunctionProtoType *Old, SourceLocation OldLoc,
+    const FunctionProtoType *New, SourceLocation NewLoc) {
+  bool OldAny = !Old->hasExceptionSpec() || Old->hasAnyExceptionSpec();
+  bool NewAny = !New->hasExceptionSpec() || New->hasAnyExceptionSpec();
+  if (OldAny && NewAny)
+    return false;
+  if (OldAny || NewAny) {
+    Diag(NewLoc, DiagID);
+    if (NoteID.getDiagID() != 0)
+      Diag(OldLoc, NoteID);
+    return true;
+  }
+
+  bool Success = true;
+  // Both have a definite exception spec. Collect the first set, then compare
+  // to the second.
+  llvm::SmallPtrSet<CanQualType, 8> OldTypes, NewTypes;
+  for (FunctionProtoType::exception_iterator I = Old->exception_begin(),
+       E = Old->exception_end(); I != E; ++I)
+    OldTypes.insert(Context.getCanonicalType(*I).getUnqualifiedType());
+
+  for (FunctionProtoType::exception_iterator I = New->exception_begin(),
+       E = New->exception_end(); I != E && Success; ++I) {
+    CanQualType TypePtr = Context.getCanonicalType(*I).getUnqualifiedType();
+    if(OldTypes.count(TypePtr))
+      NewTypes.insert(TypePtr);
+    else
+      Success = false;
+  }
+
+  Success = Success && OldTypes.size() == NewTypes.size();
+
+  if (Success) {
+    return false;
+  }
+  Diag(NewLoc, DiagID);
+  if (NoteID.getDiagID() != 0)
+    Diag(OldLoc, NoteID);
+  return true;
+}
+
+/// CheckExceptionSpecSubset - Check whether the second function type's
+/// exception specification is a subset (or equivalent) of the first function
+/// type. This is used by override and pointer assignment checks.
+bool Sema::CheckExceptionSpecSubset(
+    const PartialDiagnostic &DiagID, const PartialDiagnostic & NoteID,
+    const FunctionProtoType *Superset, SourceLocation SuperLoc,
+    const FunctionProtoType *Subset, SourceLocation SubLoc) {
+  // FIXME: As usual, we could be more specific in our error messages, but
+  // that better waits until we've got types with source locations.
+
+  if (!SubLoc.isValid())
+    SubLoc = SuperLoc;
+
+  // If superset contains everything, we're done.
+  if (!Superset->hasExceptionSpec() || Superset->hasAnyExceptionSpec())
+    return CheckParamExceptionSpec(NoteID, Superset, SuperLoc, Subset, SubLoc);
+
+  // It does not. If the subset contains everything, we've failed.
+  if (!Subset->hasExceptionSpec() || Subset->hasAnyExceptionSpec()) {
+    Diag(SubLoc, DiagID);
+    if (NoteID.getDiagID() != 0)
+      Diag(SuperLoc, NoteID);
+    return true;
+  }
+
+  // Neither contains everything. Do a proper comparison.
+  for (FunctionProtoType::exception_iterator SubI = Subset->exception_begin(),
+       SubE = Subset->exception_end(); SubI != SubE; ++SubI) {
+    // Take one type from the subset.
+    QualType CanonicalSubT = Context.getCanonicalType(*SubI);
+    // Unwrap pointers and references so that we can do checks within a class
+    // hierarchy. Don't unwrap member pointers; they don't have hierarchy
+    // conversions on the pointee.
+    bool SubIsPointer = false;
+    if (const ReferenceType *RefTy = CanonicalSubT->getAs<ReferenceType>())
+      CanonicalSubT = RefTy->getPointeeType();
+    if (const PointerType *PtrTy = CanonicalSubT->getAs<PointerType>()) {
+      CanonicalSubT = PtrTy->getPointeeType();
+      SubIsPointer = true;
+    }
+    bool SubIsClass = CanonicalSubT->isRecordType();
+    CanonicalSubT = CanonicalSubT.getLocalUnqualifiedType();
+
+    CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
+                       /*DetectVirtual=*/false);
+
+    bool Contained = false;
+    // Make sure it's in the superset.
+    for (FunctionProtoType::exception_iterator SuperI =
+           Superset->exception_begin(), SuperE = Superset->exception_end();
+         SuperI != SuperE; ++SuperI) {
+      QualType CanonicalSuperT = Context.getCanonicalType(*SuperI);
+      // SubT must be SuperT or derived from it, or pointer or reference to
+      // such types.
+      if (const ReferenceType *RefTy = CanonicalSuperT->getAs<ReferenceType>())
+        CanonicalSuperT = RefTy->getPointeeType();
+      if (SubIsPointer) {
+        if (const PointerType *PtrTy = CanonicalSuperT->getAs<PointerType>())
+          CanonicalSuperT = PtrTy->getPointeeType();
+        else {
+          continue;
+        }
+      }
+      CanonicalSuperT = CanonicalSuperT.getLocalUnqualifiedType();
+      // If the types are the same, move on to the next type in the subset.
+      if (CanonicalSubT == CanonicalSuperT) {
+        Contained = true;
+        break;
+      }
+
+      // Otherwise we need to check the inheritance.
+      if (!SubIsClass || !CanonicalSuperT->isRecordType())
+        continue;
+
+      Paths.clear();
+      if (!IsDerivedFrom(CanonicalSubT, CanonicalSuperT, Paths))
+        continue;
+
+      if (Paths.isAmbiguous(CanonicalSuperT))
+        continue;
+
+      // Do this check from a context without privileges.
+      switch (CheckBaseClassAccess(SourceLocation(), false,
+                                   CanonicalSuperT, CanonicalSubT,
+                                   Paths.front(),
+                                   /*ForceCheck*/ true,
+                                   /*ForceUnprivileged*/ true,
+                                   ADK_quiet)) {
+      case AR_accessible: break;
+      case AR_inaccessible: continue;
+      case AR_dependent:
+        llvm_unreachable("access check dependent for unprivileged context");
+        break;
+      case AR_delayed:
+        llvm_unreachable("access check delayed in non-declaration");
+        break;
+      }
+
+      Contained = true;
+      break;
+    }
+    if (!Contained) {
+      Diag(SubLoc, DiagID);
+      if (NoteID.getDiagID() != 0)
+        Diag(SuperLoc, NoteID);
+      return true;
+    }
+  }
+  // We've run half the gauntlet.
+  return CheckParamExceptionSpec(NoteID, Superset, SuperLoc, Subset, SubLoc);
+}
+
+static bool CheckSpecForTypesEquivalent(Sema &S,
+    const PartialDiagnostic &DiagID, const PartialDiagnostic & NoteID,
+    QualType Target, SourceLocation TargetLoc,
+    QualType Source, SourceLocation SourceLoc)
+{
+  const FunctionProtoType *TFunc = GetUnderlyingFunction(Target);
+  if (!TFunc)
+    return false;
+  const FunctionProtoType *SFunc = GetUnderlyingFunction(Source);
+  if (!SFunc)
+    return false;
+
+  return S.CheckEquivalentExceptionSpec(DiagID, NoteID, TFunc, TargetLoc,
+                                        SFunc, SourceLoc);
+}
+
+/// CheckParamExceptionSpec - Check if the parameter and return types of the
+/// two functions have equivalent exception specs. This is part of the
+/// assignment and override compatibility check. We do not check the parameters
+/// of parameter function pointers recursively, as no sane programmer would
+/// even be able to write such a function type.
+bool Sema::CheckParamExceptionSpec(const PartialDiagnostic & NoteID,
+    const FunctionProtoType *Target, SourceLocation TargetLoc,
+    const FunctionProtoType *Source, SourceLocation SourceLoc)
+{
+  if (CheckSpecForTypesEquivalent(*this,
+                           PDiag(diag::err_deep_exception_specs_differ) << 0, 0,
+                                  Target->getResultType(), TargetLoc,
+                                  Source->getResultType(), SourceLoc))
+    return true;
+
+  // We shouldn't even be testing this unless the arguments are otherwise
+  // compatible.
+  assert(Target->getNumArgs() == Source->getNumArgs() &&
+         "Functions have different argument counts.");
+  for (unsigned i = 0, E = Target->getNumArgs(); i != E; ++i) {
+    if (CheckSpecForTypesEquivalent(*this,
+                           PDiag(diag::err_deep_exception_specs_differ) << 1, 0,
+                                    Target->getArgType(i), TargetLoc,
+                                    Source->getArgType(i), SourceLoc))
+      return true;
+  }
+  return false;
+}
+
+bool Sema::CheckExceptionSpecCompatibility(Expr *From, QualType ToType)
+{
+  // First we check for applicability.
+  // Target type must be a function, function pointer or function reference.
+  const FunctionProtoType *ToFunc = GetUnderlyingFunction(ToType);
+  if (!ToFunc)
+    return false;
+
+  // SourceType must be a function or function pointer.
+  const FunctionProtoType *FromFunc = GetUnderlyingFunction(From->getType());
+  if (!FromFunc)
+    return false;
+
+  // Now we've got the correct types on both sides, check their compatibility.
+  // This means that the source of the conversion can only throw a subset of
+  // the exceptions of the target, and any exception specs on arguments or
+  // return types must be equivalent.
+  return CheckExceptionSpecSubset(diag::err_incompatible_exception_specs,
+                                  0, ToFunc, From->getSourceRange().getBegin(),
+                                  FromFunc, SourceLocation());
+}
+
+bool Sema::CheckOverridingFunctionExceptionSpec(const CXXMethodDecl *New,
+                                                const CXXMethodDecl *Old) {
+  return CheckExceptionSpecSubset(diag::err_override_exception_spec,
+                                  diag::note_overridden_virtual_function,
+                                  Old->getType()->getAs<FunctionProtoType>(),
+                                  Old->getLocation(),
+                                  New->getType()->getAs<FunctionProtoType>(),
+                                  New->getLocation());
+}
+
+} // end namespace clang
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
new file mode 100644
index 0000000..0442163
--- /dev/null
+++ b/lib/Sema/SemaExpr.cpp
@@ -0,0 +1,7444 @@
+//===--- SemaExpr.cpp - Semantic Analysis for Expressions -----------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+//  This file implements semantic analysis for expressions.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Sema.h"
+#include "SemaInit.h"
+#include "Lookup.h"
+#include "clang/Analysis/AnalysisContext.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/AST/DeclTemplate.h"
+#include "clang/AST/ExprCXX.h"
+#include "clang/AST/ExprObjC.h"
+#include "clang/Basic/PartialDiagnostic.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Basic/TargetInfo.h"
+#include "clang/Lex/LiteralSupport.h"
+#include "clang/Lex/Preprocessor.h"
+#include "clang/Parse/DeclSpec.h"
+#include "clang/Parse/Designator.h"
+#include "clang/Parse/Scope.h"
+#include "clang/Parse/Template.h"
+using namespace clang;
+
+
+/// \brief Determine whether the use of this declaration is valid, and
+/// emit any corresponding diagnostics.
+///
+/// This routine diagnoses various problems with referencing
+/// declarations that can occur when using a declaration. For example,
+/// it might warn if a deprecated or unavailable declaration is being
+/// used, or produce an error (and return true) if a C++0x deleted
+/// function is being used.
+///
+/// If IgnoreDeprecated is set to true, this should not want about deprecated
+/// decls.
+///
+/// \returns true if there was an error (this declaration cannot be
+/// referenced), false otherwise.
+///
+bool Sema::DiagnoseUseOfDecl(NamedDecl *D, SourceLocation Loc) {
+  // See if the decl is deprecated.
+  if (D->getAttr<DeprecatedAttr>()) {
+    EmitDeprecationWarning(D, Loc);
+  }
+
+  // See if the decl is unavailable
+  if (D->getAttr<UnavailableAttr>()) {
+    Diag(Loc, diag::warn_unavailable) << D->getDeclName();
+    Diag(D->getLocation(), diag::note_unavailable_here) << 0;
+  }
+  
+  // See if this is a deleted function.
+  if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
+    if (FD->isDeleted()) {
+      Diag(Loc, diag::err_deleted_function_use);
+      Diag(D->getLocation(), diag::note_unavailable_here) << true;
+      return true;
+    }
+  }
+
+  return false;
+}
+
+/// DiagnoseSentinelCalls - This routine checks on method dispatch calls
+/// (and other functions in future), which have been declared with sentinel
+/// attribute. It warns if call does not have the sentinel argument.
+///
+void Sema::DiagnoseSentinelCalls(NamedDecl *D, SourceLocation Loc,
+                                 Expr **Args, unsigned NumArgs) {
+  const SentinelAttr *attr = D->getAttr<SentinelAttr>();
+  if (!attr)
+    return;
+  int sentinelPos = attr->getSentinel();
+  int nullPos = attr->getNullPos();
+
+  // FIXME. ObjCMethodDecl and FunctionDecl need be derived from the same common
+  // base class. Then we won't be needing two versions of the same code.
+  unsigned int i = 0;
+  bool warnNotEnoughArgs = false;
+  int isMethod = 0;
+  if (ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) {
+    // skip over named parameters.
+    ObjCMethodDecl::param_iterator P, E = MD->param_end();
+    for (P = MD->param_begin(); (P != E && i < NumArgs); ++P) {
+      if (nullPos)
+        --nullPos;
+      else
+        ++i;
+    }
+    warnNotEnoughArgs = (P != E || i >= NumArgs);
+    isMethod = 1;
+  } else if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
+    // skip over named parameters.
+    ObjCMethodDecl::param_iterator P, E = FD->param_end();
+    for (P = FD->param_begin(); (P != E && i < NumArgs); ++P) {
+      if (nullPos)
+        --nullPos;
+      else
+        ++i;
+    }
+    warnNotEnoughArgs = (P != E || i >= NumArgs);
+  } else if (VarDecl *V = dyn_cast<VarDecl>(D)) {
+    // block or function pointer call.
+    QualType Ty = V->getType();
+    if (Ty->isBlockPointerType() || Ty->isFunctionPointerType()) {
+      const FunctionType *FT = Ty->isFunctionPointerType()
+      ? Ty->getAs<PointerType>()->getPointeeType()->getAs<FunctionType>()
+      : Ty->getAs<BlockPointerType>()->getPointeeType()->getAs<FunctionType>();
+      if (const FunctionProtoType *Proto = dyn_cast<FunctionProtoType>(FT)) {
+        unsigned NumArgsInProto = Proto->getNumArgs();
+        unsigned k;
+        for (k = 0; (k != NumArgsInProto && i < NumArgs); k++) {
+          if (nullPos)
+            --nullPos;
+          else
+            ++i;
+        }
+        warnNotEnoughArgs = (k != NumArgsInProto || i >= NumArgs);
+      }
+      if (Ty->isBlockPointerType())
+        isMethod = 2;
+    } else
+      return;
+  } else
+    return;
+
+  if (warnNotEnoughArgs) {
+    Diag(Loc, diag::warn_not_enough_argument) << D->getDeclName();
+    Diag(D->getLocation(), diag::note_sentinel_here) << isMethod;
+    return;
+  }
+  int sentinel = i;
+  while (sentinelPos > 0 && i < NumArgs-1) {
+    --sentinelPos;
+    ++i;
+  }
+  if (sentinelPos > 0) {
+    Diag(Loc, diag::warn_not_enough_argument) << D->getDeclName();
+    Diag(D->getLocation(), diag::note_sentinel_here) << isMethod;
+    return;
+  }
+  while (i < NumArgs-1) {
+    ++i;
+    ++sentinel;
+  }
+  Expr *sentinelExpr = Args[sentinel];
+  if (sentinelExpr && (!isa<GNUNullExpr>(sentinelExpr) &&
+                       (!sentinelExpr->getType()->isPointerType() ||
+                        !sentinelExpr->isNullPointerConstant(Context,
+                                            Expr::NPC_ValueDependentIsNull)))) {
+    Diag(Loc, diag::warn_missing_sentinel) << isMethod;
+    Diag(D->getLocation(), diag::note_sentinel_here) << isMethod;
+  }
+  return;
+}
+
+SourceRange Sema::getExprRange(ExprTy *E) const {
+  Expr *Ex = (Expr *)E;
+  return Ex? Ex->getSourceRange() : SourceRange();
+}
+
+//===----------------------------------------------------------------------===//
+//  Standard Promotions and Conversions
+//===----------------------------------------------------------------------===//
+
+/// DefaultFunctionArrayConversion (C99 6.3.2.1p3, C99 6.3.2.1p4).
+void Sema::DefaultFunctionArrayConversion(Expr *&E) {
+  QualType Ty = E->getType();
+  assert(!Ty.isNull() && "DefaultFunctionArrayConversion - missing type");
+
+  if (Ty->isFunctionType())
+    ImpCastExprToType(E, Context.getPointerType(Ty),
+                      CastExpr::CK_FunctionToPointerDecay);
+  else if (Ty->isArrayType()) {
+    // In C90 mode, arrays only promote to pointers if the array expression is
+    // an lvalue.  The relevant legalese is C90 6.2.2.1p3: "an lvalue that has
+    // type 'array of type' is converted to an expression that has type 'pointer
+    // to type'...".  In C99 this was changed to: C99 6.3.2.1p3: "an expression
+    // that has type 'array of type' ...".  The relevant change is "an lvalue"
+    // (C90) to "an expression" (C99).
+    //
+    // C++ 4.2p1:
+    // An lvalue or rvalue of type "array of N T" or "array of unknown bound of
+    // T" can be converted to an rvalue of type "pointer to T".
+    //
+    if (getLangOptions().C99 || getLangOptions().CPlusPlus ||
+        E->isLvalue(Context) == Expr::LV_Valid)
+      ImpCastExprToType(E, Context.getArrayDecayedType(Ty),
+                        CastExpr::CK_ArrayToPointerDecay);
+  }
+}
+
+void Sema::DefaultFunctionArrayLvalueConversion(Expr *&E) {
+  DefaultFunctionArrayConversion(E);
+  
+  QualType Ty = E->getType();
+  assert(!Ty.isNull() && "DefaultFunctionArrayLvalueConversion - missing type");
+  if (!Ty->isDependentType() && Ty.hasQualifiers() &&
+      (!getLangOptions().CPlusPlus || !Ty->isRecordType()) &&
+      E->isLvalue(Context) == Expr::LV_Valid) {
+    // C++ [conv.lval]p1:
+    //   [...] If T is a non-class type, the type of the rvalue is the
+    //   cv-unqualified version of T. Otherwise, the type of the
+    //   rvalue is T
+    //
+    // C99 6.3.2.1p2:
+    //   If the lvalue has qualified type, the value has the unqualified 
+    //   version of the type of the lvalue; otherwise, the value has the 
+    //   type of the lvalue.
+    ImpCastExprToType(E, Ty.getUnqualifiedType(), CastExpr::CK_NoOp);
+  }
+}
+
+
+/// UsualUnaryConversions - 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.
+Expr *Sema::UsualUnaryConversions(Expr *&Expr) {
+  QualType Ty = Expr->getType();
+  assert(!Ty.isNull() && "UsualUnaryConversions - missing type");
+
+  // C99 6.3.1.1p2:
+  //
+  //   The following may be used in an expression wherever an int or
+  //   unsigned int may be used:
+  //     - an object or expression with an integer type whose integer
+  //       conversion rank is less than or equal to the rank of int
+  //       and unsigned int.
+  //     - A bit-field of type _Bool, int, signed int, or unsigned int.
+  //
+  //   If an int can represent all values of the original type, the
+  //   value is converted to an int; otherwise, it is converted to an
+  //   unsigned int. These are called the integer promotions. All
+  //   other types are unchanged by the integer promotions.
+  QualType PTy = Context.isPromotableBitField(Expr);
+  if (!PTy.isNull()) {
+    ImpCastExprToType(Expr, PTy, CastExpr::CK_IntegralCast);
+    return Expr;
+  }
+  if (Ty->isPromotableIntegerType()) {
+    QualType PT = Context.getPromotedIntegerType(Ty);
+    ImpCastExprToType(Expr, PT, CastExpr::CK_IntegralCast);
+    return Expr;
+  }
+
+  DefaultFunctionArrayLvalueConversion(Expr);
+  return Expr;
+}
+
+/// DefaultArgumentPromotion (C99 6.5.2.2p6). Used for function calls that
+/// do not have a prototype. Arguments that have type float are promoted to
+/// double. All other argument types are converted by UsualUnaryConversions().
+void Sema::DefaultArgumentPromotion(Expr *&Expr) {
+  QualType Ty = Expr->getType();
+  assert(!Ty.isNull() && "DefaultArgumentPromotion - missing type");
+
+  // If this is a 'float' (CVR qualified or typedef) promote to double.
+  if (const BuiltinType *BT = Ty->getAs<BuiltinType>())
+    if (BT->getKind() == BuiltinType::Float)
+      return ImpCastExprToType(Expr, Context.DoubleTy,
+                               CastExpr::CK_FloatingCast);
+
+  UsualUnaryConversions(Expr);
+}
+
+/// DefaultVariadicArgumentPromotion - Like DefaultArgumentPromotion, but
+/// will warn if the resulting type is not a POD type, and rejects ObjC
+/// interfaces passed by value.  This returns true if the argument type is
+/// completely illegal.
+bool Sema::DefaultVariadicArgumentPromotion(Expr *&Expr, VariadicCallType CT) {
+  DefaultArgumentPromotion(Expr);
+
+  if (Expr->getType()->isObjCInterfaceType() &&
+      DiagRuntimeBehavior(Expr->getLocStart(),
+        PDiag(diag::err_cannot_pass_objc_interface_to_vararg)
+          << Expr->getType() << CT))
+    return true;
+
+  if (!Expr->getType()->isPODType() &&
+      DiagRuntimeBehavior(Expr->getLocStart(), 
+                          PDiag(diag::warn_cannot_pass_non_pod_arg_to_vararg)
+                            << Expr->getType() << CT))
+    return true;
+
+  return false;
+}
+
+
+/// 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.
+/// FIXME: verify the conversion rules for "complex int" are consistent with
+/// GCC.
+QualType Sema::UsualArithmeticConversions(Expr *&lhsExpr, Expr *&rhsExpr,
+                                          bool isCompAssign) {
+  if (!isCompAssign)
+    UsualUnaryConversions(lhsExpr);
+
+  UsualUnaryConversions(rhsExpr);
+
+  // For conversion purposes, we ignore any qualifiers.
+  // For example, "const float" and "float" are equivalent.
+  QualType lhs =
+    Context.getCanonicalType(lhsExpr->getType()).getUnqualifiedType();
+  QualType rhs =
+    Context.getCanonicalType(rhsExpr->getType()).getUnqualifiedType();
+
+  // 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() || !rhs->isArithmeticType())
+    return lhs;
+
+  // Perform bitfield promotions.
+  QualType LHSBitfieldPromoteTy = Context.isPromotableBitField(lhsExpr);
+  if (!LHSBitfieldPromoteTy.isNull())
+    lhs = LHSBitfieldPromoteTy;
+  QualType RHSBitfieldPromoteTy = Context.isPromotableBitField(rhsExpr);
+  if (!RHSBitfieldPromoteTy.isNull())
+    rhs = RHSBitfieldPromoteTy;
+
+  QualType destType = Context.UsualArithmeticConversionsType(lhs, rhs);
+  if (!isCompAssign)
+    ImpCastExprToType(lhsExpr, destType, CastExpr::CK_Unknown);
+  ImpCastExprToType(rhsExpr, destType, CastExpr::CK_Unknown);
+  return destType;
+}
+
+//===----------------------------------------------------------------------===//
+//  Semantic Analysis for various Expression Types
+//===----------------------------------------------------------------------===//
+
+
+/// ActOnStringLiteral - 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::OwningExprResult
+Sema::ActOnStringLiteral(const Token *StringToks, unsigned NumStringToks) {
+  assert(NumStringToks && "Must have at least one string!");
+
+  StringLiteralParser Literal(StringToks, NumStringToks, PP);
+  if (Literal.hadError)
+    return ExprError();
+
+  llvm::SmallVector<SourceLocation, 4> StringTokLocs;
+  for (unsigned i = 0; i != NumStringToks; ++i)
+    StringTokLocs.push_back(StringToks[i].getLocation());
+
+  QualType StrTy = Context.CharTy;
+  if (Literal.AnyWide) StrTy = Context.getWCharType();
+  if (Literal.Pascal) StrTy = Context.UnsignedCharTy;
+
+  // A C++ string literal has a const-qualified element type (C++ 2.13.4p1).
+  if (getLangOptions().CPlusPlus)
+    StrTy.addConst();
+
+  // Get an array type for the string, according to C99 6.4.5.  This includes
+  // the nul terminator character as well as the string length for pascal
+  // strings.
+  StrTy = Context.getConstantArrayType(StrTy,
+                                 llvm::APInt(32, Literal.GetNumStringChars()+1),
+                                       ArrayType::Normal, 0);
+
+  // Pass &StringTokLocs[0], StringTokLocs.size() to factory!
+  return Owned(StringLiteral::Create(Context, Literal.GetString(),
+                                     Literal.GetStringLength(),
+                                     Literal.AnyWide, StrTy,
+                                     &StringTokLocs[0],
+                                     StringTokLocs.size()));
+}
+
+/// ShouldSnapshotBlockValueReference - Return true if a reference inside of
+/// CurBlock to VD should cause it to be snapshotted (as we do for auto
+/// variables defined outside the block) or false if this is not needed (e.g.
+/// for values inside the block or for globals).
+///
+/// This also keeps the 'hasBlockDeclRefExprs' in the BlockSemaInfo records
+/// up-to-date.
+///
+static bool ShouldSnapshotBlockValueReference(BlockSemaInfo *CurBlock,
+                                              ValueDecl *VD) {
+  // If the value is defined inside the block, we couldn't snapshot it even if
+  // we wanted to.
+  if (CurBlock->TheDecl == VD->getDeclContext())
+    return false;
+
+  // If this is an enum constant or function, it is constant, don't snapshot.
+  if (isa<EnumConstantDecl>(VD) || isa<FunctionDecl>(VD))
+    return false;
+
+  // If this is a reference to an extern, static, or global variable, no need to
+  // snapshot it.
+  // FIXME: What about 'const' variables in C++?
+  if (const VarDecl *Var = dyn_cast<VarDecl>(VD))
+    if (!Var->hasLocalStorage())
+      return false;
+
+  // Blocks that have these can't be constant.
+  CurBlock->hasBlockDeclRefExprs = true;
+
+  // If we have nested blocks, the decl may be declared in an outer block (in
+  // which case that outer block doesn't get "hasBlockDeclRefExprs") or it may
+  // be defined outside all of the current blocks (in which case the blocks do
+  // all get the bit).  Walk the nesting chain.
+  for (BlockSemaInfo *NextBlock = CurBlock->PrevBlockInfo; NextBlock;
+       NextBlock = NextBlock->PrevBlockInfo) {
+    // If we found the defining block for the variable, don't mark the block as
+    // having a reference outside it.
+    if (NextBlock->TheDecl == VD->getDeclContext())
+      break;
+
+    // Otherwise, the DeclRef from the inner block causes the outer one to need
+    // a snapshot as well.
+    NextBlock->hasBlockDeclRefExprs = true;
+  }
+
+  return true;
+}
+
+
+
+/// BuildDeclRefExpr - Build a DeclRefExpr.
+Sema::OwningExprResult
+Sema::BuildDeclRefExpr(ValueDecl *D, QualType Ty, SourceLocation Loc,
+                       const CXXScopeSpec *SS) {
+  if (Context.getCanonicalType(Ty) == Context.UndeducedAutoTy) {
+    Diag(Loc,
+         diag::err_auto_variable_cannot_appear_in_own_initializer)
+      << D->getDeclName();
+    return ExprError();
+  }
+
+  if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
+    if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(CurContext)) {
+      if (const FunctionDecl *FD = MD->getParent()->isLocalClass()) {
+        if (VD->hasLocalStorage() && VD->getDeclContext() != CurContext) {
+          Diag(Loc, diag::err_reference_to_local_var_in_enclosing_function)
+            << D->getIdentifier() << FD->getDeclName();
+          Diag(D->getLocation(), diag::note_local_variable_declared_here)
+            << D->getIdentifier();
+          return ExprError();
+        }
+      }
+    }
+  }
+
+  MarkDeclarationReferenced(Loc, D);
+
+  return Owned(DeclRefExpr::Create(Context, 
+                              SS? (NestedNameSpecifier *)SS->getScopeRep() : 0, 
+                                   SS? SS->getRange() : SourceRange(), 
+                                   D, Loc, Ty));
+}
+
+/// getObjectForAnonymousRecordDecl - Retrieve the (unnamed) field or
+/// variable corresponding to the anonymous union or struct whose type
+/// is Record.
+static Decl *getObjectForAnonymousRecordDecl(ASTContext &Context,
+                                             RecordDecl *Record) {
+  assert(Record->isAnonymousStructOrUnion() &&
+         "Record must be an anonymous struct or union!");
+
+  // FIXME: Once Decls are directly linked together, this will be an O(1)
+  // operation rather than a slow walk through DeclContext's vector (which
+  // itself will be eliminated). DeclGroups might make this even better.
+  DeclContext *Ctx = Record->getDeclContext();
+  for (DeclContext::decl_iterator D = Ctx->decls_begin(),
+                               DEnd = Ctx->decls_end();
+       D != DEnd; ++D) {
+    if (*D == Record) {
+      // The object for the anonymous struct/union directly
+      // follows its type in the list of declarations.
+      ++D;
+      assert(D != DEnd && "Missing object for anonymous record");
+      assert(!cast<NamedDecl>(*D)->getDeclName() && "Decl should be unnamed");
+      return *D;
+    }
+  }
+
+  assert(false && "Missing object for anonymous record");
+  return 0;
+}
+
+/// \brief Given a field that represents a member of an anonymous
+/// struct/union, build the path from that field's context to the
+/// actual member.
+///
+/// Construct the sequence of field member references we'll have to
+/// perform to get to the field in the anonymous union/struct. The
+/// list of members is built from the field outward, so traverse it
+/// backwards to go from an object in the current context to the field
+/// we found.
+///
+/// \returns The variable from which the field access should begin,
+/// for an anonymous struct/union that is not a member of another
+/// class. Otherwise, returns NULL.
+VarDecl *Sema::BuildAnonymousStructUnionMemberPath(FieldDecl *Field,
+                                   llvm::SmallVectorImpl<FieldDecl *> &Path) {
+  assert(Field->getDeclContext()->isRecord() &&
+         cast<RecordDecl>(Field->getDeclContext())->isAnonymousStructOrUnion()
+         && "Field must be stored inside an anonymous struct or union");
+
+  Path.push_back(Field);
+  VarDecl *BaseObject = 0;
+  DeclContext *Ctx = Field->getDeclContext();
+  do {
+    RecordDecl *Record = cast<RecordDecl>(Ctx);
+    Decl *AnonObject = getObjectForAnonymousRecordDecl(Context, Record);
+    if (FieldDecl *AnonField = dyn_cast<FieldDecl>(AnonObject))
+      Path.push_back(AnonField);
+    else {
+      BaseObject = cast<VarDecl>(AnonObject);
+      break;
+    }
+    Ctx = Ctx->getParent();
+  } while (Ctx->isRecord() &&
+           cast<RecordDecl>(Ctx)->isAnonymousStructOrUnion());
+
+  return BaseObject;
+}
+
+Sema::OwningExprResult
+Sema::BuildAnonymousStructUnionMemberReference(SourceLocation Loc,
+                                               FieldDecl *Field,
+                                               Expr *BaseObjectExpr,
+                                               SourceLocation OpLoc) {
+  llvm::SmallVector<FieldDecl *, 4> AnonFields;
+  VarDecl *BaseObject = BuildAnonymousStructUnionMemberPath(Field,
+                                                            AnonFields);
+
+  // Build the expression that refers to the base object, from
+  // which we will build a sequence of member references to each
+  // of the anonymous union objects and, eventually, the field we
+  // found via name lookup.
+  bool BaseObjectIsPointer = false;
+  Qualifiers BaseQuals;
+  if (BaseObject) {
+    // BaseObject is an anonymous struct/union variable (and is,
+    // therefore, not part of another non-anonymous record).
+    if (BaseObjectExpr) BaseObjectExpr->Destroy(Context);
+    MarkDeclarationReferenced(Loc, BaseObject);
+    BaseObjectExpr = new (Context) DeclRefExpr(BaseObject,BaseObject->getType(),
+                                               SourceLocation());
+    BaseQuals
+      = Context.getCanonicalType(BaseObject->getType()).getQualifiers();
+  } else if (BaseObjectExpr) {
+    // The caller provided the base object expression. Determine
+    // whether its a pointer and whether it adds any qualifiers to the
+    // anonymous struct/union fields we're looking into.
+    QualType ObjectType = BaseObjectExpr->getType();
+    if (const PointerType *ObjectPtr = ObjectType->getAs<PointerType>()) {
+      BaseObjectIsPointer = true;
+      ObjectType = ObjectPtr->getPointeeType();
+    }
+    BaseQuals
+      = Context.getCanonicalType(ObjectType).getQualifiers();
+  } else {
+    // We've found a member of an anonymous struct/union that is
+    // inside a non-anonymous struct/union, so in a well-formed
+    // program our base object expression is "this".
+    if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(CurContext)) {
+      if (!MD->isStatic()) {
+        QualType AnonFieldType
+          = Context.getTagDeclType(
+                     cast<RecordDecl>(AnonFields.back()->getDeclContext()));
+        QualType ThisType = Context.getTagDeclType(MD->getParent());
+        if ((Context.getCanonicalType(AnonFieldType)
+               == Context.getCanonicalType(ThisType)) ||
+            IsDerivedFrom(ThisType, AnonFieldType)) {
+          // Our base object expression is "this".
+          BaseObjectExpr = new (Context) CXXThisExpr(Loc,
+                                                     MD->getThisType(Context),
+                                                     /*isImplicit=*/true);
+          BaseObjectIsPointer = true;
+        }
+      } else {
+        return ExprError(Diag(Loc,diag::err_invalid_member_use_in_static_method)
+          << Field->getDeclName());
+      }
+      BaseQuals = Qualifiers::fromCVRMask(MD->getTypeQualifiers());
+    }
+
+    if (!BaseObjectExpr)
+      return ExprError(Diag(Loc, diag::err_invalid_non_static_member_use)
+        << Field->getDeclName());
+  }
+
+  // Build the implicit member references to the field of the
+  // anonymous struct/union.
+  Expr *Result = BaseObjectExpr;
+  Qualifiers ResultQuals = BaseQuals;
+  for (llvm::SmallVector<FieldDecl *, 4>::reverse_iterator
+         FI = AnonFields.rbegin(), FIEnd = AnonFields.rend();
+       FI != FIEnd; ++FI) {
+    QualType MemberType = (*FI)->getType();
+    Qualifiers MemberTypeQuals =
+      Context.getCanonicalType(MemberType).getQualifiers();
+
+    // CVR attributes from the base are picked up by members,
+    // except that 'mutable' members don't pick up 'const'.
+    if ((*FI)->isMutable())
+      ResultQuals.removeConst();
+
+    // GC attributes are never picked up by members.
+    ResultQuals.removeObjCGCAttr();
+
+    // TR 18037 does not allow fields to be declared with address spaces.
+    assert(!MemberTypeQuals.hasAddressSpace());
+
+    Qualifiers NewQuals = ResultQuals + MemberTypeQuals;
+    if (NewQuals != MemberTypeQuals)
+      MemberType = Context.getQualifiedType(MemberType, NewQuals);
+
+    MarkDeclarationReferenced(Loc, *FI);
+    PerformObjectMemberConversion(Result, *FI);
+    // FIXME: Might this end up being a qualified name?
+    Result = new (Context) MemberExpr(Result, BaseObjectIsPointer, *FI,
+                                      OpLoc, MemberType);
+    BaseObjectIsPointer = false;
+    ResultQuals = NewQuals;
+  }
+
+  return Owned(Result);
+}
+
+/// Decomposes the given name into a DeclarationName, its location, and
+/// possibly a list of template arguments.
+///
+/// If this produces template arguments, it is permitted to call
+/// DecomposeTemplateName.
+///
+/// This actually loses a lot of source location information for
+/// non-standard name kinds; we should consider preserving that in
+/// some way.
+static void DecomposeUnqualifiedId(Sema &SemaRef,
+                                   const UnqualifiedId &Id,
+                                   TemplateArgumentListInfo &Buffer,
+                                   DeclarationName &Name,
+                                   SourceLocation &NameLoc,
+                             const TemplateArgumentListInfo *&TemplateArgs) {
+  if (Id.getKind() == UnqualifiedId::IK_TemplateId) {
+    Buffer.setLAngleLoc(Id.TemplateId->LAngleLoc);
+    Buffer.setRAngleLoc(Id.TemplateId->RAngleLoc);
+
+    ASTTemplateArgsPtr TemplateArgsPtr(SemaRef,
+                                       Id.TemplateId->getTemplateArgs(),
+                                       Id.TemplateId->NumArgs);
+    SemaRef.translateTemplateArguments(TemplateArgsPtr, Buffer);
+    TemplateArgsPtr.release();
+
+    TemplateName TName =
+      Sema::TemplateTy::make(Id.TemplateId->Template).getAsVal<TemplateName>();
+
+    Name = SemaRef.Context.getNameForTemplate(TName);
+    NameLoc = Id.TemplateId->TemplateNameLoc;
+    TemplateArgs = &Buffer;
+  } else {
+    Name = SemaRef.GetNameFromUnqualifiedId(Id);
+    NameLoc = Id.StartLocation;
+    TemplateArgs = 0;
+  }
+}
+
+/// Decompose the given template name into a list of lookup results.
+///
+/// The unqualified ID must name a non-dependent template, which can
+/// be more easily tested by checking whether DecomposeUnqualifiedId
+/// found template arguments.
+static void DecomposeTemplateName(LookupResult &R, const UnqualifiedId &Id) {
+  assert(Id.getKind() == UnqualifiedId::IK_TemplateId);
+  TemplateName TName =
+    Sema::TemplateTy::make(Id.TemplateId->Template).getAsVal<TemplateName>();
+
+  if (TemplateDecl *TD = TName.getAsTemplateDecl())
+    R.addDecl(TD);
+  else if (OverloadedTemplateStorage *OT = TName.getAsOverloadedTemplate())
+    for (OverloadedTemplateStorage::iterator I = OT->begin(), E = OT->end();
+           I != E; ++I)
+      R.addDecl(*I);
+
+  R.resolveKind();
+}
+
+/// Determines whether the given record is "fully-formed" at the given
+/// location, i.e. whether a qualified lookup into it is assured of
+/// getting consistent results already.
+static bool IsFullyFormedScope(Sema &SemaRef, CXXRecordDecl *Record) {
+  if (!Record->hasDefinition())
+    return false;
+
+  for (CXXRecordDecl::base_class_iterator I = Record->bases_begin(),
+         E = Record->bases_end(); I != E; ++I) {
+    CanQualType BaseT = SemaRef.Context.getCanonicalType((*I).getType());
+    CanQual<RecordType> BaseRT = BaseT->getAs<RecordType>();
+    if (!BaseRT) return false;
+
+    CXXRecordDecl *BaseRecord = cast<CXXRecordDecl>(BaseRT->getDecl());
+    if (!BaseRecord->hasDefinition() ||
+        !IsFullyFormedScope(SemaRef, BaseRecord))
+      return false;
+  }
+
+  return true;
+}
+
+/// Determines whether we can lookup this id-expression now or whether
+/// we have to wait until template instantiation is complete.
+static bool IsDependentIdExpression(Sema &SemaRef, const CXXScopeSpec &SS) {
+  DeclContext *DC = SemaRef.computeDeclContext(SS, false);
+
+  // If the qualifier scope isn't computable, it's definitely dependent.
+  if (!DC) return true;
+
+  // If the qualifier scope doesn't name a record, we can always look into it.
+  if (!isa<CXXRecordDecl>(DC)) return false;
+
+  // We can't look into record types unless they're fully-formed.
+  if (!IsFullyFormedScope(SemaRef, cast<CXXRecordDecl>(DC))) return true;
+
+  return false;
+}
+
+/// Determines if the given class is provably not derived from all of
+/// the prospective base classes.
+static bool IsProvablyNotDerivedFrom(Sema &SemaRef,
+                                     CXXRecordDecl *Record,
+                            const llvm::SmallPtrSet<CXXRecordDecl*, 4> &Bases) {
+  if (Bases.count(Record->getCanonicalDecl()))
+    return false;
+
+  RecordDecl *RD = Record->getDefinition(SemaRef.Context);
+  if (!RD) return false;
+  Record = cast<CXXRecordDecl>(RD);
+
+  for (CXXRecordDecl::base_class_iterator I = Record->bases_begin(),
+         E = Record->bases_end(); I != E; ++I) {
+    CanQualType BaseT = SemaRef.Context.getCanonicalType((*I).getType());
+    CanQual<RecordType> BaseRT = BaseT->getAs<RecordType>();
+    if (!BaseRT) return false;
+
+    CXXRecordDecl *BaseRecord = cast<CXXRecordDecl>(BaseRT->getDecl());
+    if (!IsProvablyNotDerivedFrom(SemaRef, BaseRecord, Bases))
+      return false;
+  }
+
+  return true;
+}
+                                  
+/// Determines if this is an instance member of a class.
+static bool IsInstanceMember(NamedDecl *D) {
+  assert(D->isCXXClassMember() &&
+         "checking whether non-member is instance member");
+
+  if (isa<FieldDecl>(D)) return true;
+  
+  if (isa<CXXMethodDecl>(D))
+    return !cast<CXXMethodDecl>(D)->isStatic();
+
+  if (isa<FunctionTemplateDecl>(D)) {
+    D = cast<FunctionTemplateDecl>(D)->getTemplatedDecl();
+    return !cast<CXXMethodDecl>(D)->isStatic();
+  }
+
+  return false;
+}
+
+enum IMAKind {
+  /// The reference is definitely not an instance member access.
+  IMA_Static,
+
+  /// The reference may be an implicit instance member access.
+  IMA_Mixed,
+
+  /// The reference may be to an instance member, but it is invalid if
+  /// so, because the context is not an instance method.
+  IMA_Mixed_StaticContext,
+
+  /// The reference may be to an instance member, but it is invalid if
+  /// so, because the context is from an unrelated class.
+  IMA_Mixed_Unrelated,
+
+  /// The reference is definitely an implicit instance member access.
+  IMA_Instance,
+
+  /// The reference may be to an unresolved using declaration.
+  IMA_Unresolved,
+
+  /// The reference may be to an unresolved using declaration and the
+  /// context is not an instance method.
+  IMA_Unresolved_StaticContext,
+
+  /// The reference is to a member of an anonymous structure in a
+  /// non-class context.
+  IMA_AnonymousMember,
+
+  /// All possible referrents are instance members and the current
+  /// context is not an instance method.
+  IMA_Error_StaticContext,
+
+  /// All possible referrents are instance members of an unrelated
+  /// class.
+  IMA_Error_Unrelated
+};
+
+/// The given lookup names class member(s) and is not being used for
+/// an address-of-member expression.  Classify the type of access
+/// according to whether it's possible that this reference names an
+/// instance member.  This is best-effort; it is okay to
+/// conservatively answer "yes", in which case some errors will simply
+/// not be caught until template-instantiation.
+static IMAKind ClassifyImplicitMemberAccess(Sema &SemaRef,
+                                            const LookupResult &R) {
+  assert(!R.empty() && (*R.begin())->isCXXClassMember());
+
+  bool isStaticContext =
+    (!isa<CXXMethodDecl>(SemaRef.CurContext) ||
+     cast<CXXMethodDecl>(SemaRef.CurContext)->isStatic());
+
+  if (R.isUnresolvableResult())
+    return isStaticContext ? IMA_Unresolved_StaticContext : IMA_Unresolved;
+
+  // Collect all the declaring classes of instance members we find.
+  bool hasNonInstance = false;
+  llvm::SmallPtrSet<CXXRecordDecl*, 4> Classes;
+  for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I) {
+    NamedDecl *D = (*I)->getUnderlyingDecl();
+    if (IsInstanceMember(D)) {
+      CXXRecordDecl *R = cast<CXXRecordDecl>(D->getDeclContext());
+
+      // If this is a member of an anonymous record, move out to the
+      // innermost non-anonymous struct or union.  If there isn't one,
+      // that's a special case.
+      while (R->isAnonymousStructOrUnion()) {
+        R = dyn_cast<CXXRecordDecl>(R->getParent());
+        if (!R) return IMA_AnonymousMember;
+      }
+      Classes.insert(R->getCanonicalDecl());
+    }
+    else
+      hasNonInstance = true;
+  }
+
+  // If we didn't find any instance members, it can't be an implicit
+  // member reference.
+  if (Classes.empty())
+    return IMA_Static;
+
+  // If the current context is not an instance method, it can't be
+  // an implicit member reference.
+  if (isStaticContext)
+    return (hasNonInstance ? IMA_Mixed_StaticContext : IMA_Error_StaticContext);
+
+  // If we can prove that the current context is unrelated to all the
+  // declaring classes, it can't be an implicit member reference (in
+  // which case it's an error if any of those members are selected).
+  if (IsProvablyNotDerivedFrom(SemaRef,
+                        cast<CXXMethodDecl>(SemaRef.CurContext)->getParent(),
+                               Classes))
+    return (hasNonInstance ? IMA_Mixed_Unrelated : IMA_Error_Unrelated);
+
+  return (hasNonInstance ? IMA_Mixed : IMA_Instance);
+}
+
+/// Diagnose a reference to a field with no object available.
+static void DiagnoseInstanceReference(Sema &SemaRef,
+                                      const CXXScopeSpec &SS,
+                                      const LookupResult &R) {
+  SourceLocation Loc = R.getNameLoc();
+  SourceRange Range(Loc);
+  if (SS.isSet()) Range.setBegin(SS.getRange().getBegin());
+
+  if (R.getAsSingle<FieldDecl>()) {
+    if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(SemaRef.CurContext)) {
+      if (MD->isStatic()) {
+        // "invalid use of member 'x' in static member function"
+        SemaRef.Diag(Loc, diag::err_invalid_member_use_in_static_method)
+          << Range << R.getLookupName();
+        return;
+      }
+    }
+
+    SemaRef.Diag(Loc, diag::err_invalid_non_static_member_use)
+      << R.getLookupName() << Range;
+    return;
+  }
+
+  SemaRef.Diag(Loc, diag::err_member_call_without_object) << Range;
+}
+
+/// Diagnose an empty lookup.
+///
+/// \return false if new lookup candidates were found
+bool Sema::DiagnoseEmptyLookup(Scope *S, const CXXScopeSpec &SS,
+                               LookupResult &R) {
+  DeclarationName Name = R.getLookupName();
+
+  unsigned diagnostic = diag::err_undeclared_var_use;
+  unsigned diagnostic_suggest = diag::err_undeclared_var_use_suggest;
+  if (Name.getNameKind() == DeclarationName::CXXOperatorName ||
+      Name.getNameKind() == DeclarationName::CXXLiteralOperatorName ||
+      Name.getNameKind() == DeclarationName::CXXConversionFunctionName) {
+    diagnostic = diag::err_undeclared_use;
+    diagnostic_suggest = diag::err_undeclared_use_suggest;
+  }
+
+  // If the original lookup was an unqualified lookup, fake an
+  // unqualified lookup.  This is useful when (for example) the
+  // original lookup would not have found something because it was a
+  // dependent name.
+  for (DeclContext *DC = SS.isEmpty()? CurContext : 0;
+       DC; DC = DC->getParent()) {
+    if (isa<CXXRecordDecl>(DC)) {
+      LookupQualifiedName(R, DC);
+
+      if (!R.empty()) {
+        // Don't give errors about ambiguities in this lookup.
+        R.suppressDiagnostics();
+
+        CXXMethodDecl *CurMethod = dyn_cast<CXXMethodDecl>(CurContext);
+        bool isInstance = CurMethod &&
+                          CurMethod->isInstance() &&
+                          DC == CurMethod->getParent();
+
+        // Give a code modification hint to insert 'this->'.
+        // TODO: fixit for inserting 'Base<T>::' in the other cases.
+        // Actually quite difficult!
+        if (isInstance)
+          Diag(R.getNameLoc(), diagnostic) << Name
+            << CodeModificationHint::CreateInsertion(R.getNameLoc(),
+                                                     "this->");
+        else
+          Diag(R.getNameLoc(), diagnostic) << Name;
+
+        // Do we really want to note all of these?
+        for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I)
+          Diag((*I)->getLocation(), diag::note_dependent_var_use);
+
+        // Tell the callee to try to recover.
+        return false;
+      }
+    }
+  }
+
+  // We didn't find anything, so try to correct for a typo.
+  if (S && CorrectTypo(R, S, &SS)) {
+    if (isa<ValueDecl>(*R.begin()) || isa<FunctionTemplateDecl>(*R.begin())) {
+      if (SS.isEmpty())
+        Diag(R.getNameLoc(), diagnostic_suggest) << Name << R.getLookupName()
+          << CodeModificationHint::CreateReplacement(R.getNameLoc(),
+                                              R.getLookupName().getAsString());
+      else 
+        Diag(R.getNameLoc(), diag::err_no_member_suggest)
+          << Name << computeDeclContext(SS, false) << R.getLookupName()
+          << SS.getRange()
+          << CodeModificationHint::CreateReplacement(R.getNameLoc(),
+                                              R.getLookupName().getAsString());
+      if (NamedDecl *ND = R.getAsSingle<NamedDecl>())
+        Diag(ND->getLocation(), diag::note_previous_decl)
+          << ND->getDeclName();
+      
+      // Tell the callee to try to recover.
+      return false;
+    }
+
+    if (isa<TypeDecl>(*R.begin()) || isa<ObjCInterfaceDecl>(*R.begin())) {
+      // FIXME: If we ended up with a typo for a type name or
+      // Objective-C class name, we're in trouble because the parser
+      // is in the wrong place to recover. Suggest the typo
+      // correction, but don't make it a fix-it since we're not going
+      // to recover well anyway.
+      if (SS.isEmpty())
+        Diag(R.getNameLoc(), diagnostic_suggest) << Name << R.getLookupName();
+      else 
+        Diag(R.getNameLoc(), diag::err_no_member_suggest)
+          << Name << computeDeclContext(SS, false) << R.getLookupName()
+          << SS.getRange();
+
+      // Don't try to recover; it won't work.
+      return true;
+    }
+
+    R.clear();
+  }
+
+  // Emit a special diagnostic for failed member lookups.
+  // FIXME: computing the declaration context might fail here (?)
+  if (!SS.isEmpty()) {
+    Diag(R.getNameLoc(), diag::err_no_member)
+      << Name << computeDeclContext(SS, false)
+      << SS.getRange();
+    return true;
+  }
+
+  // Give up, we can't recover.
+  Diag(R.getNameLoc(), diagnostic) << Name;
+  return true;
+}
+
+Sema::OwningExprResult Sema::ActOnIdExpression(Scope *S,
+                                               const CXXScopeSpec &SS,
+                                               UnqualifiedId &Id,
+                                               bool HasTrailingLParen,
+                                               bool isAddressOfOperand) {
+  assert(!(isAddressOfOperand && HasTrailingLParen) &&
+         "cannot be direct & operand and have a trailing lparen");
+
+  if (SS.isInvalid())
+    return ExprError();
+
+  TemplateArgumentListInfo TemplateArgsBuffer;
+
+  // Decompose the UnqualifiedId into the following data.
+  DeclarationName Name;
+  SourceLocation NameLoc;
+  const TemplateArgumentListInfo *TemplateArgs;
+  DecomposeUnqualifiedId(*this, Id, TemplateArgsBuffer,
+                         Name, NameLoc, TemplateArgs);
+
+  IdentifierInfo *II = Name.getAsIdentifierInfo();
+
+  // C++ [temp.dep.expr]p3:
+  //   An id-expression is type-dependent if it contains:
+  //     -- an identifier that was declared with a dependent type,
+  //        (note: handled after lookup)
+  //     -- a template-id that is dependent,
+  //        (note: handled in BuildTemplateIdExpr)
+  //     -- a conversion-function-id that specifies a dependent type,
+  //     -- a nested-name-specifier that contains a class-name that
+  //        names a dependent type.
+  // Determine whether this is a member of an unknown specialization;
+  // we need to handle these differently.
+  if ((Name.getNameKind() == DeclarationName::CXXConversionFunctionName &&
+       Name.getCXXNameType()->isDependentType()) ||
+      (SS.isSet() && IsDependentIdExpression(*this, SS))) {
+    return ActOnDependentIdExpression(SS, Name, NameLoc,
+                                      isAddressOfOperand,
+                                      TemplateArgs);
+  }
+
+  // Perform the required lookup.
+  LookupResult R(*this, Name, NameLoc, LookupOrdinaryName);
+  if (TemplateArgs) {
+    // Just re-use the lookup done by isTemplateName.
+    DecomposeTemplateName(R, Id);
+  } else {
+    bool IvarLookupFollowUp = (!SS.isSet() && II && getCurMethodDecl());
+    LookupParsedName(R, S, &SS, !IvarLookupFollowUp);
+
+    // If this reference is in an Objective-C method, then we need to do
+    // some special Objective-C lookup, too.
+    if (IvarLookupFollowUp) {
+      OwningExprResult E(LookupInObjCMethod(R, S, II, true));
+      if (E.isInvalid())
+        return ExprError();
+
+      Expr *Ex = E.takeAs<Expr>();
+      if (Ex) return Owned(Ex);
+    }
+  }
+
+  if (R.isAmbiguous())
+    return ExprError();
+
+  // Determine whether this name might be a candidate for
+  // argument-dependent lookup.
+  bool ADL = UseArgumentDependentLookup(SS, R, HasTrailingLParen);
+
+  if (R.empty() && !ADL) {
+    // Otherwise, this could be an implicitly declared function reference (legal
+    // in C90, extension in C99, forbidden in C++).
+    if (HasTrailingLParen && II && !getLangOptions().CPlusPlus) {
+      NamedDecl *D = ImplicitlyDefineFunction(NameLoc, *II, S);
+      if (D) R.addDecl(D);
+    }
+
+    // If this name wasn't predeclared and if this is not a function
+    // call, diagnose the problem.
+    if (R.empty()) {
+      if (DiagnoseEmptyLookup(S, SS, R))
+        return ExprError();
+
+      assert(!R.empty() &&
+             "DiagnoseEmptyLookup returned false but added no results");
+
+      // If we found an Objective-C instance variable, let
+      // LookupInObjCMethod build the appropriate expression to
+      // reference the ivar. 
+      if (ObjCIvarDecl *Ivar = R.getAsSingle<ObjCIvarDecl>()) {
+        R.clear();
+        OwningExprResult E(LookupInObjCMethod(R, S, Ivar->getIdentifier()));
+        assert(E.isInvalid() || E.get());
+        return move(E);
+      }
+    }
+  }
+
+  // This is guaranteed from this point on.
+  assert(!R.empty() || ADL);
+
+  if (VarDecl *Var = R.getAsSingle<VarDecl>()) {
+    // Warn about constructs like:
+    //   if (void *X = foo()) { ... } else { X }.
+    // In the else block, the pointer is always false.
+
+    if (Var->isDeclaredInCondition() && Var->getType()->isScalarType()) {
+      Scope *CheckS = S;
+      while (CheckS && CheckS->getControlParent()) {
+        if (CheckS->isWithinElse() &&
+            CheckS->getControlParent()->isDeclScope(DeclPtrTy::make(Var))) {
+          ExprError(Diag(NameLoc, diag::warn_value_always_zero)
+            << Var->getDeclName()
+            << (Var->getType()->isPointerType()? 2 :
+                Var->getType()->isBooleanType()? 1 : 0));
+          break;
+        }
+
+        // Move to the parent of this scope.
+        CheckS = CheckS->getParent();
+      }
+    }
+  } else if (FunctionDecl *Func = R.getAsSingle<FunctionDecl>()) {
+    if (!getLangOptions().CPlusPlus && !Func->hasPrototype()) {
+      // C99 DR 316 says that, if a function type comes from a
+      // function definition (without a prototype), that type is only
+      // used for checking compatibility. Therefore, when referencing
+      // the function, we pretend that we don't have the full function
+      // type.
+      if (DiagnoseUseOfDecl(Func, NameLoc))
+        return ExprError();
+
+      QualType T = Func->getType();
+      QualType NoProtoType = T;
+      if (const FunctionProtoType *Proto = T->getAs<FunctionProtoType>())
+        NoProtoType = Context.getFunctionNoProtoType(Proto->getResultType());
+      return BuildDeclRefExpr(Func, NoProtoType, NameLoc, &SS);
+    }
+  }
+
+  // Check whether this might be a C++ implicit instance member access.
+  // C++ [expr.prim.general]p6:
+  //   Within the definition of a non-static member function, an
+  //   identifier that names a non-static member is transformed to a
+  //   class member access expression.
+  // But note that &SomeClass::foo is grammatically distinct, even
+  // though we don't parse it that way.
+  if (!R.empty() && (*R.begin())->isCXXClassMember()) {
+    bool isAbstractMemberPointer = (isAddressOfOperand && !SS.isEmpty());
+    if (!isAbstractMemberPointer)
+      return BuildPossibleImplicitMemberExpr(SS, R, TemplateArgs);
+  }
+
+  if (TemplateArgs)
+    return BuildTemplateIdExpr(SS, R, ADL, *TemplateArgs);
+
+  return BuildDeclarationNameExpr(SS, R, ADL);
+}
+
+/// Builds an expression which might be an implicit member expression.
+Sema::OwningExprResult
+Sema::BuildPossibleImplicitMemberExpr(const CXXScopeSpec &SS,
+                                      LookupResult &R,
+                                const TemplateArgumentListInfo *TemplateArgs) {
+  switch (ClassifyImplicitMemberAccess(*this, R)) {
+  case IMA_Instance:
+    return BuildImplicitMemberExpr(SS, R, TemplateArgs, true);
+
+  case IMA_AnonymousMember:
+    assert(R.isSingleResult());
+    return BuildAnonymousStructUnionMemberReference(R.getNameLoc(),
+                                                    R.getAsSingle<FieldDecl>());
+
+  case IMA_Mixed:
+  case IMA_Mixed_Unrelated:
+  case IMA_Unresolved:
+    return BuildImplicitMemberExpr(SS, R, TemplateArgs, false);
+
+  case IMA_Static:
+  case IMA_Mixed_StaticContext:
+  case IMA_Unresolved_StaticContext:
+    if (TemplateArgs)
+      return BuildTemplateIdExpr(SS, R, false, *TemplateArgs);
+    return BuildDeclarationNameExpr(SS, R, false);
+
+  case IMA_Error_StaticContext:
+  case IMA_Error_Unrelated:
+    DiagnoseInstanceReference(*this, SS, R);
+    return ExprError();
+  }
+
+  llvm_unreachable("unexpected instance member access kind");
+  return ExprError();
+}
+
+/// BuildQualifiedDeclarationNameExpr - Build a C++ qualified
+/// declaration name, generally during template instantiation.
+/// There's a large number of things which don't need to be done along
+/// this path.
+Sema::OwningExprResult
+Sema::BuildQualifiedDeclarationNameExpr(const CXXScopeSpec &SS,
+                                        DeclarationName Name,
+                                        SourceLocation NameLoc) {
+  DeclContext *DC;
+  if (!(DC = computeDeclContext(SS, false)) ||
+      DC->isDependentContext() ||
+      RequireCompleteDeclContext(SS))
+    return BuildDependentDeclRefExpr(SS, Name, NameLoc, 0);
+
+  LookupResult R(*this, Name, NameLoc, LookupOrdinaryName);
+  LookupQualifiedName(R, DC);
+
+  if (R.isAmbiguous())
+    return ExprError();
+
+  if (R.empty()) {
+    Diag(NameLoc, diag::err_no_member) << Name << DC << SS.getRange();
+    return ExprError();
+  }
+
+  return BuildDeclarationNameExpr(SS, R, /*ADL*/ false);
+}
+
+/// LookupInObjCMethod - The parser has read a name in, and Sema has
+/// detected that we're currently inside an ObjC method.  Perform some
+/// additional lookup.
+///
+/// Ideally, most of this would be done by lookup, but there's
+/// actually quite a lot of extra work involved.
+///
+/// Returns a null sentinel to indicate trivial success.
+Sema::OwningExprResult
+Sema::LookupInObjCMethod(LookupResult &Lookup, Scope *S,
+                         IdentifierInfo *II,
+                         bool AllowBuiltinCreation) {
+  SourceLocation Loc = Lookup.getNameLoc();
+
+  // There are two cases to handle here.  1) scoped lookup could have failed,
+  // in which case we should look for an ivar.  2) scoped lookup could have
+  // found a decl, but that decl is outside the current instance method (i.e.
+  // a global variable).  In these two cases, we do a lookup for an ivar with
+  // this name, if the lookup sucedes, we replace it our current decl.
+
+  // If we're in a class method, we don't normally want to look for
+  // ivars.  But if we don't find anything else, and there's an
+  // ivar, that's an error.
+  bool IsClassMethod = getCurMethodDecl()->isClassMethod();
+
+  bool LookForIvars;
+  if (Lookup.empty())
+    LookForIvars = true;
+  else if (IsClassMethod)
+    LookForIvars = false;
+  else
+    LookForIvars = (Lookup.isSingleResult() &&
+                    Lookup.getFoundDecl()->isDefinedOutsideFunctionOrMethod());
+  ObjCInterfaceDecl *IFace = 0;
+  if (LookForIvars) {
+    IFace = getCurMethodDecl()->getClassInterface();
+    ObjCInterfaceDecl *ClassDeclared;
+    if (ObjCIvarDecl *IV = IFace->lookupInstanceVariable(II, ClassDeclared)) {
+      // Diagnose using an ivar in a class method.
+      if (IsClassMethod)
+        return ExprError(Diag(Loc, diag::error_ivar_use_in_class_method)
+                         << IV->getDeclName());
+
+      // If we're referencing an invalid decl, just return this as a silent
+      // error node.  The error diagnostic was already emitted on the decl.
+      if (IV->isInvalidDecl())
+        return ExprError();
+
+      // Check if referencing a field with __attribute__((deprecated)).
+      if (DiagnoseUseOfDecl(IV, Loc))
+        return ExprError();
+
+      // Diagnose the use of an ivar outside of the declaring class.
+      if (IV->getAccessControl() == ObjCIvarDecl::Private &&
+          ClassDeclared != IFace)
+        Diag(Loc, diag::error_private_ivar_access) << IV->getDeclName();
+
+      // FIXME: This should use a new expr for a direct reference, don't
+      // turn this into Self->ivar, just return a BareIVarExpr or something.
+      IdentifierInfo &II = Context.Idents.get("self");
+      UnqualifiedId SelfName;
+      SelfName.setIdentifier(&II, SourceLocation());          
+      CXXScopeSpec SelfScopeSpec;
+      OwningExprResult SelfExpr = ActOnIdExpression(S, SelfScopeSpec,
+                                                    SelfName, false, false);
+      MarkDeclarationReferenced(Loc, IV);
+      return Owned(new (Context)
+                   ObjCIvarRefExpr(IV, IV->getType(), Loc,
+                                   SelfExpr.takeAs<Expr>(), true, true));
+    }
+  } else if (getCurMethodDecl()->isInstanceMethod()) {
+    // We should warn if a local variable hides an ivar.
+    ObjCInterfaceDecl *IFace = getCurMethodDecl()->getClassInterface();
+    ObjCInterfaceDecl *ClassDeclared;
+    if (ObjCIvarDecl *IV = IFace->lookupInstanceVariable(II, ClassDeclared)) {
+      if (IV->getAccessControl() != ObjCIvarDecl::Private ||
+          IFace == ClassDeclared)
+        Diag(Loc, diag::warn_ivar_use_hidden) << IV->getDeclName();
+    }
+  }
+
+  // Needed to implement property "super.method" notation.
+  if (Lookup.empty() && II->isStr("super")) {
+    QualType T;
+    
+    if (getCurMethodDecl()->isInstanceMethod())
+      T = Context.getObjCObjectPointerType(Context.getObjCInterfaceType(
+                                    getCurMethodDecl()->getClassInterface()));
+    else
+      T = Context.getObjCClassType();
+    return Owned(new (Context) ObjCSuperExpr(Loc, T));
+  }
+  if (Lookup.empty() && II && AllowBuiltinCreation) {
+    // FIXME. Consolidate this with similar code in LookupName.
+    if (unsigned BuiltinID = II->getBuiltinID()) {
+      if (!(getLangOptions().CPlusPlus &&
+            Context.BuiltinInfo.isPredefinedLibFunction(BuiltinID))) {
+        NamedDecl *D = LazilyCreateBuiltin((IdentifierInfo *)II, BuiltinID,
+                                           S, Lookup.isForRedeclaration(),
+                                           Lookup.getNameLoc());
+        if (D) Lookup.addDecl(D);
+      }
+    }
+  }
+  if (LangOpts.ObjCNonFragileABI2 && LookForIvars && Lookup.empty()) {
+    ObjCIvarDecl *Ivar = SynthesizeNewPropertyIvar(IFace, II);
+    if (Ivar)
+      return LookupInObjCMethod(Lookup, S, II, AllowBuiltinCreation);
+  }
+  // Sentinel value saying that we didn't do anything special.
+  return Owned((Expr*) 0);
+}
+
+/// \brief Cast member's object to its own class if necessary.
+bool
+Sema::PerformObjectMemberConversion(Expr *&From, NamedDecl *Member) {
+  if (FieldDecl *FD = dyn_cast<FieldDecl>(Member))
+    if (CXXRecordDecl *RD =
+        dyn_cast<CXXRecordDecl>(FD->getDeclContext())) {
+      QualType DestType =
+        Context.getCanonicalType(Context.getTypeDeclType(RD));
+      if (DestType->isDependentType() || From->getType()->isDependentType())
+        return false;
+      QualType FromRecordType = From->getType();
+      QualType DestRecordType = DestType;
+      if (FromRecordType->getAs<PointerType>()) {
+        DestType = Context.getPointerType(DestType);
+        FromRecordType = FromRecordType->getPointeeType();
+      }
+      if (!Context.hasSameUnqualifiedType(FromRecordType, DestRecordType) &&
+          CheckDerivedToBaseConversion(FromRecordType,
+                                       DestRecordType,
+                                       From->getSourceRange().getBegin(),
+                                       From->getSourceRange()))
+        return true;
+      ImpCastExprToType(From, DestType, CastExpr::CK_DerivedToBase,
+                        /*isLvalue=*/true);
+    }
+  return false;
+}
+
+/// \brief Build a MemberExpr AST node.
+static MemberExpr *BuildMemberExpr(ASTContext &C, Expr *Base, bool isArrow,
+                                   const CXXScopeSpec &SS, ValueDecl *Member,
+                                   SourceLocation Loc, QualType Ty,
+                          const TemplateArgumentListInfo *TemplateArgs = 0) {
+  NestedNameSpecifier *Qualifier = 0;
+  SourceRange QualifierRange;
+  if (SS.isSet()) {
+    Qualifier = (NestedNameSpecifier *) SS.getScopeRep();
+    QualifierRange = SS.getRange();
+  }
+
+  return MemberExpr::Create(C, Base, isArrow, Qualifier, QualifierRange,
+                            Member, Loc, TemplateArgs, Ty);
+}
+
+/// Builds an implicit member access expression.  The current context
+/// is known to be an instance method, and the given unqualified lookup
+/// set is known to contain only instance members, at least one of which
+/// is from an appropriate type.
+Sema::OwningExprResult
+Sema::BuildImplicitMemberExpr(const CXXScopeSpec &SS,
+                              LookupResult &R,
+                              const TemplateArgumentListInfo *TemplateArgs,
+                              bool IsKnownInstance) {
+  assert(!R.empty() && !R.isAmbiguous());
+
+  SourceLocation Loc = R.getNameLoc();
+
+  // We may have found a field within an anonymous union or struct
+  // (C++ [class.union]).
+  // FIXME: This needs to happen post-isImplicitMemberReference?
+  // FIXME: template-ids inside anonymous structs?
+  if (FieldDecl *FD = R.getAsSingle<FieldDecl>())
+    if (cast<RecordDecl>(FD->getDeclContext())->isAnonymousStructOrUnion())
+      return BuildAnonymousStructUnionMemberReference(Loc, FD);
+
+  // If this is known to be an instance access, go ahead and build a
+  // 'this' expression now.
+  QualType ThisType = cast<CXXMethodDecl>(CurContext)->getThisType(Context);
+  Expr *This = 0; // null signifies implicit access
+  if (IsKnownInstance) {
+    SourceLocation Loc = R.getNameLoc();
+    if (SS.getRange().isValid())
+      Loc = SS.getRange().getBegin();
+    This = new (Context) CXXThisExpr(Loc, ThisType, /*isImplicit=*/true);
+  }
+
+  return BuildMemberReferenceExpr(ExprArg(*this, This), ThisType,
+                                  /*OpLoc*/ SourceLocation(),
+                                  /*IsArrow*/ true,
+                                  SS,
+                                  /*FirstQualifierInScope*/ 0,
+                                  R, TemplateArgs);
+}
+
+bool Sema::UseArgumentDependentLookup(const CXXScopeSpec &SS,
+                                      const LookupResult &R,
+                                      bool HasTrailingLParen) {
+  // Only when used directly as the postfix-expression of a call.
+  if (!HasTrailingLParen)
+    return false;
+
+  // Never if a scope specifier was provided.
+  if (SS.isSet())
+    return false;
+
+  // Only in C++ or ObjC++.
+  if (!getLangOptions().CPlusPlus)
+    return false;
+
+  // Turn off ADL when we find certain kinds of declarations during
+  // normal lookup:
+  for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I) {
+    NamedDecl *D = *I;
+
+    // C++0x [basic.lookup.argdep]p3:
+    //     -- a declaration of a class member
+    // Since using decls preserve this property, we check this on the
+    // original decl.
+    if (D->isCXXClassMember())
+      return false;
+
+    // C++0x [basic.lookup.argdep]p3:
+    //     -- a block-scope function declaration that is not a
+    //        using-declaration
+    // NOTE: we also trigger this for function templates (in fact, we
+    // don't check the decl type at all, since all other decl types
+    // turn off ADL anyway).
+    if (isa<UsingShadowDecl>(D))
+      D = cast<UsingShadowDecl>(D)->getTargetDecl();
+    else if (D->getDeclContext()->isFunctionOrMethod())
+      return false;
+
+    // C++0x [basic.lookup.argdep]p3:
+    //     -- a declaration that is neither a function or a function
+    //        template
+    // And also for builtin functions.
+    if (isa<FunctionDecl>(D)) {
+      FunctionDecl *FDecl = cast<FunctionDecl>(D);
+
+      // But also builtin functions.
+      if (FDecl->getBuiltinID() && FDecl->isImplicit())
+        return false;
+    } else if (!isa<FunctionTemplateDecl>(D))
+      return false;
+  }
+
+  return true;
+}
+
+
+/// Diagnoses obvious problems with the use of the given declaration
+/// as an expression.  This is only actually called for lookups that
+/// were not overloaded, and it doesn't promise that the declaration
+/// will in fact be used.
+static bool CheckDeclInExpr(Sema &S, SourceLocation Loc, NamedDecl *D) {
+  if (isa<TypedefDecl>(D)) {
+    S.Diag(Loc, diag::err_unexpected_typedef) << D->getDeclName();
+    return true;
+  }
+
+  if (isa<ObjCInterfaceDecl>(D)) {
+    S.Diag(Loc, diag::err_unexpected_interface) << D->getDeclName();
+    return true;
+  }
+
+  if (isa<NamespaceDecl>(D)) {
+    S.Diag(Loc, diag::err_unexpected_namespace) << D->getDeclName();
+    return true;
+  }
+
+  return false;
+}
+
+Sema::OwningExprResult
+Sema::BuildDeclarationNameExpr(const CXXScopeSpec &SS,
+                               LookupResult &R,
+                               bool NeedsADL) {
+  // If this is a single, fully-resolved result and we don't need ADL,
+  // just build an ordinary singleton decl ref.
+  if (!NeedsADL && R.isSingleResult() && !R.getAsSingle<FunctionTemplateDecl>())
+    return BuildDeclarationNameExpr(SS, R.getNameLoc(), R.getFoundDecl());
+
+  // We only need to check the declaration if there's exactly one
+  // result, because in the overloaded case the results can only be
+  // functions and function templates.
+  if (R.isSingleResult() &&
+      CheckDeclInExpr(*this, R.getNameLoc(), R.getFoundDecl()))
+    return ExprError();
+
+  // Otherwise, just build an unresolved lookup expression.  Suppress
+  // any lookup-related diagnostics; we'll hash these out later, when
+  // we've picked a target.
+  R.suppressDiagnostics();
+
+  bool Dependent
+    = UnresolvedLookupExpr::ComputeDependence(R.begin(), R.end(), 0);
+  UnresolvedLookupExpr *ULE
+    = UnresolvedLookupExpr::Create(Context, Dependent, R.getNamingClass(),
+                                   (NestedNameSpecifier*) SS.getScopeRep(),
+                                   SS.getRange(),
+                                   R.getLookupName(), R.getNameLoc(),
+                                   NeedsADL, R.isOverloadedResult());
+  ULE->addDecls(R.begin(), R.end());
+
+  return Owned(ULE);
+}
+                               
+
+/// \brief Complete semantic analysis for a reference to the given declaration.
+Sema::OwningExprResult
+Sema::BuildDeclarationNameExpr(const CXXScopeSpec &SS,
+                               SourceLocation Loc, NamedDecl *D) {
+  assert(D && "Cannot refer to a NULL declaration");
+  assert(!isa<FunctionTemplateDecl>(D) &&
+         "Cannot refer unambiguously to a function template");
+
+  if (CheckDeclInExpr(*this, Loc, D))
+    return ExprError();
+
+  if (TemplateDecl *Template = dyn_cast<TemplateDecl>(D)) {
+    // Specifically diagnose references to class templates that are missing
+    // a template argument list.
+    Diag(Loc, diag::err_template_decl_ref)
+      << Template << SS.getRange();
+    Diag(Template->getLocation(), diag::note_template_decl_here);
+    return ExprError();
+  }
+
+  // Make sure that we're referring to a value.
+  ValueDecl *VD = dyn_cast<ValueDecl>(D);
+  if (!VD) {
+    Diag(Loc, diag::err_ref_non_value) 
+      << D << SS.getRange();
+    Diag(D->getLocation(), diag::note_declared_at);
+    return ExprError();
+  }
+
+  // Check whether this declaration can be used. Note that we suppress
+  // this check when we're going to perform argument-dependent lookup
+  // on this function name, because this might not be the function
+  // that overload resolution actually selects.
+  if (DiagnoseUseOfDecl(VD, Loc))
+    return ExprError();
+
+  // Only create DeclRefExpr's for valid Decl's.
+  if (VD->isInvalidDecl())
+    return ExprError();
+
+  // If the identifier reference is inside a block, and it refers to a value
+  // that is outside the block, create a BlockDeclRefExpr instead of a
+  // DeclRefExpr.  This ensures the value is treated as a copy-in snapshot when
+  // the block is formed.
+  //
+  // We do not do this for things like enum constants, global variables, etc,
+  // as they do not get snapshotted.
+  //
+  if (CurBlock && ShouldSnapshotBlockValueReference(CurBlock, VD)) {
+    if (VD->getType().getTypePtr()->isVariablyModifiedType()) {
+      Diag(Loc, diag::err_ref_vm_type);
+      Diag(D->getLocation(), diag::note_declared_at);
+      return ExprError();
+    }
+
+    if (VD->getType()->isArrayType()) {
+      Diag(Loc, diag::err_ref_array_type);
+      Diag(D->getLocation(), diag::note_declared_at);
+      return ExprError();
+    }
+
+    MarkDeclarationReferenced(Loc, VD);
+    QualType ExprTy = VD->getType().getNonReferenceType();
+    // The BlocksAttr indicates the variable is bound by-reference.
+    if (VD->getAttr<BlocksAttr>())
+      return Owned(new (Context) BlockDeclRefExpr(VD, ExprTy, Loc, true));
+    // This is to record that a 'const' was actually synthesize and added.
+    bool constAdded = !ExprTy.isConstQualified();
+    // Variable will be bound by-copy, make it const within the closure.
+
+    ExprTy.addConst();
+    return Owned(new (Context) BlockDeclRefExpr(VD, ExprTy, Loc, false,
+                                                constAdded));
+  }
+  // If this reference is not in a block or if the referenced variable is
+  // within the block, create a normal DeclRefExpr.
+
+  return BuildDeclRefExpr(VD, VD->getType().getNonReferenceType(), Loc, &SS);
+}
+
+Sema::OwningExprResult Sema::ActOnPredefinedExpr(SourceLocation Loc,
+                                                 tok::TokenKind Kind) {
+  PredefinedExpr::IdentType IT;
+
+  switch (Kind) {
+  default: assert(0 && "Unknown simple primary expr!");
+  case tok::kw___func__: IT = PredefinedExpr::Func; break; // [C99 6.4.2.2]
+  case tok::kw___FUNCTION__: IT = PredefinedExpr::Function; break;
+  case tok::kw___PRETTY_FUNCTION__: IT = PredefinedExpr::PrettyFunction; break;
+  }
+
+  // Pre-defined identifiers are of type char[x], where x is the length of the
+  // string.
+
+  Decl *currentDecl = getCurFunctionOrMethodDecl();
+  if (!currentDecl) {
+    Diag(Loc, diag::ext_predef_outside_function);
+    currentDecl = Context.getTranslationUnitDecl();
+  }
+
+  QualType ResTy;
+  if (cast<DeclContext>(currentDecl)->isDependentContext()) {
+    ResTy = Context.DependentTy;
+  } else {
+    unsigned Length =
+      PredefinedExpr::ComputeName(Context, IT, currentDecl).length();
+
+    llvm::APInt LengthI(32, Length + 1);
+    ResTy = Context.CharTy.withConst();
+    ResTy = Context.getConstantArrayType(ResTy, LengthI, ArrayType::Normal, 0);
+  }
+  return Owned(new (Context) PredefinedExpr(Loc, ResTy, IT));
+}
+
+Sema::OwningExprResult Sema::ActOnCharacterConstant(const Token &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 ExprError();
+
+  QualType Ty;
+  if (!getLangOptions().CPlusPlus)
+    Ty = Context.IntTy;   // 'x' and L'x' -> int in C.
+  else if (Literal.isWide())
+    Ty = Context.WCharTy; // L'x' -> wchar_t in C++.
+  else if (Literal.isMultiChar())
+    Ty = Context.IntTy;   // 'wxyz' -> int in C++.
+  else
+    Ty = Context.CharTy;  // 'x' -> char in C++
+
+  return Owned(new (Context) CharacterLiteral(Literal.getValue(),
+                                              Literal.isWide(),
+                                              Ty, Tok.getLocation()));
+}
+
+Action::OwningExprResult Sema::ActOnNumericConstant(const Token &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 Val = PP.getSpellingOfSingleCharacterNumericConstant(Tok);
+    unsigned IntSize = Context.Target.getIntWidth();
+    return Owned(new (Context) IntegerLiteral(llvm::APInt(IntSize, Val-'0'),
+                    Context.IntTy, Tok.getLocation()));
+  }
+
+  llvm::SmallString<512> IntegerBuffer;
+  // Add padding so that NumericLiteralParser can overread by one character.
+  IntegerBuffer.resize(Tok.getLength()+1);
+  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 ExprError();
+
+  Expr *Res;
+
+  if (Literal.isFloatingLiteral()) {
+    QualType Ty;
+    if (Literal.isFloat)
+      Ty = Context.FloatTy;
+    else if (!Literal.isLong)
+      Ty = Context.DoubleTy;
+    else
+      Ty = Context.LongDoubleTy;
+
+    const llvm::fltSemantics &Format = Context.getFloatTypeSemantics(Ty);
+
+    using llvm::APFloat;
+    APFloat Val(Format);
+
+    APFloat::opStatus result = Literal.GetFloatValue(Val);
+
+    // Overflow is always an error, but underflow is only an error if
+    // we underflowed to zero (APFloat reports denormals as underflow).
+    if ((result & APFloat::opOverflow) ||
+        ((result & APFloat::opUnderflow) && Val.isZero())) {
+      unsigned diagnostic;
+      llvm::SmallVector<char, 20> buffer;
+      if (result & APFloat::opOverflow) {
+        diagnostic = diag::err_float_overflow;
+        APFloat::getLargest(Format).toString(buffer);
+      } else {
+        diagnostic = diag::err_float_underflow;
+        APFloat::getSmallest(Format).toString(buffer);
+      }
+
+      Diag(Tok.getLocation(), diagnostic)
+        << Ty
+        << llvm::StringRef(buffer.data(), buffer.size());
+    }
+
+    bool isExact = (result == APFloat::opOK);
+    Res = new (Context) FloatingLiteral(Val, isExact, Ty, Tok.getLocation());
+
+  } else if (!Literal.isIntegerLiteral()) {
+    return ExprError();
+  } else {
+    QualType Ty;
+
+    // long long is a C99 feature.
+    if (!getLangOptions().C99 && !getLangOptions().CPlusPlus0x &&
+        Literal.isLongLong)
+      Diag(Tok.getLocation(), diag::ext_longlong);
+
+    // Get the value in the widest-possible width.
+    llvm::APInt ResultVal(Context.Target.getIntMaxTWidth(), 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);
+      Ty = Context.UnsignedLongLongTy;
+      assert(Context.getTypeSize(Ty) == 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.
+      unsigned Width = 0;
+      if (!Literal.isLong && !Literal.isLongLong) {
+        // Are int/unsigned possibilities?
+        unsigned IntSize = Context.Target.getIntWidth();
+
+        // 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)
+            Ty = Context.IntTy;
+          else if (AllowUnsigned)
+            Ty = Context.UnsignedIntTy;
+          Width = IntSize;
+        }
+      }
+
+      // Are long/unsigned long possibilities?
+      if (Ty.isNull() && !Literal.isLongLong) {
+        unsigned LongSize = Context.Target.getLongWidth();
+
+        // 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)
+            Ty = Context.LongTy;
+          else if (AllowUnsigned)
+            Ty = Context.UnsignedLongTy;
+          Width = LongSize;
+        }
+      }
+
+      // Finally, check long long if needed.
+      if (Ty.isNull()) {
+        unsigned LongLongSize = Context.Target.getLongLongWidth();
+
+        // 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)
+            Ty = Context.LongLongTy;
+          else if (AllowUnsigned)
+            Ty = Context.UnsignedLongLongTy;
+          Width = LongLongSize;
+        }
+      }
+
+      // 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 (Ty.isNull()) {
+        Diag(Tok.getLocation(), diag::warn_integer_too_large_for_signed);
+        Ty = Context.UnsignedLongLongTy;
+        Width = Context.Target.getLongLongWidth();
+      }
+
+      if (ResultVal.getBitWidth() != Width)
+        ResultVal.trunc(Width);
+    }
+    Res = new (Context) IntegerLiteral(ResultVal, Ty, Tok.getLocation());
+  }
+
+  // If this is an imaginary literal, create the ImaginaryLiteral wrapper.
+  if (Literal.isImaginary)
+    Res = new (Context) ImaginaryLiteral(Res,
+                                        Context.getComplexType(Res->getType()));
+
+  return Owned(Res);
+}
+
+Action::OwningExprResult Sema::ActOnParenExpr(SourceLocation L,
+                                              SourceLocation R, ExprArg Val) {
+  Expr *E = Val.takeAs<Expr>();
+  assert((E != 0) && "ActOnParenExpr() missing expr");
+  return Owned(new (Context) ParenExpr(L, R, E));
+}
+
+/// The UsualUnaryConversions() function is *not* called by this routine.
+/// See C99 6.3.2.1p[2-4] for more details.
+bool Sema::CheckSizeOfAlignOfOperand(QualType exprType,
+                                     SourceLocation OpLoc,
+                                     const SourceRange &ExprRange,
+                                     bool isSizeof) {
+  if (exprType->isDependentType())
+    return false;
+
+  // C++ [expr.sizeof]p2: "When applied to a reference or a reference type,
+  //   the result is the size of the referenced type."
+  // C++ [expr.alignof]p3: "When alignof is applied to a reference type, the
+  //   result shall be the alignment of the referenced type."
+  if (const ReferenceType *Ref = exprType->getAs<ReferenceType>())
+    exprType = Ref->getPointeeType();
+
+  // C99 6.5.3.4p1:
+  if (exprType->isFunctionType()) {
+    // alignof(function) is allowed as an extension.
+    if (isSizeof)
+      Diag(OpLoc, diag::ext_sizeof_function_type) << ExprRange;
+    return false;
+  }
+
+  // Allow sizeof(void)/alignof(void) as an extension.
+  if (exprType->isVoidType()) {
+    Diag(OpLoc, diag::ext_sizeof_void_type)
+      << (isSizeof ? "sizeof" : "__alignof") << ExprRange;
+    return false;
+  }
+
+  if (RequireCompleteType(OpLoc, exprType,
+                          PDiag(diag::err_sizeof_alignof_incomplete_type)
+                          << int(!isSizeof) << ExprRange))
+    return true;
+
+  // Reject sizeof(interface) and sizeof(interface<proto>) in 64-bit mode.
+  if (LangOpts.ObjCNonFragileABI && exprType->isObjCInterfaceType()) {
+    Diag(OpLoc, diag::err_sizeof_nonfragile_interface)
+      << exprType << isSizeof << ExprRange;
+    return true;
+  }
+
+  return false;
+}
+
+bool Sema::CheckAlignOfExpr(Expr *E, SourceLocation OpLoc,
+                            const SourceRange &ExprRange) {
+  E = E->IgnoreParens();
+
+  // alignof decl is always ok.
+  if (isa<DeclRefExpr>(E))
+    return false;
+
+  // Cannot know anything else if the expression is dependent.
+  if (E->isTypeDependent())
+    return false;
+
+  if (E->getBitField()) {
+    Diag(OpLoc, diag::err_sizeof_alignof_bitfield) << 1 << ExprRange;
+    return true;
+  }
+
+  // Alignment of a field access is always okay, so long as it isn't a
+  // bit-field.
+  if (MemberExpr *ME = dyn_cast<MemberExpr>(E))
+    if (isa<FieldDecl>(ME->getMemberDecl()))
+      return false;
+
+  return CheckSizeOfAlignOfOperand(E->getType(), OpLoc, ExprRange, false);
+}
+
+/// \brief Build a sizeof or alignof expression given a type operand.
+Action::OwningExprResult
+Sema::CreateSizeOfAlignOfExpr(TypeSourceInfo *TInfo,
+                              SourceLocation OpLoc,
+                              bool isSizeOf, SourceRange R) {
+  if (!TInfo)
+    return ExprError();
+
+  QualType T = TInfo->getType();
+
+  if (!T->isDependentType() &&
+      CheckSizeOfAlignOfOperand(T, OpLoc, R, isSizeOf))
+    return ExprError();
+
+  // C99 6.5.3.4p4: the type (an unsigned integer type) is size_t.
+  return Owned(new (Context) SizeOfAlignOfExpr(isSizeOf, TInfo,
+                                               Context.getSizeType(), OpLoc,
+                                               R.getEnd()));
+}
+
+/// \brief Build a sizeof or alignof expression given an expression
+/// operand.
+Action::OwningExprResult
+Sema::CreateSizeOfAlignOfExpr(Expr *E, SourceLocation OpLoc,
+                              bool isSizeOf, SourceRange R) {
+  // Verify that the operand is valid.
+  bool isInvalid = false;
+  if (E->isTypeDependent()) {
+    // Delay type-checking for type-dependent expressions.
+  } else if (!isSizeOf) {
+    isInvalid = CheckAlignOfExpr(E, OpLoc, R);
+  } else if (E->getBitField()) {  // C99 6.5.3.4p1.
+    Diag(OpLoc, diag::err_sizeof_alignof_bitfield) << 0;
+    isInvalid = true;
+  } else {
+    isInvalid = CheckSizeOfAlignOfOperand(E->getType(), OpLoc, R, true);
+  }
+
+  if (isInvalid)
+    return ExprError();
+
+  // C99 6.5.3.4p4: the type (an unsigned integer type) is size_t.
+  return Owned(new (Context) SizeOfAlignOfExpr(isSizeOf, E,
+                                               Context.getSizeType(), OpLoc,
+                                               R.getEnd()));
+}
+
+/// ActOnSizeOfAlignOfExpr - Handle @c sizeof(type) and @c sizeof @c expr and
+/// the same for @c alignof and @c __alignof
+/// Note that the ArgRange is invalid if isType is false.
+Action::OwningExprResult
+Sema::ActOnSizeOfAlignOfExpr(SourceLocation OpLoc, bool isSizeof, bool isType,
+                             void *TyOrEx, const SourceRange &ArgRange) {
+  // If error parsing type, ignore.
+  if (TyOrEx == 0) return ExprError();
+
+  if (isType) {
+    TypeSourceInfo *TInfo;
+    (void) GetTypeFromParser(TyOrEx, &TInfo);
+    return CreateSizeOfAlignOfExpr(TInfo, OpLoc, isSizeof, ArgRange);
+  }
+
+  Expr *ArgEx = (Expr *)TyOrEx;
+  Action::OwningExprResult Result
+    = CreateSizeOfAlignOfExpr(ArgEx, OpLoc, isSizeof, ArgEx->getSourceRange());
+
+  if (Result.isInvalid())
+    DeleteExpr(ArgEx);
+
+  return move(Result);
+}
+
+QualType Sema::CheckRealImagOperand(Expr *&V, SourceLocation Loc, bool isReal) {
+  if (V->isTypeDependent())
+    return Context.DependentTy;
+
+  // These operators return the element type of a complex type.
+  if (const ComplexType *CT = V->getType()->getAs<ComplexType>())
+    return CT->getElementType();
+
+  // Otherwise they pass through real integer and floating point types here.
+  if (V->getType()->isArithmeticType())
+    return V->getType();
+
+  // Reject anything else.
+  Diag(Loc, diag::err_realimag_invalid_type) << V->getType()
+    << (isReal ? "__real" : "__imag");
+  return QualType();
+}
+
+
+
+Action::OwningExprResult
+Sema::ActOnPostfixUnaryOp(Scope *S, SourceLocation OpLoc,
+                          tok::TokenKind Kind, ExprArg 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;
+  }
+
+  return BuildUnaryOp(S, OpLoc, Opc, move(Input));
+}
+
+Action::OwningExprResult
+Sema::ActOnArraySubscriptExpr(Scope *S, ExprArg Base, SourceLocation LLoc,
+                              ExprArg Idx, SourceLocation RLoc) {
+  // Since this might be a postfix expression, get rid of ParenListExprs.
+  Base = MaybeConvertParenListExprToParenExpr(S, move(Base));
+
+  Expr *LHSExp = static_cast<Expr*>(Base.get()),
+       *RHSExp = static_cast<Expr*>(Idx.get());
+
+  if (getLangOptions().CPlusPlus &&
+      (LHSExp->isTypeDependent() || RHSExp->isTypeDependent())) {
+    Base.release();
+    Idx.release();
+    return Owned(new (Context) ArraySubscriptExpr(LHSExp, RHSExp,
+                                                  Context.DependentTy, RLoc));
+  }
+
+  if (getLangOptions().CPlusPlus &&
+      (LHSExp->getType()->isRecordType() ||
+       LHSExp->getType()->isEnumeralType() ||
+       RHSExp->getType()->isRecordType() ||
+       RHSExp->getType()->isEnumeralType())) {
+    return CreateOverloadedArraySubscriptExpr(LLoc, RLoc, move(Base),move(Idx));
+  }
+
+  return CreateBuiltinArraySubscriptExpr(move(Base), LLoc, move(Idx), RLoc);
+}
+
+
+Action::OwningExprResult
+Sema::CreateBuiltinArraySubscriptExpr(ExprArg Base, SourceLocation LLoc,
+                                     ExprArg Idx, SourceLocation RLoc) {
+  Expr *LHSExp = static_cast<Expr*>(Base.get());
+  Expr *RHSExp = static_cast<Expr*>(Idx.get());
+
+  // Perform default conversions.
+  if (!LHSExp->getType()->getAs<VectorType>())
+      DefaultFunctionArrayLvalueConversion(LHSExp);
+  DefaultFunctionArrayLvalueConversion(RHSExp);
+
+  QualType LHSTy = LHSExp->getType(), RHSTy = RHSExp->getType();
+
+  // 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 ResultType;
+  if (LHSTy->isDependentType() || RHSTy->isDependentType()) {
+    BaseExpr = LHSExp;
+    IndexExpr = RHSExp;
+    ResultType = Context.DependentTy;
+  } else if (const PointerType *PTy = LHSTy->getAs<PointerType>()) {
+    BaseExpr = LHSExp;
+    IndexExpr = RHSExp;
+    ResultType = PTy->getPointeeType();
+  } else if (const PointerType *PTy = RHSTy->getAs<PointerType>()) {
+     // Handle the uncommon case of "123[Ptr]".
+    BaseExpr = RHSExp;
+    IndexExpr = LHSExp;
+    ResultType = PTy->getPointeeType();
+  } else if (const ObjCObjectPointerType *PTy =
+               LHSTy->getAs<ObjCObjectPointerType>()) {
+    BaseExpr = LHSExp;
+    IndexExpr = RHSExp;
+    ResultType = PTy->getPointeeType();
+  } else if (const ObjCObjectPointerType *PTy =
+               RHSTy->getAs<ObjCObjectPointerType>()) {
+     // Handle the uncommon case of "123[Ptr]".
+    BaseExpr = RHSExp;
+    IndexExpr = LHSExp;
+    ResultType = PTy->getPointeeType();
+  } else if (const VectorType *VTy = LHSTy->getAs<VectorType>()) {
+    BaseExpr = LHSExp;    // vectors: V[123]
+    IndexExpr = RHSExp;
+
+    // FIXME: need to deal with const...
+    ResultType = VTy->getElementType();
+  } else if (LHSTy->isArrayType()) {
+    // If we see an array that wasn't promoted by
+    // DefaultFunctionArrayLvalueConversion, it must be an array that
+    // wasn't promoted because of the C90 rule that doesn't
+    // allow promoting non-lvalue arrays.  Warn, then
+    // force the promotion here.
+    Diag(LHSExp->getLocStart(), diag::ext_subscript_non_lvalue) <<
+        LHSExp->getSourceRange();
+    ImpCastExprToType(LHSExp, Context.getArrayDecayedType(LHSTy),
+                      CastExpr::CK_ArrayToPointerDecay);
+    LHSTy = LHSExp->getType();
+
+    BaseExpr = LHSExp;
+    IndexExpr = RHSExp;
+    ResultType = LHSTy->getAs<PointerType>()->getPointeeType();
+  } else if (RHSTy->isArrayType()) {
+    // Same as previous, except for 123[f().a] case
+    Diag(RHSExp->getLocStart(), diag::ext_subscript_non_lvalue) <<
+        RHSExp->getSourceRange();
+    ImpCastExprToType(RHSExp, Context.getArrayDecayedType(RHSTy),
+                      CastExpr::CK_ArrayToPointerDecay);
+    RHSTy = RHSExp->getType();
+
+    BaseExpr = RHSExp;
+    IndexExpr = LHSExp;
+    ResultType = RHSTy->getAs<PointerType>()->getPointeeType();
+  } else {
+    return ExprError(Diag(LLoc, diag::err_typecheck_subscript_value)
+       << LHSExp->getSourceRange() << RHSExp->getSourceRange());
+  }
+  // C99 6.5.2.1p1
+  if (!(IndexExpr->getType()->isIntegerType() &&
+        IndexExpr->getType()->isScalarType()) && !IndexExpr->isTypeDependent())
+    return ExprError(Diag(LLoc, diag::err_typecheck_subscript_not_integer)
+                     << IndexExpr->getSourceRange());
+
+  if ((IndexExpr->getType()->isSpecificBuiltinType(BuiltinType::Char_S) ||
+       IndexExpr->getType()->isSpecificBuiltinType(BuiltinType::Char_U))
+         && !IndexExpr->isTypeDependent())
+    Diag(LLoc, diag::warn_subscript_is_char) << IndexExpr->getSourceRange();
+
+  // C99 6.5.2.1p1: "shall have type "pointer to *object* type". Similarly,
+  // C++ [expr.sub]p1: The type "T" shall be a completely-defined object
+  // type. Note that Functions are not objects, and that (in C99 parlance)
+  // incomplete types are not object types.
+  if (ResultType->isFunctionType()) {
+    Diag(BaseExpr->getLocStart(), diag::err_subscript_function_type)
+      << ResultType << BaseExpr->getSourceRange();
+    return ExprError();
+  }
+
+  if (!ResultType->isDependentType() &&
+      RequireCompleteType(LLoc, ResultType,
+                          PDiag(diag::err_subscript_incomplete_type)
+                            << BaseExpr->getSourceRange()))
+    return ExprError();
+
+  // Diagnose bad cases where we step over interface counts.
+  if (ResultType->isObjCInterfaceType() && LangOpts.ObjCNonFragileABI) {
+    Diag(LLoc, diag::err_subscript_nonfragile_interface)
+      << ResultType << BaseExpr->getSourceRange();
+    return ExprError();
+  }
+
+  Base.release();
+  Idx.release();
+  return Owned(new (Context) ArraySubscriptExpr(LHSExp, RHSExp,
+                                                ResultType, RLoc));
+}
+
+QualType Sema::
+CheckExtVectorComponent(QualType baseType, SourceLocation OpLoc,
+                        const IdentifierInfo *CompName,
+                        SourceLocation CompLoc) {
+  // FIXME: Share logic with ExtVectorElementExpr::containsDuplicateElements,
+  // see FIXME there.
+  //
+  // FIXME: This logic can be greatly simplified by splitting it along
+  // halving/not halving and reworking the component checking.
+  const ExtVectorType *vecType = baseType->getAs<ExtVectorType>();
+
+  // The vector accessor can't exceed the number of elements.
+  const char *compStr = CompName->getNameStart();
+
+  // This flag determines whether or not the component is one of the four
+  // special names that indicate a subset of exactly half the elements are
+  // to be selected.
+  bool HalvingSwizzle = false;
+
+  // This flag determines whether or not CompName has an 's' char prefix,
+  // indicating that it is a string of hex values to be used as vector indices.
+  bool HexSwizzle = *compStr == 's' || *compStr == 'S';
+
+  // Check that we've found one of the special components, or that the component
+  // names must come from the same set.
+  if (!strcmp(compStr, "hi") || !strcmp(compStr, "lo") ||
+      !strcmp(compStr, "even") || !strcmp(compStr, "odd")) {
+    HalvingSwizzle = true;
+  } else if (vecType->getPointAccessorIdx(*compStr) != -1) {
+    do
+      compStr++;
+    while (*compStr && vecType->getPointAccessorIdx(*compStr) != -1);
+  } else if (HexSwizzle || vecType->getNumericAccessorIdx(*compStr) != -1) {
+    do
+      compStr++;
+    while (*compStr && vecType->getNumericAccessorIdx(*compStr) != -1);
+  }
+
+  if (!HalvingSwizzle && *compStr) {
+    // We didn't get to the end of the string. This means the component names
+    // didn't come from the same set *or* we encountered an illegal name.
+    Diag(OpLoc, diag::err_ext_vector_component_name_illegal)
+      << std::string(compStr,compStr+1) << SourceRange(CompLoc);
+    return QualType();
+  }
+
+  // Ensure no component accessor exceeds the width of the vector type it
+  // operates on.
+  if (!HalvingSwizzle) {
+    compStr = CompName->getNameStart();
+
+    if (HexSwizzle)
+      compStr++;
+
+    while (*compStr) {
+      if (!vecType->isAccessorWithinNumElements(*compStr++)) {
+        Diag(OpLoc, diag::err_ext_vector_component_exceeds_length)
+          << baseType << SourceRange(CompLoc);
+        return QualType();
+      }
+    }
+  }
+
+  // The component accessor looks fine - now we need to compute the actual type.
+  // The vector type is implied by the component accessor. For example,
+  // vec4.b is a float, vec4.xy is a vec2, vec4.rgb is a vec3, etc.
+  // vec4.s0 is a float, vec4.s23 is a vec3, etc.
+  // vec4.hi, vec4.lo, vec4.e, and vec4.o all return vec2.
+  unsigned CompSize = HalvingSwizzle ? (vecType->getNumElements() + 1) / 2
+                                     : CompName->getLength();
+  if (HexSwizzle)
+    CompSize--;
+
+  if (CompSize == 1)
+    return vecType->getElementType();
+
+  QualType VT = Context.getExtVectorType(vecType->getElementType(), CompSize);
+  // Now look up the TypeDefDecl from the vector type. Without this,
+  // diagostics look bad. We want extended vector types to appear built-in.
+  for (unsigned i = 0, E = ExtVectorDecls.size(); i != E; ++i) {
+    if (ExtVectorDecls[i]->getUnderlyingType() == VT)
+      return Context.getTypedefType(ExtVectorDecls[i]);
+  }
+  return VT; // should never get here (a typedef type should always be found).
+}
+
+static Decl *FindGetterNameDeclFromProtocolList(const ObjCProtocolDecl*PDecl,
+                                                IdentifierInfo *Member,
+                                                const Selector &Sel,
+                                                ASTContext &Context) {
+
+  if (ObjCPropertyDecl *PD = PDecl->FindPropertyDeclaration(Member))
+    return PD;
+  if (ObjCMethodDecl *OMD = PDecl->getInstanceMethod(Sel))
+    return OMD;
+
+  for (ObjCProtocolDecl::protocol_iterator I = PDecl->protocol_begin(),
+       E = PDecl->protocol_end(); I != E; ++I) {
+    if (Decl *D = FindGetterNameDeclFromProtocolList(*I, Member, Sel,
+                                                     Context))
+      return D;
+  }
+  return 0;
+}
+
+static Decl *FindGetterNameDecl(const ObjCObjectPointerType *QIdTy,
+                                IdentifierInfo *Member,
+                                const Selector &Sel,
+                                ASTContext &Context) {
+  // Check protocols on qualified interfaces.
+  Decl *GDecl = 0;
+  for (ObjCObjectPointerType::qual_iterator I = QIdTy->qual_begin(),
+       E = QIdTy->qual_end(); I != E; ++I) {
+    if (ObjCPropertyDecl *PD = (*I)->FindPropertyDeclaration(Member)) {
+      GDecl = PD;
+      break;
+    }
+    // Also must look for a getter name which uses property syntax.
+    if (ObjCMethodDecl *OMD = (*I)->getInstanceMethod(Sel)) {
+      GDecl = OMD;
+      break;
+    }
+  }
+  if (!GDecl) {
+    for (ObjCObjectPointerType::qual_iterator I = QIdTy->qual_begin(),
+         E = QIdTy->qual_end(); I != E; ++I) {
+      // Search in the protocol-qualifier list of current protocol.
+      GDecl = FindGetterNameDeclFromProtocolList(*I, Member, Sel, Context);
+      if (GDecl)
+        return GDecl;
+    }
+  }
+  return GDecl;
+}
+
+Sema::OwningExprResult
+Sema::ActOnDependentMemberExpr(ExprArg Base, QualType BaseType,
+                               bool IsArrow, SourceLocation OpLoc,
+                               const CXXScopeSpec &SS,
+                               NamedDecl *FirstQualifierInScope,
+                               DeclarationName Name, SourceLocation NameLoc,
+                               const TemplateArgumentListInfo *TemplateArgs) {
+  Expr *BaseExpr = Base.takeAs<Expr>();
+
+  // Even in dependent contexts, try to diagnose base expressions with
+  // obviously wrong types, e.g.:
+  //
+  // T* t;
+  // t.f;
+  //
+  // In Obj-C++, however, the above expression is valid, since it could be
+  // accessing the 'f' property if T is an Obj-C interface. The extra check
+  // allows this, while still reporting an error if T is a struct pointer.
+  if (!IsArrow) {
+    const PointerType *PT = BaseType->getAs<PointerType>();
+    if (PT && (!getLangOptions().ObjC1 ||
+               PT->getPointeeType()->isRecordType())) {
+      assert(BaseExpr && "cannot happen with implicit member accesses");
+      Diag(NameLoc, diag::err_typecheck_member_reference_struct_union)
+        << BaseType << BaseExpr->getSourceRange();
+      return ExprError();
+    }
+  }
+
+  assert(BaseType->isDependentType() || Name.isDependentName());
+
+  // Get the type being accessed in BaseType.  If this is an arrow, the BaseExpr
+  // must have pointer type, and the accessed type is the pointee.
+  return Owned(CXXDependentScopeMemberExpr::Create(Context, BaseExpr, BaseType,
+                                                   IsArrow, OpLoc,
+                 static_cast<NestedNameSpecifier*>(SS.getScopeRep()),
+                                                   SS.getRange(),
+                                                   FirstQualifierInScope,
+                                                   Name, NameLoc,
+                                                   TemplateArgs));
+}
+
+/// We know that the given qualified member reference points only to
+/// declarations which do not belong to the static type of the base
+/// expression.  Diagnose the problem.
+static void DiagnoseQualifiedMemberReference(Sema &SemaRef,
+                                             Expr *BaseExpr,
+                                             QualType BaseType,
+                                             const CXXScopeSpec &SS,
+                                             const LookupResult &R) {
+  // If this is an implicit member access, use a different set of
+  // diagnostics.
+  if (!BaseExpr)
+    return DiagnoseInstanceReference(SemaRef, SS, R);
+
+  // FIXME: this is an exceedingly lame diagnostic for some of the more
+  // complicated cases here.
+  DeclContext *DC = R.getRepresentativeDecl()->getDeclContext();
+  SemaRef.Diag(R.getNameLoc(), diag::err_not_direct_base_or_virtual)
+    << SS.getRange() << DC << BaseType;
+}
+
+// Check whether the declarations we found through a nested-name
+// specifier in a member expression are actually members of the base
+// type.  The restriction here is:
+//
+//   C++ [expr.ref]p2:
+//     ... In these cases, the id-expression shall name a
+//     member of the class or of one of its base classes.
+//
+// So it's perfectly legitimate for the nested-name specifier to name
+// an unrelated class, and for us to find an overload set including
+// decls from classes which are not superclasses, as long as the decl
+// we actually pick through overload resolution is from a superclass.
+bool Sema::CheckQualifiedMemberReference(Expr *BaseExpr,
+                                         QualType BaseType,
+                                         const CXXScopeSpec &SS,
+                                         const LookupResult &R) {
+  const RecordType *BaseRT = BaseType->getAs<RecordType>();
+  if (!BaseRT) {
+    // We can't check this yet because the base type is still
+    // dependent.
+    assert(BaseType->isDependentType());
+    return false;
+  }
+  CXXRecordDecl *BaseRecord = cast<CXXRecordDecl>(BaseRT->getDecl());
+
+  for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I) {
+    // If this is an implicit member reference and we find a
+    // non-instance member, it's not an error.
+    if (!BaseExpr && !IsInstanceMember((*I)->getUnderlyingDecl()))
+      return false;
+
+    // Note that we use the DC of the decl, not the underlying decl.
+    CXXRecordDecl *RecordD = cast<CXXRecordDecl>((*I)->getDeclContext());
+    while (RecordD->isAnonymousStructOrUnion())
+      RecordD = cast<CXXRecordDecl>(RecordD->getParent());
+
+    llvm::SmallPtrSet<CXXRecordDecl*,4> MemberRecord;
+    MemberRecord.insert(RecordD->getCanonicalDecl());
+
+    if (!IsProvablyNotDerivedFrom(*this, BaseRecord, MemberRecord))
+      return false;
+  }
+
+  DiagnoseQualifiedMemberReference(*this, BaseExpr, BaseType, SS, R);
+  return true;
+}
+
+static bool
+LookupMemberExprInRecord(Sema &SemaRef, LookupResult &R,
+                         SourceRange BaseRange, const RecordType *RTy,
+                         SourceLocation OpLoc, const CXXScopeSpec &SS) {
+  RecordDecl *RDecl = RTy->getDecl();
+  if (SemaRef.RequireCompleteType(OpLoc, QualType(RTy, 0),
+                                  PDiag(diag::err_typecheck_incomplete_tag)
+                                    << BaseRange))
+    return true;
+
+  DeclContext *DC = RDecl;
+  if (SS.isSet()) {
+    // If the member name was a qualified-id, look into the
+    // nested-name-specifier.
+    DC = SemaRef.computeDeclContext(SS, false);
+
+    if (SemaRef.RequireCompleteDeclContext(SS)) {
+      SemaRef.Diag(SS.getRange().getEnd(), diag::err_typecheck_incomplete_tag)
+        << SS.getRange() << DC;
+      return true;
+    }
+
+    assert(DC && "Cannot handle non-computable dependent contexts in lookup");
+      
+    if (!isa<TypeDecl>(DC)) {
+      SemaRef.Diag(R.getNameLoc(), diag::err_qualified_member_nonclass)
+        << DC << SS.getRange();
+      return true;
+    }
+  }
+
+  // The record definition is complete, now look up the member.
+  SemaRef.LookupQualifiedName(R, DC);
+
+  if (!R.empty())
+    return false;
+
+  // We didn't find anything with the given name, so try to correct
+  // for typos.
+  DeclarationName Name = R.getLookupName();
+  if (SemaRef.CorrectTypo(R, 0, &SS, DC) && 
+      (isa<ValueDecl>(*R.begin()) || isa<FunctionTemplateDecl>(*R.begin()))) {
+    SemaRef.Diag(R.getNameLoc(), diag::err_no_member_suggest)
+      << Name << DC << R.getLookupName() << SS.getRange()
+      << CodeModificationHint::CreateReplacement(R.getNameLoc(),
+                                         R.getLookupName().getAsString());
+    if (NamedDecl *ND = R.getAsSingle<NamedDecl>())
+      SemaRef.Diag(ND->getLocation(), diag::note_previous_decl)
+        << ND->getDeclName();
+    return false;
+  } else {
+    R.clear();
+  }
+
+  return false;
+}
+
+Sema::OwningExprResult
+Sema::BuildMemberReferenceExpr(ExprArg BaseArg, QualType BaseType,
+                               SourceLocation OpLoc, bool IsArrow,
+                               const CXXScopeSpec &SS,
+                               NamedDecl *FirstQualifierInScope,
+                               DeclarationName Name, SourceLocation NameLoc,
+                               const TemplateArgumentListInfo *TemplateArgs) {
+  Expr *Base = BaseArg.takeAs<Expr>();
+
+  if (BaseType->isDependentType() ||
+      (SS.isSet() && isDependentScopeSpecifier(SS)))
+    return ActOnDependentMemberExpr(ExprArg(*this, Base), BaseType,
+                                    IsArrow, OpLoc,
+                                    SS, FirstQualifierInScope,
+                                    Name, NameLoc,
+                                    TemplateArgs);
+
+  LookupResult R(*this, Name, NameLoc, LookupMemberName);
+
+  // Implicit member accesses.
+  if (!Base) {
+    QualType RecordTy = BaseType;
+    if (IsArrow) RecordTy = RecordTy->getAs<PointerType>()->getPointeeType();
+    if (LookupMemberExprInRecord(*this, R, SourceRange(),
+                                 RecordTy->getAs<RecordType>(),
+                                 OpLoc, SS))
+      return ExprError();
+
+  // Explicit member accesses.
+  } else {
+    OwningExprResult Result =
+      LookupMemberExpr(R, Base, IsArrow, OpLoc,
+                       SS, /*ObjCImpDecl*/ DeclPtrTy());
+
+    if (Result.isInvalid()) {
+      Owned(Base);
+      return ExprError();
+    }
+
+    if (Result.get())
+      return move(Result);
+  }
+
+  return BuildMemberReferenceExpr(ExprArg(*this, Base), BaseType,
+                                  OpLoc, IsArrow, SS, FirstQualifierInScope,
+                                  R, TemplateArgs);
+}
+
+Sema::OwningExprResult
+Sema::BuildMemberReferenceExpr(ExprArg Base, QualType BaseExprType,
+                               SourceLocation OpLoc, bool IsArrow,
+                               const CXXScopeSpec &SS,
+                               NamedDecl *FirstQualifierInScope,
+                               LookupResult &R,
+                         const TemplateArgumentListInfo *TemplateArgs) {
+  Expr *BaseExpr = Base.takeAs<Expr>();
+  QualType BaseType = BaseExprType;
+  if (IsArrow) {
+    assert(BaseType->isPointerType());
+    BaseType = BaseType->getAs<PointerType>()->getPointeeType();
+  }
+
+  NestedNameSpecifier *Qualifier =
+    static_cast<NestedNameSpecifier*>(SS.getScopeRep());
+  DeclarationName MemberName = R.getLookupName();
+  SourceLocation MemberLoc = R.getNameLoc();
+
+  if (R.isAmbiguous())
+    return ExprError();
+
+  if (R.empty()) {
+    // Rederive where we looked up.
+    DeclContext *DC = (SS.isSet()
+                       ? computeDeclContext(SS, false)
+                       : BaseType->getAs<RecordType>()->getDecl());
+
+    Diag(R.getNameLoc(), diag::err_no_member)
+      << MemberName << DC
+      << (BaseExpr ? BaseExpr->getSourceRange() : SourceRange());
+    return ExprError();
+  }
+
+  // Diagnose lookups that find only declarations from a non-base
+  // type.  This is possible for either qualified lookups (which may
+  // have been qualified with an unrelated type) or implicit member
+  // expressions (which were found with unqualified lookup and thus
+  // may have come from an enclosing scope).  Note that it's okay for
+  // lookup to find declarations from a non-base type as long as those
+  // aren't the ones picked by overload resolution.
+  if ((SS.isSet() || !BaseExpr ||
+       (isa<CXXThisExpr>(BaseExpr) &&
+        cast<CXXThisExpr>(BaseExpr)->isImplicit())) &&
+      CheckQualifiedMemberReference(BaseExpr, BaseType, SS, R))
+    return ExprError();
+
+  // Construct an unresolved result if we in fact got an unresolved
+  // result.
+  if (R.isOverloadedResult() || R.isUnresolvableResult()) {
+    bool Dependent =
+      BaseExprType->isDependentType() ||
+      R.isUnresolvableResult() ||
+      OverloadExpr::ComputeDependence(R.begin(), R.end(), TemplateArgs);
+
+    // Suppress any lookup-related diagnostics; we'll do these when we
+    // pick a member.
+    R.suppressDiagnostics();
+
+    UnresolvedMemberExpr *MemExpr
+      = UnresolvedMemberExpr::Create(Context, Dependent,
+                                     R.isUnresolvableResult(),
+                                     BaseExpr, BaseExprType,
+                                     IsArrow, OpLoc,
+                                     Qualifier, SS.getRange(),
+                                     MemberName, MemberLoc,
+                                     TemplateArgs);
+    MemExpr->addDecls(R.begin(), R.end());
+
+    return Owned(MemExpr);
+  }
+
+  assert(R.isSingleResult());  
+  NamedDecl *MemberDecl = R.getFoundDecl();
+
+  // FIXME: diagnose the presence of template arguments now.
+
+  // If the decl being referenced had an error, return an error for this
+  // sub-expr without emitting another error, in order to avoid cascading
+  // error cases.
+  if (MemberDecl->isInvalidDecl())
+    return ExprError();
+
+  // Handle the implicit-member-access case.
+  if (!BaseExpr) {
+    // If this is not an instance member, convert to a non-member access.
+    if (!IsInstanceMember(MemberDecl))
+      return BuildDeclarationNameExpr(SS, R.getNameLoc(), MemberDecl);
+
+    SourceLocation Loc = R.getNameLoc();
+    if (SS.getRange().isValid())
+      Loc = SS.getRange().getBegin();
+    BaseExpr = new (Context) CXXThisExpr(Loc, BaseExprType,/*isImplicit=*/true);
+  }
+
+  bool ShouldCheckUse = true;
+  if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(MemberDecl)) {
+    // Don't diagnose the use of a virtual member function unless it's
+    // explicitly qualified.
+    if (MD->isVirtual() && !SS.isSet())
+      ShouldCheckUse = false;
+  }
+
+  // Check the use of this member.
+  if (ShouldCheckUse && DiagnoseUseOfDecl(MemberDecl, MemberLoc)) {
+    Owned(BaseExpr);
+    return ExprError();
+  }
+
+  if (FieldDecl *FD = dyn_cast<FieldDecl>(MemberDecl)) {
+    // We may have found a field within an anonymous union or struct
+    // (C++ [class.union]).
+    if (cast<RecordDecl>(FD->getDeclContext())->isAnonymousStructOrUnion() &&
+        !BaseType->getAs<RecordType>()->getDecl()->isAnonymousStructOrUnion())
+      return BuildAnonymousStructUnionMemberReference(MemberLoc, FD,
+                                                      BaseExpr, OpLoc);
+
+    // Figure out the type of the member; see C99 6.5.2.3p3, C++ [expr.ref]
+    QualType MemberType = FD->getType();
+    if (const ReferenceType *Ref = MemberType->getAs<ReferenceType>())
+      MemberType = Ref->getPointeeType();
+    else {
+      Qualifiers BaseQuals = BaseType.getQualifiers();
+      BaseQuals.removeObjCGCAttr();
+      if (FD->isMutable()) BaseQuals.removeConst();
+
+      Qualifiers MemberQuals
+        = Context.getCanonicalType(MemberType).getQualifiers();
+
+      Qualifiers Combined = BaseQuals + MemberQuals;
+      if (Combined != MemberQuals)
+        MemberType = Context.getQualifiedType(MemberType, Combined);
+    }
+
+    MarkDeclarationReferenced(MemberLoc, FD);
+    if (PerformObjectMemberConversion(BaseExpr, FD))
+      return ExprError();
+    return Owned(BuildMemberExpr(Context, BaseExpr, IsArrow, SS,
+                                 FD, MemberLoc, MemberType));
+  }
+
+  if (VarDecl *Var = dyn_cast<VarDecl>(MemberDecl)) {
+    MarkDeclarationReferenced(MemberLoc, Var);
+    return Owned(BuildMemberExpr(Context, BaseExpr, IsArrow, SS,
+                                 Var, MemberLoc,
+                                 Var->getType().getNonReferenceType()));
+  }
+
+  if (FunctionDecl *MemberFn = dyn_cast<FunctionDecl>(MemberDecl)) {
+    MarkDeclarationReferenced(MemberLoc, MemberDecl);
+    return Owned(BuildMemberExpr(Context, BaseExpr, IsArrow, SS,
+                                 MemberFn, MemberLoc,
+                                 MemberFn->getType()));
+  }
+
+  if (EnumConstantDecl *Enum = dyn_cast<EnumConstantDecl>(MemberDecl)) {
+    MarkDeclarationReferenced(MemberLoc, MemberDecl);
+    return Owned(BuildMemberExpr(Context, BaseExpr, IsArrow, SS,
+                                 Enum, MemberLoc, Enum->getType()));
+  }
+
+  Owned(BaseExpr);
+
+  if (isa<TypeDecl>(MemberDecl))
+    return ExprError(Diag(MemberLoc,diag::err_typecheck_member_reference_type)
+                     << MemberName << int(IsArrow));
+
+  // We found a declaration kind that we didn't expect. This is a
+  // generic error message that tells the user that she can't refer
+  // to this member with '.' or '->'.
+  return ExprError(Diag(MemberLoc,
+                        diag::err_typecheck_member_reference_unknown)
+      << MemberName << int(IsArrow));
+}
+
+/// Look up the given member of the given non-type-dependent
+/// expression.  This can return in one of two ways:
+///  * If it returns a sentinel null-but-valid result, the caller will
+///    assume that lookup was performed and the results written into
+///    the provided structure.  It will take over from there.
+///  * Otherwise, the returned expression will be produced in place of
+///    an ordinary member expression.
+///
+/// The ObjCImpDecl bit is a gross hack that will need to be properly
+/// fixed for ObjC++.
+Sema::OwningExprResult
+Sema::LookupMemberExpr(LookupResult &R, Expr *&BaseExpr,
+                       bool &IsArrow, SourceLocation OpLoc,
+                       const CXXScopeSpec &SS,
+                       DeclPtrTy ObjCImpDecl) {
+  assert(BaseExpr && "no base expression");
+
+  // Perform default conversions.
+  DefaultFunctionArrayConversion(BaseExpr);
+
+  QualType BaseType = BaseExpr->getType();
+  assert(!BaseType->isDependentType());
+
+  DeclarationName MemberName = R.getLookupName();
+  SourceLocation MemberLoc = R.getNameLoc();
+
+  // If the user is trying to apply -> or . to a function pointer
+  // type, it's probably because they forgot parentheses to call that
+  // function. Suggest the addition of those parentheses, build the
+  // call, and continue on.
+  if (const PointerType *Ptr = BaseType->getAs<PointerType>()) {
+    if (const FunctionProtoType *Fun
+          = Ptr->getPointeeType()->getAs<FunctionProtoType>()) {
+      QualType ResultTy = Fun->getResultType();
+      if (Fun->getNumArgs() == 0 &&
+          ((!IsArrow && ResultTy->isRecordType()) ||
+           (IsArrow && ResultTy->isPointerType() &&
+            ResultTy->getAs<PointerType>()->getPointeeType()
+                                                          ->isRecordType()))) {
+        SourceLocation Loc = PP.getLocForEndOfToken(BaseExpr->getLocEnd());
+        Diag(Loc, diag::err_member_reference_needs_call)
+          << QualType(Fun, 0)
+          << CodeModificationHint::CreateInsertion(Loc, "()");
+        
+        OwningExprResult NewBase
+          = ActOnCallExpr(0, ExprArg(*this, BaseExpr), Loc, 
+                          MultiExprArg(*this, 0, 0), 0, Loc);
+        if (NewBase.isInvalid())
+          return ExprError();
+        
+        BaseExpr = NewBase.takeAs<Expr>();
+        DefaultFunctionArrayConversion(BaseExpr);
+        BaseType = BaseExpr->getType();
+      }
+    }
+  }
+
+  // If this is an Objective-C pseudo-builtin and a definition is provided then
+  // use that.
+  if (BaseType->isObjCIdType()) {
+    if (IsArrow) {
+      // Handle the following exceptional case PObj->isa.
+      if (const ObjCObjectPointerType *OPT =
+          BaseType->getAs<ObjCObjectPointerType>()) {
+        if (OPT->getPointeeType()->isSpecificBuiltinType(BuiltinType::ObjCId) &&
+            MemberName.getAsIdentifierInfo()->isStr("isa"))
+          return Owned(new (Context) ObjCIsaExpr(BaseExpr, true, MemberLoc,
+                                                 Context.getObjCClassType()));
+      }
+    }
+    // We have an 'id' type. Rather than fall through, we check if this
+    // is a reference to 'isa'.
+    if (BaseType != Context.ObjCIdRedefinitionType) {
+      BaseType = Context.ObjCIdRedefinitionType;
+      ImpCastExprToType(BaseExpr, BaseType, CastExpr::CK_BitCast);
+    }
+  }
+
+  // If this is an Objective-C pseudo-builtin and a definition is provided then
+  // use that.
+  if (Context.isObjCSelType(BaseType)) {
+    // We have an 'SEL' type. Rather than fall through, we check if this
+    // is a reference to 'sel_id'.
+    if (BaseType != Context.ObjCSelRedefinitionType) {
+      BaseType = Context.ObjCSelRedefinitionType;
+      ImpCastExprToType(BaseExpr, BaseType, CastExpr::CK_BitCast);
+    }
+  }
+
+  assert(!BaseType.isNull() && "no type for member expression");
+
+  // Handle properties on ObjC 'Class' types.
+  if (!IsArrow && BaseType->isObjCClassType()) {
+    // Also must look for a getter name which uses property syntax.
+    IdentifierInfo *Member = MemberName.getAsIdentifierInfo();
+    Selector Sel = PP.getSelectorTable().getNullarySelector(Member);
+    if (ObjCMethodDecl *MD = getCurMethodDecl()) {
+      ObjCInterfaceDecl *IFace = MD->getClassInterface();
+      ObjCMethodDecl *Getter;
+      // FIXME: need to also look locally in the implementation.
+      if ((Getter = IFace->lookupClassMethod(Sel))) {
+        // Check the use of this method.
+        if (DiagnoseUseOfDecl(Getter, MemberLoc))
+          return ExprError();
+      }
+      // If we found a getter then this may be a valid dot-reference, we
+      // will look for the matching setter, in case it is needed.
+      Selector SetterSel =
+      SelectorTable::constructSetterName(PP.getIdentifierTable(),
+                                         PP.getSelectorTable(), Member);
+      ObjCMethodDecl *Setter = IFace->lookupClassMethod(SetterSel);
+      if (!Setter) {
+        // If this reference is in an @implementation, also check for 'private'
+        // methods.
+        Setter = IFace->lookupPrivateInstanceMethod(SetterSel);
+      }
+      // Look through local category implementations associated with the class.
+      if (!Setter)
+        Setter = IFace->getCategoryClassMethod(SetterSel);
+      
+      if (Setter && DiagnoseUseOfDecl(Setter, MemberLoc))
+        return ExprError();
+      
+      if (Getter || Setter) {
+        QualType PType;
+        
+        if (Getter)
+          PType = Getter->getResultType();
+        else
+          // Get the expression type from Setter's incoming parameter.
+          PType = (*(Setter->param_end() -1))->getType();
+        // FIXME: we must check that the setter has property type.
+        return Owned(new (Context) ObjCImplicitSetterGetterRefExpr(Getter, 
+                                                  PType,
+                                                  Setter, MemberLoc, BaseExpr));
+      }
+      return ExprError(Diag(MemberLoc, diag::err_property_not_found)
+                       << MemberName << BaseType);
+    }
+  }
+  
+  if (BaseType->isObjCClassType() &&
+      BaseType != Context.ObjCClassRedefinitionType) {
+    BaseType = Context.ObjCClassRedefinitionType;
+    ImpCastExprToType(BaseExpr, BaseType, CastExpr::CK_BitCast);
+  }
+
+  if (IsArrow) {
+    if (const PointerType *PT = BaseType->getAs<PointerType>())
+      BaseType = PT->getPointeeType();
+    else if (BaseType->isObjCObjectPointerType())
+      ;
+    else if (BaseType->isRecordType()) {
+      // Recover from arrow accesses to records, e.g.:
+      //   struct MyRecord foo;
+      //   foo->bar
+      // This is actually well-formed in C++ if MyRecord has an
+      // overloaded operator->, but that should have been dealt with
+      // by now.
+      Diag(OpLoc, diag::err_typecheck_member_reference_suggestion)
+        << BaseType << int(IsArrow) << BaseExpr->getSourceRange()
+        << CodeModificationHint::CreateReplacement(OpLoc, ".");
+      IsArrow = false;
+    } else {
+      Diag(MemberLoc, diag::err_typecheck_member_reference_arrow)
+        << BaseType << BaseExpr->getSourceRange();
+      return ExprError();
+    }
+  } else {
+    // Recover from dot accesses to pointers, e.g.:
+    //   type *foo;
+    //   foo.bar
+    // This is actually well-formed in two cases:
+    //   - 'type' is an Objective C type
+    //   - 'bar' is a pseudo-destructor name which happens to refer to
+    //     the appropriate pointer type
+    if (MemberName.getNameKind() != DeclarationName::CXXDestructorName) {
+      const PointerType *PT = BaseType->getAs<PointerType>();
+      if (PT && PT->getPointeeType()->isRecordType()) {
+        Diag(OpLoc, diag::err_typecheck_member_reference_suggestion)
+          << BaseType << int(IsArrow) << BaseExpr->getSourceRange()
+          << CodeModificationHint::CreateReplacement(OpLoc, "->");
+        BaseType = PT->getPointeeType();
+        IsArrow = true;
+      }
+    }
+  }
+  
+  // Handle field access to simple records.  This also handles access
+  // to fields of the ObjC 'id' struct.
+  if (const RecordType *RTy = BaseType->getAs<RecordType>()) {
+    if (LookupMemberExprInRecord(*this, R, BaseExpr->getSourceRange(),
+                                 RTy, OpLoc, SS))
+      return ExprError();
+    return Owned((Expr*) 0);
+  }
+
+  // Handle pseudo-destructors (C++ [expr.pseudo]). Since anything referring
+  // into a record type was handled above, any destructor we see here is a
+  // pseudo-destructor.
+  if (MemberName.getNameKind() == DeclarationName::CXXDestructorName) {
+    // C++ [expr.pseudo]p2:
+    //   The left hand side of the dot operator shall be of scalar type. The
+    //   left hand side of the arrow operator shall be of pointer to scalar
+    //   type.
+    if (!BaseType->isScalarType())
+      return Owned(Diag(OpLoc, diag::err_pseudo_dtor_base_not_scalar)
+                     << BaseType << BaseExpr->getSourceRange());
+
+    //   [...] The type designated by the pseudo-destructor-name shall be the
+    //   same as the object type.
+    if (!MemberName.getCXXNameType()->isDependentType() &&
+        !Context.hasSameUnqualifiedType(BaseType, MemberName.getCXXNameType()))
+      return Owned(Diag(OpLoc, diag::err_pseudo_dtor_type_mismatch)
+                     << BaseType << MemberName.getCXXNameType()
+                     << BaseExpr->getSourceRange() << SourceRange(MemberLoc));
+
+    //   [...] Furthermore, the two type-names in a pseudo-destructor-name of
+    //   the form
+    //
+    //       ::[opt] nested-name-specifier[opt] type-name ::  ̃ type-name
+    //
+    //   shall designate the same scalar type.
+    //
+    // FIXME: DPG can't see any way to trigger this particular clause, so it
+    // isn't checked here.
+
+    // FIXME: We've lost the precise spelling of the type by going through
+    // DeclarationName. Can we do better?
+    return Owned(new (Context) CXXPseudoDestructorExpr(Context, BaseExpr,
+                                                       IsArrow, OpLoc,
+                               (NestedNameSpecifier *) SS.getScopeRep(),
+                                                       SS.getRange(),
+                                                   MemberName.getCXXNameType(),
+                                                       MemberLoc));
+  }
+
+  // Handle access to Objective-C instance variables, such as "Obj->ivar" and
+  // (*Obj).ivar.
+  if ((IsArrow && BaseType->isObjCObjectPointerType()) ||
+      (!IsArrow && BaseType->isObjCInterfaceType())) {
+    const ObjCObjectPointerType *OPT = BaseType->getAs<ObjCObjectPointerType>();
+    const ObjCInterfaceType *IFaceT =
+      OPT ? OPT->getInterfaceType() : BaseType->getAs<ObjCInterfaceType>();
+    if (IFaceT) {
+      IdentifierInfo *Member = MemberName.getAsIdentifierInfo();
+
+      ObjCInterfaceDecl *IDecl = IFaceT->getDecl();
+      ObjCInterfaceDecl *ClassDeclared;
+      ObjCIvarDecl *IV = IDecl->lookupInstanceVariable(Member, ClassDeclared);
+
+      if (!IV) {
+        // Attempt to correct for typos in ivar names.
+        LookupResult Res(*this, R.getLookupName(), R.getNameLoc(),
+                         LookupMemberName);
+        if (CorrectTypo(Res, 0, 0, IDecl) &&
+            (IV = Res.getAsSingle<ObjCIvarDecl>())) {
+          Diag(R.getNameLoc(), 
+               diag::err_typecheck_member_reference_ivar_suggest)
+            << IDecl->getDeclName() << MemberName << IV->getDeclName()
+            << CodeModificationHint::CreateReplacement(R.getNameLoc(),
+                                                       IV->getNameAsString());
+          Diag(IV->getLocation(), diag::note_previous_decl)
+            << IV->getDeclName();          
+        }
+      }
+
+      if (IV) {
+        // If the decl being referenced had an error, return an error for this
+        // sub-expr without emitting another error, in order to avoid cascading
+        // error cases.
+        if (IV->isInvalidDecl())
+          return ExprError();
+
+        // Check whether we can reference this field.
+        if (DiagnoseUseOfDecl(IV, MemberLoc))
+          return ExprError();
+        if (IV->getAccessControl() != ObjCIvarDecl::Public &&
+            IV->getAccessControl() != ObjCIvarDecl::Package) {
+          ObjCInterfaceDecl *ClassOfMethodDecl = 0;
+          if (ObjCMethodDecl *MD = getCurMethodDecl())
+            ClassOfMethodDecl =  MD->getClassInterface();
+          else if (ObjCImpDecl && getCurFunctionDecl()) {
+            // Case of a c-function declared inside an objc implementation.
+            // FIXME: For a c-style function nested inside an objc implementation
+            // class, there is no implementation context available, so we pass
+            // down the context as argument to this routine. Ideally, this context
+            // need be passed down in the AST node and somehow calculated from the
+            // AST for a function decl.
+            Decl *ImplDecl = ObjCImpDecl.getAs<Decl>();
+            if (ObjCImplementationDecl *IMPD =
+                dyn_cast<ObjCImplementationDecl>(ImplDecl))
+              ClassOfMethodDecl = IMPD->getClassInterface();
+            else if (ObjCCategoryImplDecl* CatImplClass =
+                        dyn_cast<ObjCCategoryImplDecl>(ImplDecl))
+              ClassOfMethodDecl = CatImplClass->getClassInterface();
+          }
+
+          if (IV->getAccessControl() == ObjCIvarDecl::Private) {
+            if (ClassDeclared != IDecl ||
+                ClassOfMethodDecl != ClassDeclared)
+              Diag(MemberLoc, diag::error_private_ivar_access)
+                << IV->getDeclName();
+          } else if (!IDecl->isSuperClassOf(ClassOfMethodDecl))
+            // @protected
+            Diag(MemberLoc, diag::error_protected_ivar_access)
+              << IV->getDeclName();
+        }
+
+        return Owned(new (Context) ObjCIvarRefExpr(IV, IV->getType(),
+                                                   MemberLoc, BaseExpr,
+                                                   IsArrow));
+      }
+      return ExprError(Diag(MemberLoc, diag::err_typecheck_member_reference_ivar)
+                         << IDecl->getDeclName() << MemberName
+                         << BaseExpr->getSourceRange());
+    }
+  }
+  // Handle properties on 'id' and qualified "id".
+  if (!IsArrow && (BaseType->isObjCIdType() ||
+                   BaseType->isObjCQualifiedIdType())) {
+    const ObjCObjectPointerType *QIdTy = BaseType->getAs<ObjCObjectPointerType>();
+    IdentifierInfo *Member = MemberName.getAsIdentifierInfo();
+
+    // Check protocols on qualified interfaces.
+    Selector Sel = PP.getSelectorTable().getNullarySelector(Member);
+    if (Decl *PMDecl = FindGetterNameDecl(QIdTy, Member, Sel, Context)) {
+      if (ObjCPropertyDecl *PD = dyn_cast<ObjCPropertyDecl>(PMDecl)) {
+        // Check the use of this declaration
+        if (DiagnoseUseOfDecl(PD, MemberLoc))
+          return ExprError();
+
+        return Owned(new (Context) ObjCPropertyRefExpr(PD, PD->getType(),
+                                                       MemberLoc, BaseExpr));
+      }
+      if (ObjCMethodDecl *OMD = dyn_cast<ObjCMethodDecl>(PMDecl)) {
+        // Check the use of this method.
+        if (DiagnoseUseOfDecl(OMD, MemberLoc))
+          return ExprError();
+
+        return Owned(new (Context) ObjCMessageExpr(BaseExpr, Sel,
+                                                   OMD->getResultType(),
+                                                   OMD, OpLoc, MemberLoc,
+                                                   NULL, 0));
+      }
+    }
+
+    return ExprError(Diag(MemberLoc, diag::err_property_not_found)
+                       << MemberName << BaseType);
+  }
+  // Handle Objective-C property access, which is "Obj.property" where Obj is a
+  // pointer to a (potentially qualified) interface type.
+  const ObjCObjectPointerType *OPT;
+  if (!IsArrow && (OPT = BaseType->getAsObjCInterfacePointerType())) {
+    const ObjCInterfaceType *IFaceT = OPT->getInterfaceType();
+    ObjCInterfaceDecl *IFace = IFaceT->getDecl();
+    IdentifierInfo *Member = MemberName.getAsIdentifierInfo();
+
+    // Search for a declared property first.
+    if (ObjCPropertyDecl *PD = IFace->FindPropertyDeclaration(Member)) {
+      // Check whether we can reference this property.
+      if (DiagnoseUseOfDecl(PD, MemberLoc))
+        return ExprError();
+      QualType ResTy = PD->getType();
+      Selector Sel = PP.getSelectorTable().getNullarySelector(Member);
+      ObjCMethodDecl *Getter = IFace->lookupInstanceMethod(Sel);
+      if (DiagnosePropertyAccessorMismatch(PD, Getter, MemberLoc))
+        ResTy = Getter->getResultType();
+      return Owned(new (Context) ObjCPropertyRefExpr(PD, ResTy,
+                                                     MemberLoc, BaseExpr));
+    }
+    // Check protocols on qualified interfaces.
+    for (ObjCObjectPointerType::qual_iterator I = OPT->qual_begin(),
+         E = OPT->qual_end(); I != E; ++I)
+      if (ObjCPropertyDecl *PD = (*I)->FindPropertyDeclaration(Member)) {
+        // Check whether we can reference this property.
+        if (DiagnoseUseOfDecl(PD, MemberLoc))
+          return ExprError();
+
+        return Owned(new (Context) ObjCPropertyRefExpr(PD, PD->getType(),
+                                                       MemberLoc, BaseExpr));
+      }
+    // If that failed, look for an "implicit" property by seeing if the nullary
+    // selector is implemented.
+
+    // FIXME: The logic for looking up nullary and unary selectors should be
+    // shared with the code in ActOnInstanceMessage.
+
+    Selector Sel = PP.getSelectorTable().getNullarySelector(Member);
+    ObjCMethodDecl *Getter = IFace->lookupInstanceMethod(Sel);
+
+    // If this reference is in an @implementation, check for 'private' methods.
+    if (!Getter)
+      Getter = IFace->lookupPrivateInstanceMethod(Sel);
+
+    // Look through local category implementations associated with the class.
+    if (!Getter)
+      Getter = IFace->getCategoryInstanceMethod(Sel);
+    if (Getter) {
+      // Check if we can reference this property.
+      if (DiagnoseUseOfDecl(Getter, MemberLoc))
+        return ExprError();
+    }
+    // If we found a getter then this may be a valid dot-reference, we
+    // will look for the matching setter, in case it is needed.
+    Selector SetterSel =
+      SelectorTable::constructSetterName(PP.getIdentifierTable(),
+                                         PP.getSelectorTable(), Member);
+    ObjCMethodDecl *Setter = IFace->lookupInstanceMethod(SetterSel);
+    if (!Setter) {
+      // If this reference is in an @implementation, also check for 'private'
+      // methods.
+      Setter = IFace->lookupPrivateInstanceMethod(SetterSel);
+    }
+    // Look through local category implementations associated with the class.
+    if (!Setter)
+      Setter = IFace->getCategoryInstanceMethod(SetterSel);
+
+    if (Setter && DiagnoseUseOfDecl(Setter, MemberLoc))
+      return ExprError();
+
+    if (Getter) {
+      QualType PType;
+      PType = Getter->getResultType();
+      return Owned(new (Context) ObjCImplicitSetterGetterRefExpr(Getter, PType,
+                                      Setter, MemberLoc, BaseExpr));
+    }
+
+    // Attempt to correct for typos in property names.
+    LookupResult Res(*this, R.getLookupName(), R.getNameLoc(),
+                     LookupOrdinaryName);
+    if (CorrectTypo(Res, 0, 0, IFace, false, OPT) && 
+        Res.getAsSingle<ObjCPropertyDecl>()) {
+      Diag(R.getNameLoc(), diag::err_property_not_found_suggest)
+        << MemberName << BaseType << Res.getLookupName()
+        << CodeModificationHint::CreateReplacement(R.getNameLoc(),
+                                           Res.getLookupName().getAsString());
+      ObjCPropertyDecl *Property = Res.getAsSingle<ObjCPropertyDecl>();
+      Diag(Property->getLocation(), diag::note_previous_decl)
+        << Property->getDeclName();          
+
+      return LookupMemberExpr(Res, BaseExpr, IsArrow, OpLoc, SS,
+                              ObjCImpDecl);
+    }
+
+    return ExprError(Diag(MemberLoc, diag::err_property_not_found)
+      << MemberName << BaseType);
+  }
+
+  // Handle the following exceptional case (*Obj).isa.
+  if (!IsArrow &&
+      BaseType->isSpecificBuiltinType(BuiltinType::ObjCId) &&
+      MemberName.getAsIdentifierInfo()->isStr("isa"))
+    return Owned(new (Context) ObjCIsaExpr(BaseExpr, false, MemberLoc,
+                                           Context.getObjCClassType()));
+
+  // Handle 'field access' to vectors, such as 'V.xx'.
+  if (BaseType->isExtVectorType()) {
+    IdentifierInfo *Member = MemberName.getAsIdentifierInfo();
+    QualType ret = CheckExtVectorComponent(BaseType, OpLoc, Member, MemberLoc);
+    if (ret.isNull())
+      return ExprError();
+    return Owned(new (Context) ExtVectorElementExpr(ret, BaseExpr, *Member,
+                                                    MemberLoc));
+  }
+
+  Diag(MemberLoc, diag::err_typecheck_member_reference_struct_union)
+    << BaseType << BaseExpr->getSourceRange();
+
+  return ExprError();
+}
+
+static Sema::OwningExprResult DiagnoseDtorReference(Sema &SemaRef,
+                                                    SourceLocation NameLoc,
+                                                    Sema::ExprArg MemExpr) {
+  Expr *E = (Expr *) MemExpr.get();
+  SourceLocation ExpectedLParenLoc = SemaRef.PP.getLocForEndOfToken(NameLoc);
+  SemaRef.Diag(E->getLocStart(), diag::err_dtor_expr_without_call)
+    << isa<CXXPseudoDestructorExpr>(E)
+    << CodeModificationHint::CreateInsertion(ExpectedLParenLoc, "()");
+  
+  return SemaRef.ActOnCallExpr(/*Scope*/ 0,
+                               move(MemExpr),
+                               /*LPLoc*/ ExpectedLParenLoc,
+                               Sema::MultiExprArg(SemaRef, 0, 0),
+                               /*CommaLocs*/ 0,
+                               /*RPLoc*/ ExpectedLParenLoc);
+}
+
+/// The main callback when the parser finds something like
+///   expression . [nested-name-specifier] identifier
+///   expression -> [nested-name-specifier] identifier
+/// where 'identifier' encompasses a fairly broad spectrum of
+/// possibilities, including destructor and operator references.
+///
+/// \param OpKind either tok::arrow or tok::period
+/// \param HasTrailingLParen whether the next token is '(', which
+///   is used to diagnose mis-uses of special members that can
+///   only be called
+/// \param ObjCImpDecl the current ObjC @implementation decl;
+///   this is an ugly hack around the fact that ObjC @implementations
+///   aren't properly put in the context chain
+Sema::OwningExprResult Sema::ActOnMemberAccessExpr(Scope *S, ExprArg BaseArg,
+                                                   SourceLocation OpLoc,
+                                                   tok::TokenKind OpKind,
+                                                   const CXXScopeSpec &SS,
+                                                   UnqualifiedId &Id,
+                                                   DeclPtrTy ObjCImpDecl,
+                                                   bool HasTrailingLParen) {
+  if (SS.isSet() && SS.isInvalid())
+    return ExprError();
+
+  TemplateArgumentListInfo TemplateArgsBuffer;
+
+  // Decompose the name into its component parts.
+  DeclarationName Name;
+  SourceLocation NameLoc;
+  const TemplateArgumentListInfo *TemplateArgs;
+  DecomposeUnqualifiedId(*this, Id, TemplateArgsBuffer,
+                         Name, NameLoc, TemplateArgs);
+
+  bool IsArrow = (OpKind == tok::arrow);
+
+  NamedDecl *FirstQualifierInScope
+    = (!SS.isSet() ? 0 : FindFirstQualifierInScope(S,
+                       static_cast<NestedNameSpecifier*>(SS.getScopeRep())));
+
+  // This is a postfix expression, so get rid of ParenListExprs.
+  BaseArg = MaybeConvertParenListExprToParenExpr(S, move(BaseArg));
+
+  Expr *Base = BaseArg.takeAs<Expr>();
+  OwningExprResult Result(*this);
+  if (Base->getType()->isDependentType() || Name.isDependentName()) {
+    Result = ActOnDependentMemberExpr(ExprArg(*this, Base), Base->getType(),
+                                      IsArrow, OpLoc,
+                                      SS, FirstQualifierInScope,
+                                      Name, NameLoc,
+                                      TemplateArgs);
+  } else {
+    LookupResult R(*this, Name, NameLoc, LookupMemberName);
+    if (TemplateArgs) {
+      // Re-use the lookup done for the template name.
+      DecomposeTemplateName(R, Id);
+    } else {
+      Result = LookupMemberExpr(R, Base, IsArrow, OpLoc,
+                                SS, ObjCImpDecl);
+
+      if (Result.isInvalid()) {
+        Owned(Base);
+        return ExprError();
+      }
+
+      if (Result.get()) {
+        // The only way a reference to a destructor can be used is to
+        // immediately call it, which falls into this case.  If the
+        // next token is not a '(', produce a diagnostic and build the
+        // call now.
+        if (!HasTrailingLParen &&
+            Id.getKind() == UnqualifiedId::IK_DestructorName)
+          return DiagnoseDtorReference(*this, NameLoc, move(Result));
+
+        return move(Result);
+      }
+    }
+
+    Result = BuildMemberReferenceExpr(ExprArg(*this, Base), Base->getType(),
+                                      OpLoc, IsArrow, SS, FirstQualifierInScope,
+                                      R, TemplateArgs);
+  }
+
+  return move(Result);
+}
+
+Sema::OwningExprResult Sema::BuildCXXDefaultArgExpr(SourceLocation CallLoc,
+                                                    FunctionDecl *FD,
+                                                    ParmVarDecl *Param) {
+  if (Param->hasUnparsedDefaultArg()) {
+    Diag (CallLoc,
+          diag::err_use_of_default_argument_to_function_declared_later) <<
+      FD << cast<CXXRecordDecl>(FD->getDeclContext())->getDeclName();
+    Diag(UnparsedDefaultArgLocs[Param],
+          diag::note_default_argument_declared_here);
+  } else {
+    if (Param->hasUninstantiatedDefaultArg()) {
+      Expr *UninstExpr = Param->getUninstantiatedDefaultArg();
+
+      // Instantiate the expression.
+      MultiLevelTemplateArgumentList ArgList
+        = getTemplateInstantiationArgs(FD, 0, /*RelativeToPrimary=*/true);
+
+      InstantiatingTemplate Inst(*this, CallLoc, Param,
+                                 ArgList.getInnermost().getFlatArgumentList(),
+                                 ArgList.getInnermost().flat_size());
+
+      OwningExprResult Result = SubstExpr(UninstExpr, ArgList);
+      if (Result.isInvalid())
+        return ExprError();
+
+      // Check the expression as an initializer for the parameter.
+      InitializedEntity Entity
+        = InitializedEntity::InitializeParameter(Param);
+      InitializationKind Kind
+        = InitializationKind::CreateCopy(Param->getLocation(),
+               /*FIXME:EqualLoc*/UninstExpr->getSourceRange().getBegin());
+      Expr *ResultE = Result.takeAs<Expr>();
+
+      InitializationSequence InitSeq(*this, Entity, Kind, &ResultE, 1);
+      Result = InitSeq.Perform(*this, Entity, Kind, 
+                               MultiExprArg(*this, (void**)&ResultE, 1));
+      if (Result.isInvalid())
+        return ExprError();
+      
+      // Build the default argument expression.
+      return Owned(CXXDefaultArgExpr::Create(Context, CallLoc, Param,
+                                             Result.takeAs<Expr>()));
+    }
+
+    // If the default expression creates temporaries, we need to
+    // push them to the current stack of expression temporaries so they'll
+    // be properly destroyed.
+    // FIXME: We should really be rebuilding the default argument with new
+    // bound temporaries; see the comment in PR5810.
+    for (unsigned i = 0, e = Param->getNumDefaultArgTemporaries(); i != e; ++i)
+      ExprTemporaries.push_back(Param->getDefaultArgTemporary(i));
+  }
+
+  // We already type-checked the argument, so we know it works.
+  return Owned(CXXDefaultArgExpr::Create(Context, CallLoc, Param));
+}
+
+/// ConvertArgumentsForCall - Converts the arguments specified in
+/// Args/NumArgs to the parameter types of the function FDecl with
+/// function prototype Proto. Call is the call expression itself, and
+/// Fn is the function expression. For a C++ member function, this
+/// routine does not attempt to convert the object argument. Returns
+/// true if the call is ill-formed.
+bool
+Sema::ConvertArgumentsForCall(CallExpr *Call, Expr *Fn,
+                              FunctionDecl *FDecl,
+                              const FunctionProtoType *Proto,
+                              Expr **Args, unsigned NumArgs,
+                              SourceLocation RParenLoc) {
+  // 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();
+  bool Invalid = false;
+   
+  // If too few arguments are available (and we don't have default
+  // arguments for the remaining parameters), don't make the call.
+  if (NumArgs < NumArgsInProto) {
+    if (!FDecl || NumArgs < FDecl->getMinRequiredArguments())
+      return Diag(RParenLoc, diag::err_typecheck_call_too_few_args)
+        << Fn->getType()->isBlockPointerType() << Fn->getSourceRange();
+    Call->setNumArgs(Context, NumArgsInProto);
+  }
+
+  // If too many are passed and not variadic, error on the extras and drop
+  // them.
+  if (NumArgs > NumArgsInProto) {
+    if (!Proto->isVariadic()) {
+      Diag(Args[NumArgsInProto]->getLocStart(),
+           diag::err_typecheck_call_too_many_args)
+        << Fn->getType()->isBlockPointerType() << Fn->getSourceRange()
+        << SourceRange(Args[NumArgsInProto]->getLocStart(),
+                       Args[NumArgs-1]->getLocEnd());
+      // This deletes the extra arguments.
+      Call->setNumArgs(Context, NumArgsInProto);
+      return true;
+    }
+  }
+  llvm::SmallVector<Expr *, 8> AllArgs;
+  VariadicCallType CallType = 
+    Proto->isVariadic() ? VariadicFunction : VariadicDoesNotApply;
+  if (Fn->getType()->isBlockPointerType())
+    CallType = VariadicBlock; // Block
+  else if (isa<MemberExpr>(Fn))
+    CallType = VariadicMethod;
+  Invalid = GatherArgumentsForCall(Call->getSourceRange().getBegin(), FDecl,
+                                   Proto, 0, Args, NumArgs, AllArgs, CallType);
+  if (Invalid)
+    return true;
+  unsigned TotalNumArgs = AllArgs.size();
+  for (unsigned i = 0; i < TotalNumArgs; ++i)
+    Call->setArg(i, AllArgs[i]);
+  
+  return false;
+}
+
+bool Sema::GatherArgumentsForCall(SourceLocation CallLoc,
+                                  FunctionDecl *FDecl,
+                                  const FunctionProtoType *Proto,
+                                  unsigned FirstProtoArg,
+                                  Expr **Args, unsigned NumArgs,
+                                  llvm::SmallVector<Expr *, 8> &AllArgs,
+                                  VariadicCallType CallType) {
+  unsigned NumArgsInProto = Proto->getNumArgs();
+  unsigned NumArgsToCheck = NumArgs;
+  bool Invalid = false;
+  if (NumArgs != NumArgsInProto)
+    // Use default arguments for missing arguments
+    NumArgsToCheck = NumArgsInProto;
+  unsigned ArgIx = 0;
+  // Continue to check argument types (even if we have too few/many args).
+  for (unsigned i = FirstProtoArg; i != NumArgsToCheck; i++) {
+    QualType ProtoArgType = Proto->getArgType(i);
+    
+    Expr *Arg;
+    if (ArgIx < NumArgs) {
+      Arg = Args[ArgIx++];
+      
+      if (RequireCompleteType(Arg->getSourceRange().getBegin(),
+                              ProtoArgType,
+                              PDiag(diag::err_call_incomplete_argument)
+                              << Arg->getSourceRange()))
+        return true;
+      
+      // Pass the argument
+      ParmVarDecl *Param = 0;
+      if (FDecl && i < FDecl->getNumParams())
+        Param = FDecl->getParamDecl(i);
+
+      
+      InitializedEntity Entity =
+        Param? InitializedEntity::InitializeParameter(Param)
+             : InitializedEntity::InitializeParameter(ProtoArgType);
+      OwningExprResult ArgE = PerformCopyInitialization(Entity,
+                                                        SourceLocation(),
+                                                        Owned(Arg));
+      if (ArgE.isInvalid())
+        return true;
+
+      Arg = ArgE.takeAs<Expr>();
+    } else {
+      ParmVarDecl *Param = FDecl->getParamDecl(i);
+      
+      OwningExprResult ArgExpr =
+        BuildCXXDefaultArgExpr(CallLoc, FDecl, Param);
+      if (ArgExpr.isInvalid())
+        return true;
+      
+      Arg = ArgExpr.takeAs<Expr>();
+    }
+    AllArgs.push_back(Arg);
+  }
+  
+  // If this is a variadic call, handle args passed through "...".
+  if (CallType != VariadicDoesNotApply) {
+    // Promote the arguments (C99 6.5.2.2p7).
+    for (unsigned i = ArgIx; i < NumArgs; i++) {
+      Expr *Arg = Args[i];
+      Invalid |= DefaultVariadicArgumentPromotion(Arg, CallType);
+      AllArgs.push_back(Arg);
+    }
+  }
+  return Invalid;
+}
+
+/// ActOnCallExpr - 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::OwningExprResult
+Sema::ActOnCallExpr(Scope *S, ExprArg fn, SourceLocation LParenLoc,
+                    MultiExprArg args,
+                    SourceLocation *CommaLocs, SourceLocation RParenLoc) {
+  unsigned NumArgs = args.size();
+
+  // Since this might be a postfix expression, get rid of ParenListExprs.
+  fn = MaybeConvertParenListExprToParenExpr(S, move(fn));
+
+  Expr *Fn = fn.takeAs<Expr>();
+  Expr **Args = reinterpret_cast<Expr**>(args.release());
+  assert(Fn && "no function call expression");
+
+  if (getLangOptions().CPlusPlus) {
+    // If this is a pseudo-destructor expression, build the call immediately.
+    if (isa<CXXPseudoDestructorExpr>(Fn)) {
+      if (NumArgs > 0) {
+        // Pseudo-destructor calls should not have any arguments.
+        Diag(Fn->getLocStart(), diag::err_pseudo_dtor_call_with_args)
+          << CodeModificationHint::CreateRemoval(
+                                    SourceRange(Args[0]->getLocStart(),
+                                                Args[NumArgs-1]->getLocEnd()));
+
+        for (unsigned I = 0; I != NumArgs; ++I)
+          Args[I]->Destroy(Context);
+
+        NumArgs = 0;
+      }
+
+      return Owned(new (Context) CallExpr(Context, Fn, 0, 0, Context.VoidTy,
+                                          RParenLoc));
+    }
+
+    // Determine whether this is a dependent call inside a C++ template,
+    // in which case we won't do any semantic analysis now.
+    // FIXME: Will need to cache the results of name lookup (including ADL) in
+    // Fn.
+    bool Dependent = false;
+    if (Fn->isTypeDependent())
+      Dependent = true;
+    else if (Expr::hasAnyTypeDependentArguments(Args, NumArgs))
+      Dependent = true;
+
+    if (Dependent)
+      return Owned(new (Context) CallExpr(Context, Fn, Args, NumArgs,
+                                          Context.DependentTy, RParenLoc));
+
+    // Determine whether this is a call to an object (C++ [over.call.object]).
+    if (Fn->getType()->isRecordType())
+      return Owned(BuildCallToObjectOfClassType(S, Fn, LParenLoc, Args, NumArgs,
+                                                CommaLocs, RParenLoc));
+
+    Expr *NakedFn = Fn->IgnoreParens();
+
+    // Determine whether this is a call to an unresolved member function.
+    if (UnresolvedMemberExpr *MemE = dyn_cast<UnresolvedMemberExpr>(NakedFn)) {
+      // If lookup was unresolved but not dependent (i.e. didn't find
+      // an unresolved using declaration), it has to be an overloaded
+      // function set, which means it must contain either multiple
+      // declarations (all methods or method templates) or a single
+      // method template.
+      assert((MemE->getNumDecls() > 1) ||
+             isa<FunctionTemplateDecl>(*MemE->decls_begin()));
+      (void)MemE;
+
+      return BuildCallToMemberFunction(S, Fn, LParenLoc, Args, NumArgs,
+                                       CommaLocs, RParenLoc);
+    }
+
+    // Determine whether this is a call to a member function.
+    if (MemberExpr *MemExpr = dyn_cast<MemberExpr>(NakedFn)) {
+      NamedDecl *MemDecl = MemExpr->getMemberDecl();
+      if (isa<CXXMethodDecl>(MemDecl))
+        return BuildCallToMemberFunction(S, Fn, LParenLoc, Args, NumArgs,
+                                         CommaLocs, RParenLoc);
+    }
+    
+    // Determine whether this is a call to a pointer-to-member function.
+    if (BinaryOperator *BO = dyn_cast<BinaryOperator>(NakedFn)) {
+      if (BO->getOpcode() == BinaryOperator::PtrMemD ||
+          BO->getOpcode() == BinaryOperator::PtrMemI) {
+        if (const FunctionProtoType *FPT = 
+              dyn_cast<FunctionProtoType>(BO->getType())) {
+          QualType ResultTy = FPT->getResultType().getNonReferenceType();
+      
+          ExprOwningPtr<CXXMemberCallExpr> 
+            TheCall(this, new (Context) CXXMemberCallExpr(Context, BO, Args, 
+                                                          NumArgs, ResultTy,
+                                                          RParenLoc));
+        
+          if (CheckCallReturnType(FPT->getResultType(), 
+                                  BO->getRHS()->getSourceRange().getBegin(), 
+                                  TheCall.get(), 0))
+            return ExprError();
+
+          if (ConvertArgumentsForCall(&*TheCall, BO, 0, FPT, Args, NumArgs, 
+                                      RParenLoc))
+            return ExprError();
+
+          return Owned(MaybeBindToTemporary(TheCall.release()).release());
+        }
+        return ExprError(Diag(Fn->getLocStart(), 
+                              diag::err_typecheck_call_not_function)
+                              << Fn->getType() << Fn->getSourceRange());
+      }
+    }
+  }
+
+  // If we're directly calling a function, get the appropriate declaration.
+  // Also, in C++, keep track of whether we should perform argument-dependent
+  // lookup and whether there were any explicitly-specified template arguments.
+
+  Expr *NakedFn = Fn->IgnoreParens();
+  if (isa<UnresolvedLookupExpr>(NakedFn)) {
+    UnresolvedLookupExpr *ULE = cast<UnresolvedLookupExpr>(NakedFn);
+    return BuildOverloadedCallExpr(Fn, ULE, LParenLoc, Args, NumArgs,
+                                   CommaLocs, RParenLoc);
+  }
+
+  NamedDecl *NDecl = 0;
+  if (isa<DeclRefExpr>(NakedFn))
+    NDecl = cast<DeclRefExpr>(NakedFn)->getDecl();
+
+  return BuildResolvedCallExpr(Fn, NDecl, LParenLoc, Args, NumArgs, RParenLoc);
+}
+
+/// BuildResolvedCallExpr - Build a call to a resolved expression,
+/// i.e. an expression not of \p OverloadTy.  The expression should
+/// unary-convert to an expression of function-pointer or
+/// block-pointer type.
+///
+/// \param NDecl the declaration being called, if available
+Sema::OwningExprResult
+Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl,
+                            SourceLocation LParenLoc,
+                            Expr **Args, unsigned NumArgs,
+                            SourceLocation RParenLoc) {
+  FunctionDecl *FDecl = dyn_cast_or_null<FunctionDecl>(NDecl);
+
+  // Promote the function operand.
+  UsualUnaryConversions(Fn);
+
+  // Make the call expr early, before semantic checks.  This guarantees cleanup
+  // of arguments and function on error.
+  ExprOwningPtr<CallExpr> TheCall(this, new (Context) CallExpr(Context, Fn,
+                                                               Args, NumArgs,
+                                                               Context.BoolTy,
+                                                               RParenLoc));
+
+  const FunctionType *FuncT;
+  if (!Fn->getType()->isBlockPointerType()) {
+    // C99 6.5.2.2p1 - "The expression that denotes the called function shall
+    // have type pointer to function".
+    const PointerType *PT = Fn->getType()->getAs<PointerType>();
+    if (PT == 0)
+      return ExprError(Diag(LParenLoc, diag::err_typecheck_call_not_function)
+        << Fn->getType() << Fn->getSourceRange());
+    FuncT = PT->getPointeeType()->getAs<FunctionType>();
+  } else { // This is a block call.
+    FuncT = Fn->getType()->getAs<BlockPointerType>()->getPointeeType()->
+                getAs<FunctionType>();
+  }
+  if (FuncT == 0)
+    return ExprError(Diag(LParenLoc, diag::err_typecheck_call_not_function)
+      << Fn->getType() << Fn->getSourceRange());
+
+  // Check for a valid return type
+  if (CheckCallReturnType(FuncT->getResultType(), 
+                          Fn->getSourceRange().getBegin(), TheCall.get(),
+                          FDecl))
+    return ExprError();
+
+  // We know the result type of the call, set it.
+  TheCall->setType(FuncT->getResultType().getNonReferenceType());
+
+  if (const FunctionProtoType *Proto = dyn_cast<FunctionProtoType>(FuncT)) {
+    if (ConvertArgumentsForCall(&*TheCall, Fn, FDecl, Proto, Args, NumArgs,
+                                RParenLoc))
+      return ExprError();
+  } else {
+    assert(isa<FunctionNoProtoType>(FuncT) && "Unknown FunctionType!");
+
+    if (FDecl) {
+      // Check if we have too few/too many template arguments, based
+      // on our knowledge of the function definition.
+      const FunctionDecl *Def = 0;
+      if (FDecl->getBody(Def) && NumArgs != Def->param_size()) {
+        const FunctionProtoType *Proto =
+            Def->getType()->getAs<FunctionProtoType>();
+        if (!Proto || !(Proto->isVariadic() && NumArgs >= Def->param_size())) {
+          Diag(RParenLoc, diag::warn_call_wrong_number_of_arguments)
+            << (NumArgs > Def->param_size()) << FDecl << Fn->getSourceRange();
+        }
+      }
+    }
+
+    // Promote the arguments (C99 6.5.2.2p6).
+    for (unsigned i = 0; i != NumArgs; i++) {
+      Expr *Arg = Args[i];
+      DefaultArgumentPromotion(Arg);
+      if (RequireCompleteType(Arg->getSourceRange().getBegin(),
+                              Arg->getType(),
+                              PDiag(diag::err_call_incomplete_argument)
+                                << Arg->getSourceRange()))
+        return ExprError();
+      TheCall->setArg(i, Arg);
+    }
+  }
+
+  if (CXXMethodDecl *Method = dyn_cast_or_null<CXXMethodDecl>(FDecl))
+    if (!Method->isStatic())
+      return ExprError(Diag(LParenLoc, diag::err_member_call_without_object)
+        << Fn->getSourceRange());
+
+  // Check for sentinels
+  if (NDecl)
+    DiagnoseSentinelCalls(NDecl, LParenLoc, Args, NumArgs);
+
+  // Do special checking on direct calls to functions.
+  if (FDecl) {
+    if (CheckFunctionCall(FDecl, TheCall.get()))
+      return ExprError();
+
+    if (unsigned BuiltinID = FDecl->getBuiltinID())
+      return CheckBuiltinFunctionCall(BuiltinID, TheCall.take());
+  } else if (NDecl) {
+    if (CheckBlockCall(NDecl, TheCall.get()))
+      return ExprError();
+  }
+
+  return MaybeBindToTemporary(TheCall.take());
+}
+
+Action::OwningExprResult
+Sema::ActOnCompoundLiteral(SourceLocation LParenLoc, TypeTy *Ty,
+                           SourceLocation RParenLoc, ExprArg InitExpr) {
+  assert((Ty != 0) && "ActOnCompoundLiteral(): missing type");
+  // FIXME: put back this assert when initializers are worked out.
+  //assert((InitExpr != 0) && "ActOnCompoundLiteral(): missing expression");
+
+  TypeSourceInfo *TInfo;
+  QualType literalType = GetTypeFromParser(Ty, &TInfo);
+  if (!TInfo)
+    TInfo = Context.getTrivialTypeSourceInfo(literalType);
+
+  return BuildCompoundLiteralExpr(LParenLoc, TInfo, RParenLoc, move(InitExpr));
+}
+
+Action::OwningExprResult
+Sema::BuildCompoundLiteralExpr(SourceLocation LParenLoc, TypeSourceInfo *TInfo,
+                               SourceLocation RParenLoc, ExprArg InitExpr) {
+  QualType literalType = TInfo->getType();
+  Expr *literalExpr = static_cast<Expr*>(InitExpr.get());
+
+  if (literalType->isArrayType()) {
+    if (literalType->isVariableArrayType())
+      return ExprError(Diag(LParenLoc, diag::err_variable_object_no_init)
+        << SourceRange(LParenLoc, literalExpr->getSourceRange().getEnd()));
+  } else if (!literalType->isDependentType() &&
+             RequireCompleteType(LParenLoc, literalType,
+                      PDiag(diag::err_typecheck_decl_incomplete_type)
+                        << SourceRange(LParenLoc,
+                                       literalExpr->getSourceRange().getEnd())))
+    return ExprError();
+
+  InitializedEntity Entity
+    = InitializedEntity::InitializeTemporary(literalType);
+  InitializationKind Kind
+    = InitializationKind::CreateCast(SourceRange(LParenLoc, RParenLoc), 
+                                     /*IsCStyleCast=*/true);
+  InitializationSequence InitSeq(*this, Entity, Kind, &literalExpr, 1);
+  OwningExprResult Result = InitSeq.Perform(*this, Entity, Kind,
+                                   MultiExprArg(*this, (void**)&literalExpr, 1),
+                                            &literalType);
+  if (Result.isInvalid())
+    return ExprError();
+  InitExpr.release();
+  literalExpr = static_cast<Expr*>(Result.get());
+
+  bool isFileScope = getCurFunctionOrMethodDecl() == 0;
+  if (isFileScope) { // 6.5.2.5p3
+    if (CheckForConstantInitializer(literalExpr, literalType))
+      return ExprError();
+  }
+
+  Result.release();
+  
+  return Owned(new (Context) CompoundLiteralExpr(LParenLoc, TInfo, literalType,
+                                                 literalExpr, isFileScope));
+}
+
+Action::OwningExprResult
+Sema::ActOnInitList(SourceLocation LBraceLoc, MultiExprArg initlist,
+                    SourceLocation RBraceLoc) {
+  unsigned NumInit = initlist.size();
+  Expr **InitList = reinterpret_cast<Expr**>(initlist.release());
+
+  // Semantic analysis for initializers is done by ActOnDeclarator() and
+  // CheckInitializer() - it requires knowledge of the object being intialized.
+
+  InitListExpr *E = new (Context) InitListExpr(LBraceLoc, InitList, NumInit,
+                                               RBraceLoc);
+  E->setType(Context.VoidTy); // FIXME: just a place holder for now.
+  return Owned(E);
+}
+
+static CastExpr::CastKind getScalarCastKind(ASTContext &Context,
+                                            QualType SrcTy, QualType DestTy) {
+  if (Context.hasSameUnqualifiedType(SrcTy, DestTy))
+    return CastExpr::CK_NoOp;
+
+  if (SrcTy->hasPointerRepresentation()) {
+    if (DestTy->hasPointerRepresentation())
+      return DestTy->isObjCObjectPointerType() ? 
+                CastExpr::CK_AnyPointerToObjCPointerCast : 
+                CastExpr::CK_BitCast;
+    if (DestTy->isIntegerType())
+      return CastExpr::CK_PointerToIntegral;
+  }
+  
+  if (SrcTy->isIntegerType()) {
+    if (DestTy->isIntegerType())
+      return CastExpr::CK_IntegralCast;
+    if (DestTy->hasPointerRepresentation())
+      return CastExpr::CK_IntegralToPointer;
+    if (DestTy->isRealFloatingType())
+      return CastExpr::CK_IntegralToFloating;
+  }
+  
+  if (SrcTy->isRealFloatingType()) {
+    if (DestTy->isRealFloatingType())
+      return CastExpr::CK_FloatingCast;
+    if (DestTy->isIntegerType())
+      return CastExpr::CK_FloatingToIntegral;
+  }
+  
+  // FIXME: Assert here.
+  // assert(false && "Unhandled cast combination!");
+  return CastExpr::CK_Unknown;
+}
+
+/// CheckCastTypes - Check type constraints for casting between types.
+bool Sema::CheckCastTypes(SourceRange TyR, QualType castType, Expr *&castExpr,
+                          CastExpr::CastKind& Kind,
+                          CXXMethodDecl *& ConversionDecl,
+                          bool FunctionalStyle) {
+  if (getLangOptions().CPlusPlus)
+    return CXXCheckCStyleCast(TyR, castType, castExpr, Kind, FunctionalStyle,
+                              ConversionDecl);
+
+  DefaultFunctionArrayLvalueConversion(castExpr);
+
+  // C99 6.5.4p2: the cast type needs to be void or scalar and the expression
+  // type needs to be scalar.
+  if (castType->isVoidType()) {
+    // Cast to void allows any expr type.
+    Kind = CastExpr::CK_ToVoid;
+    return false;
+  }
+  
+  if (!castType->isScalarType() && !castType->isVectorType()) {
+    if (Context.hasSameUnqualifiedType(castType, castExpr->getType()) &&
+        (castType->isStructureType() || castType->isUnionType())) {
+      // GCC struct/union extension: allow cast to self.
+      // FIXME: Check that the cast destination type is complete.
+      Diag(TyR.getBegin(), diag::ext_typecheck_cast_nonscalar)
+        << castType << castExpr->getSourceRange();
+      Kind = CastExpr::CK_NoOp;
+      return false;
+    }
+    
+    if (castType->isUnionType()) {
+      // GCC cast to union extension
+      RecordDecl *RD = castType->getAs<RecordType>()->getDecl();
+      RecordDecl::field_iterator Field, FieldEnd;
+      for (Field = RD->field_begin(), FieldEnd = RD->field_end();
+           Field != FieldEnd; ++Field) {
+        if (Context.hasSameUnqualifiedType(Field->getType(), 
+                                           castExpr->getType())) {
+          Diag(TyR.getBegin(), diag::ext_typecheck_cast_to_union)
+            << castExpr->getSourceRange();
+          break;
+        }
+      }
+      if (Field == FieldEnd)
+        return Diag(TyR.getBegin(), diag::err_typecheck_cast_to_union_no_type)
+          << castExpr->getType() << castExpr->getSourceRange();
+      Kind = CastExpr::CK_ToUnion;
+      return false;
+    }
+    
+    // Reject any other conversions to non-scalar types.
+    return Diag(TyR.getBegin(), diag::err_typecheck_cond_expect_scalar)
+      << castType << castExpr->getSourceRange();
+  }
+  
+  if (!castExpr->getType()->isScalarType() && 
+      !castExpr->getType()->isVectorType()) {
+    return Diag(castExpr->getLocStart(),
+                diag::err_typecheck_expect_scalar_operand)
+      << castExpr->getType() << castExpr->getSourceRange();
+  }
+  
+  if (castType->isExtVectorType()) 
+    return CheckExtVectorCast(TyR, castType, castExpr, Kind);
+  
+  if (castType->isVectorType())
+    return CheckVectorCast(TyR, castType, castExpr->getType(), Kind);
+  if (castExpr->getType()->isVectorType())
+    return CheckVectorCast(TyR, castExpr->getType(), castType, Kind);
+
+  if (getLangOptions().ObjC1 && isa<ObjCSuperExpr>(castExpr))
+    return Diag(castExpr->getLocStart(), diag::err_illegal_super_cast) << TyR;
+  
+  if (isa<ObjCSelectorExpr>(castExpr))
+    return Diag(castExpr->getLocStart(), diag::err_cast_selector_expr);
+  
+  if (!castType->isArithmeticType()) {
+    QualType castExprType = castExpr->getType();
+    if (!castExprType->isIntegralType() && castExprType->isArithmeticType())
+      return Diag(castExpr->getLocStart(),
+                  diag::err_cast_pointer_from_non_pointer_int)
+        << castExprType << castExpr->getSourceRange();
+  } else if (!castExpr->getType()->isArithmeticType()) {
+    if (!castType->isIntegralType() && castType->isArithmeticType())
+      return Diag(castExpr->getLocStart(),
+                  diag::err_cast_pointer_to_non_pointer_int)
+        << castType << castExpr->getSourceRange();
+  }
+
+  Kind = getScalarCastKind(Context, castExpr->getType(), castType);
+  return false;
+}
+
+bool Sema::CheckVectorCast(SourceRange R, QualType VectorTy, QualType Ty,
+                           CastExpr::CastKind &Kind) {
+  assert(VectorTy->isVectorType() && "Not a vector type!");
+
+  if (Ty->isVectorType() || Ty->isIntegerType()) {
+    if (Context.getTypeSize(VectorTy) != Context.getTypeSize(Ty))
+      return Diag(R.getBegin(),
+                  Ty->isVectorType() ?
+                  diag::err_invalid_conversion_between_vectors :
+                  diag::err_invalid_conversion_between_vector_and_integer)
+        << VectorTy << Ty << R;
+  } else
+    return Diag(R.getBegin(),
+                diag::err_invalid_conversion_between_vector_and_scalar)
+      << VectorTy << Ty << R;
+
+  Kind = CastExpr::CK_BitCast;
+  return false;
+}
+
+bool Sema::CheckExtVectorCast(SourceRange R, QualType DestTy, Expr *&CastExpr, 
+                              CastExpr::CastKind &Kind) {
+  assert(DestTy->isExtVectorType() && "Not an extended vector type!");
+  
+  QualType SrcTy = CastExpr->getType();
+  
+  // If SrcTy is a VectorType, the total size must match to explicitly cast to
+  // an ExtVectorType.
+  if (SrcTy->isVectorType()) {
+    if (Context.getTypeSize(DestTy) != Context.getTypeSize(SrcTy))
+      return Diag(R.getBegin(),diag::err_invalid_conversion_between_ext_vectors)
+        << DestTy << SrcTy << R;
+    Kind = CastExpr::CK_BitCast;
+    return false;
+  }
+
+  // All non-pointer scalars can be cast to ExtVector type.  The appropriate
+  // conversion will take place first from scalar to elt type, and then
+  // splat from elt type to vector.
+  if (SrcTy->isPointerType())
+    return Diag(R.getBegin(),
+                diag::err_invalid_conversion_between_vector_and_scalar)
+      << DestTy << SrcTy << R;
+
+  QualType DestElemTy = DestTy->getAs<ExtVectorType>()->getElementType();
+  ImpCastExprToType(CastExpr, DestElemTy,
+                    getScalarCastKind(Context, SrcTy, DestElemTy));
+  
+  Kind = CastExpr::CK_VectorSplat;
+  return false;
+}
+
+Action::OwningExprResult
+Sema::ActOnCastExpr(Scope *S, SourceLocation LParenLoc, TypeTy *Ty,
+                    SourceLocation RParenLoc, ExprArg Op) {
+  assert((Ty != 0) && (Op.get() != 0) &&
+         "ActOnCastExpr(): missing type or expr");
+
+  TypeSourceInfo *castTInfo;
+  QualType castType = GetTypeFromParser(Ty, &castTInfo);
+  if (!castTInfo)
+    castTInfo = Context.getTrivialTypeSourceInfo(castType);
+
+  // If the Expr being casted is a ParenListExpr, handle it specially.
+  Expr *castExpr = (Expr *)Op.get();
+  if (isa<ParenListExpr>(castExpr))
+    return ActOnCastOfParenListExpr(S, LParenLoc, RParenLoc, move(Op),
+                                    castTInfo);
+
+  return BuildCStyleCastExpr(LParenLoc, castTInfo, RParenLoc, move(Op));
+}
+
+Action::OwningExprResult
+Sema::BuildCStyleCastExpr(SourceLocation LParenLoc, TypeSourceInfo *Ty,
+                          SourceLocation RParenLoc, ExprArg Op) {
+  Expr *castExpr = static_cast<Expr*>(Op.get());
+
+  CXXMethodDecl *Method = 0;
+  CastExpr::CastKind Kind = CastExpr::CK_Unknown;
+  if (CheckCastTypes(SourceRange(LParenLoc, RParenLoc), Ty->getType(), castExpr,
+                     Kind, Method))
+    return ExprError();
+
+  if (Method) {
+    // FIXME: preserve type source info here
+    OwningExprResult CastArg = BuildCXXCastArgument(LParenLoc, Ty->getType(),
+                                                    Kind, Method, move(Op));
+
+    if (CastArg.isInvalid())
+      return ExprError();
+
+    castExpr = CastArg.takeAs<Expr>();
+  } else {
+    Op.release();
+  }
+
+  return Owned(new (Context) CStyleCastExpr(Ty->getType().getNonReferenceType(),
+                                            Kind, castExpr, Ty,
+                                            LParenLoc, RParenLoc));
+}
+
+/// This is not an AltiVec-style cast, so turn the ParenListExpr into a sequence
+/// of comma binary operators.
+Action::OwningExprResult
+Sema::MaybeConvertParenListExprToParenExpr(Scope *S, ExprArg EA) {
+  Expr *expr = EA.takeAs<Expr>();
+  ParenListExpr *E = dyn_cast<ParenListExpr>(expr);
+  if (!E)
+    return Owned(expr);
+
+  OwningExprResult Result(*this, E->getExpr(0));
+
+  for (unsigned i = 1, e = E->getNumExprs(); i != e && !Result.isInvalid(); ++i)
+    Result = ActOnBinOp(S, E->getExprLoc(), tok::comma, move(Result),
+                        Owned(E->getExpr(i)));
+
+  return ActOnParenExpr(E->getLParenLoc(), E->getRParenLoc(), move(Result));
+}
+
+Action::OwningExprResult
+Sema::ActOnCastOfParenListExpr(Scope *S, SourceLocation LParenLoc,
+                               SourceLocation RParenLoc, ExprArg Op,
+                               TypeSourceInfo *TInfo) {
+  ParenListExpr *PE = (ParenListExpr *)Op.get();
+  QualType Ty = TInfo->getType();
+
+  // If this is an altivec initializer, '(' type ')' '(' init, ..., init ')'
+  // then handle it as such.
+  if (getLangOptions().AltiVec && Ty->isVectorType()) {
+    if (PE->getNumExprs() == 0) {
+      Diag(PE->getExprLoc(), diag::err_altivec_empty_initializer);
+      return ExprError();
+    }
+
+    llvm::SmallVector<Expr *, 8> initExprs;
+    for (unsigned i = 0, e = PE->getNumExprs(); i != e; ++i)
+      initExprs.push_back(PE->getExpr(i));
+
+    // FIXME: This means that pretty-printing the final AST will produce curly
+    // braces instead of the original commas.
+    Op.release();
+    InitListExpr *E = new (Context) InitListExpr(LParenLoc, &initExprs[0],
+                                                 initExprs.size(), RParenLoc);
+    E->setType(Ty);
+    return BuildCompoundLiteralExpr(LParenLoc, TInfo, RParenLoc, Owned(E));
+  } else {
+    // This is not an AltiVec-style cast, so turn the ParenListExpr into a
+    // sequence of BinOp comma operators.
+    Op = MaybeConvertParenListExprToParenExpr(S, move(Op));
+    return BuildCStyleCastExpr(LParenLoc, TInfo, RParenLoc, move(Op));
+  }
+}
+
+Action::OwningExprResult Sema::ActOnParenOrParenListExpr(SourceLocation L,
+                                                  SourceLocation R,
+                                                  MultiExprArg Val,
+                                                  TypeTy *TypeOfCast) {
+  unsigned nexprs = Val.size();
+  Expr **exprs = reinterpret_cast<Expr**>(Val.release());
+  assert((exprs != 0) && "ActOnParenOrParenListExpr() missing expr list");
+  Expr *expr;
+  if (nexprs == 1 && TypeOfCast && !TypeIsVectorType(TypeOfCast))
+    expr = new (Context) ParenExpr(L, R, exprs[0]);
+  else
+    expr = new (Context) ParenListExpr(Context, L, exprs, nexprs, R);
+  return Owned(expr);
+}
+
+/// Note that lhs is not null here, even if this is the gnu "x ?: y" extension.
+/// In that case, lhs = cond.
+/// C99 6.5.15
+QualType Sema::CheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS,
+                                        SourceLocation QuestionLoc) {
+  // C++ is sufficiently different to merit its own checker.
+  if (getLangOptions().CPlusPlus)
+    return CXXCheckConditionalOperands(Cond, LHS, RHS, QuestionLoc);
+
+  CheckSignCompare(LHS, RHS, QuestionLoc, diag::warn_mixed_sign_conditional);
+
+  UsualUnaryConversions(Cond);
+  UsualUnaryConversions(LHS);
+  UsualUnaryConversions(RHS);
+  QualType CondTy = Cond->getType();
+  QualType LHSTy = LHS->getType();
+  QualType RHSTy = RHS->getType();
+
+  // first, check the condition.
+  if (!CondTy->isScalarType()) { // C99 6.5.15p2
+    Diag(Cond->getLocStart(), diag::err_typecheck_cond_expect_scalar)
+      << CondTy;
+    return QualType();
+  }
+
+  // Now check the two expressions.
+  if (LHSTy->isVectorType() || RHSTy->isVectorType())
+    return CheckVectorOperands(QuestionLoc, LHS, RHS);
+
+  // If both operands have arithmetic type, do the usual arithmetic conversions
+  // to find a common type: C99 6.5.15p3,5.
+  if (LHSTy->isArithmeticType() && RHSTy->isArithmeticType()) {
+    UsualArithmeticConversions(LHS, RHS);
+    return LHS->getType();
+  }
+
+  // If both operands are the same structure or union type, the result is that
+  // type.
+  if (const RecordType *LHSRT = LHSTy->getAs<RecordType>()) {    // C99 6.5.15p3
+    if (const RecordType *RHSRT = RHSTy->getAs<RecordType>())
+      if (LHSRT->getDecl() == RHSRT->getDecl())
+        // "If both the operands have structure or union type, the result has
+        // that type."  This implies that CV qualifiers are dropped.
+        return LHSTy.getUnqualifiedType();
+    // FIXME: Type of conditional expression must be complete in C mode.
+  }
+
+  // C99 6.5.15p5: "If both operands have void type, the result has void type."
+  // The following || allows only one side to be void (a GCC-ism).
+  if (LHSTy->isVoidType() || RHSTy->isVoidType()) {
+    if (!LHSTy->isVoidType())
+      Diag(RHS->getLocStart(), diag::ext_typecheck_cond_one_void)
+        << RHS->getSourceRange();
+    if (!RHSTy->isVoidType())
+      Diag(LHS->getLocStart(), diag::ext_typecheck_cond_one_void)
+        << LHS->getSourceRange();
+    ImpCastExprToType(LHS, Context.VoidTy, CastExpr::CK_ToVoid);
+    ImpCastExprToType(RHS, Context.VoidTy, CastExpr::CK_ToVoid);
+    return Context.VoidTy;
+  }
+  // C99 6.5.15p6 - "if one operand is a null pointer constant, the result has
+  // the type of the other operand."
+  if ((LHSTy->isAnyPointerType() || LHSTy->isBlockPointerType()) &&
+      RHS->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull)) {
+    // promote the null to a pointer.
+    ImpCastExprToType(RHS, LHSTy, CastExpr::CK_Unknown);
+    return LHSTy;
+  }
+  if ((RHSTy->isAnyPointerType() || RHSTy->isBlockPointerType()) &&
+      LHS->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull)) {
+    ImpCastExprToType(LHS, RHSTy, CastExpr::CK_Unknown);
+    return RHSTy;
+  }
+  
+  // All objective-c pointer type analysis is done here.
+  QualType compositeType = FindCompositeObjCPointerType(LHS, RHS,
+                                                        QuestionLoc);
+  if (!compositeType.isNull())
+    return compositeType;
+  
+  
+  // Handle block pointer types.
+  if (LHSTy->isBlockPointerType() || RHSTy->isBlockPointerType()) {
+    if (!LHSTy->isBlockPointerType() || !RHSTy->isBlockPointerType()) {
+      if (LHSTy->isVoidPointerType() || RHSTy->isVoidPointerType()) {
+        QualType destType = Context.getPointerType(Context.VoidTy);
+        ImpCastExprToType(LHS, destType, CastExpr::CK_BitCast);
+        ImpCastExprToType(RHS, destType, CastExpr::CK_BitCast);
+        return destType;
+      }
+      Diag(QuestionLoc, diag::err_typecheck_cond_incompatible_operands)
+      << LHSTy << RHSTy << LHS->getSourceRange() << RHS->getSourceRange();
+      return QualType();
+    }
+    // We have 2 block pointer types.
+    if (Context.getCanonicalType(LHSTy) == Context.getCanonicalType(RHSTy)) {
+      // Two identical block pointer types are always compatible.
+      return LHSTy;
+    }
+    // The block pointer types aren't identical, continue checking.
+    QualType lhptee = LHSTy->getAs<BlockPointerType>()->getPointeeType();
+    QualType rhptee = RHSTy->getAs<BlockPointerType>()->getPointeeType();
+    
+    if (!Context.typesAreCompatible(lhptee.getUnqualifiedType(),
+                                    rhptee.getUnqualifiedType())) {
+      Diag(QuestionLoc, diag::warn_typecheck_cond_incompatible_pointers)
+      << LHSTy << RHSTy << LHS->getSourceRange() << RHS->getSourceRange();
+      // In this situation, we assume void* type. No especially good
+      // reason, but this is what gcc does, and we do have to pick
+      // to get a consistent AST.
+      QualType incompatTy = Context.getPointerType(Context.VoidTy);
+      ImpCastExprToType(LHS, incompatTy, CastExpr::CK_BitCast);
+      ImpCastExprToType(RHS, incompatTy, CastExpr::CK_BitCast);
+      return incompatTy;
+    }
+    // The block pointer types are compatible.
+    ImpCastExprToType(LHS, LHSTy, CastExpr::CK_BitCast);
+    ImpCastExprToType(RHS, LHSTy, CastExpr::CK_BitCast);
+    return LHSTy;
+  }
+  
+  // Check constraints for C object pointers types (C99 6.5.15p3,6).
+  if (LHSTy->isPointerType() && RHSTy->isPointerType()) {
+    // get the "pointed to" types
+    QualType lhptee = LHSTy->getAs<PointerType>()->getPointeeType();
+    QualType rhptee = RHSTy->getAs<PointerType>()->getPointeeType();
+
+    // ignore qualifiers on void (C99 6.5.15p3, clause 6)
+    if (lhptee->isVoidType() && rhptee->isIncompleteOrObjectType()) {
+      // Figure out necessary qualifiers (C99 6.5.15p6)
+      QualType destPointee
+        = Context.getQualifiedType(lhptee, rhptee.getQualifiers());
+      QualType destType = Context.getPointerType(destPointee);
+      // Add qualifiers if necessary.
+      ImpCastExprToType(LHS, destType, CastExpr::CK_NoOp);
+      // Promote to void*.
+      ImpCastExprToType(RHS, destType, CastExpr::CK_BitCast);
+      return destType;
+    }
+    if (rhptee->isVoidType() && lhptee->isIncompleteOrObjectType()) {
+      QualType destPointee
+        = Context.getQualifiedType(rhptee, lhptee.getQualifiers());
+      QualType destType = Context.getPointerType(destPointee);
+      // Add qualifiers if necessary.
+      ImpCastExprToType(RHS, destType, CastExpr::CK_NoOp);
+      // Promote to void*.
+      ImpCastExprToType(LHS, destType, CastExpr::CK_BitCast);
+      return destType;
+    }
+
+    if (Context.getCanonicalType(LHSTy) == Context.getCanonicalType(RHSTy)) {
+      // Two identical pointer types are always compatible.
+      return LHSTy;
+    }
+    if (!Context.typesAreCompatible(lhptee.getUnqualifiedType(),
+                                    rhptee.getUnqualifiedType())) {
+      Diag(QuestionLoc, diag::warn_typecheck_cond_incompatible_pointers)
+        << LHSTy << RHSTy << LHS->getSourceRange() << RHS->getSourceRange();
+      // In this situation, we assume void* type. No especially good
+      // reason, but this is what gcc does, and we do have to pick
+      // to get a consistent AST.
+      QualType incompatTy = Context.getPointerType(Context.VoidTy);
+      ImpCastExprToType(LHS, incompatTy, CastExpr::CK_BitCast);
+      ImpCastExprToType(RHS, incompatTy, CastExpr::CK_BitCast);
+      return incompatTy;
+    }
+    // The pointer types are compatible.
+    // 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.
+    // FIXME: Need to calculate the composite type.
+    // FIXME: Need to add qualifiers
+    ImpCastExprToType(LHS, LHSTy, CastExpr::CK_BitCast);
+    ImpCastExprToType(RHS, LHSTy, CastExpr::CK_BitCast);
+    return LHSTy;
+  }
+
+  // GCC compatibility: soften pointer/integer mismatch.
+  if (RHSTy->isPointerType() && LHSTy->isIntegerType()) {
+    Diag(QuestionLoc, diag::warn_typecheck_cond_pointer_integer_mismatch)
+      << LHSTy << RHSTy << LHS->getSourceRange() << RHS->getSourceRange();
+    ImpCastExprToType(LHS, RHSTy, CastExpr::CK_IntegralToPointer);
+    return RHSTy;
+  }
+  if (LHSTy->isPointerType() && RHSTy->isIntegerType()) {
+    Diag(QuestionLoc, diag::warn_typecheck_cond_pointer_integer_mismatch)
+      << LHSTy << RHSTy << LHS->getSourceRange() << RHS->getSourceRange();
+    ImpCastExprToType(RHS, LHSTy, CastExpr::CK_IntegralToPointer);
+    return LHSTy;
+  }
+
+  // Otherwise, the operands are not compatible.
+  Diag(QuestionLoc, diag::err_typecheck_cond_incompatible_operands)
+    << LHSTy << RHSTy << LHS->getSourceRange() << RHS->getSourceRange();
+  return QualType();
+}
+
+/// FindCompositeObjCPointerType - Helper method to find composite type of
+/// two objective-c pointer types of the two input expressions.
+QualType Sema::FindCompositeObjCPointerType(Expr *&LHS, Expr *&RHS,
+                                        SourceLocation QuestionLoc) {
+  QualType LHSTy = LHS->getType();
+  QualType RHSTy = RHS->getType();
+  
+  // Handle things like Class and struct objc_class*.  Here we case the result
+  // to the pseudo-builtin, because that will be implicitly cast back to the
+  // redefinition type if an attempt is made to access its fields.
+  if (LHSTy->isObjCClassType() &&
+      (RHSTy.getDesugaredType() == Context.ObjCClassRedefinitionType)) {
+    ImpCastExprToType(RHS, LHSTy, CastExpr::CK_BitCast);
+    return LHSTy;
+  }
+  if (RHSTy->isObjCClassType() &&
+      (LHSTy.getDesugaredType() == Context.ObjCClassRedefinitionType)) {
+    ImpCastExprToType(LHS, RHSTy, CastExpr::CK_BitCast);
+    return RHSTy;
+  }
+  // And the same for struct objc_object* / id
+  if (LHSTy->isObjCIdType() &&
+      (RHSTy.getDesugaredType() == Context.ObjCIdRedefinitionType)) {
+    ImpCastExprToType(RHS, LHSTy, CastExpr::CK_BitCast);
+    return LHSTy;
+  }
+  if (RHSTy->isObjCIdType() &&
+      (LHSTy.getDesugaredType() == Context.ObjCIdRedefinitionType)) {
+    ImpCastExprToType(LHS, RHSTy, CastExpr::CK_BitCast);
+    return RHSTy;
+  }
+  // And the same for struct objc_selector* / SEL
+  if (Context.isObjCSelType(LHSTy) &&
+      (RHSTy.getDesugaredType() == Context.ObjCSelRedefinitionType)) {
+    ImpCastExprToType(RHS, LHSTy, CastExpr::CK_BitCast);
+    return LHSTy;
+  }
+  if (Context.isObjCSelType(RHSTy) &&
+      (LHSTy.getDesugaredType() == Context.ObjCSelRedefinitionType)) {
+    ImpCastExprToType(LHS, RHSTy, CastExpr::CK_BitCast);
+    return RHSTy;
+  }
+  // Check constraints for Objective-C object pointers types.
+  if (LHSTy->isObjCObjectPointerType() && RHSTy->isObjCObjectPointerType()) {
+    
+    if (Context.getCanonicalType(LHSTy) == Context.getCanonicalType(RHSTy)) {
+      // Two identical object pointer types are always compatible.
+      return LHSTy;
+    }
+    const ObjCObjectPointerType *LHSOPT = LHSTy->getAs<ObjCObjectPointerType>();
+    const ObjCObjectPointerType *RHSOPT = RHSTy->getAs<ObjCObjectPointerType>();
+    QualType compositeType = LHSTy;
+    
+    // If both operands are interfaces and either operand can be
+    // assigned to the other, use that type as the composite
+    // type. This allows
+    //   xxx ? (A*) a : (B*) b
+    // where B is a subclass of A.
+    //
+    // Additionally, as for assignment, if either type is 'id'
+    // allow silent coercion. Finally, if the types are
+    // incompatible then make sure to use 'id' as the composite
+    // type so the result is acceptable for sending messages to.
+    
+    // FIXME: Consider unifying with 'areComparableObjCPointerTypes'.
+    // It could return the composite type.
+    if (Context.canAssignObjCInterfaces(LHSOPT, RHSOPT)) {
+      compositeType = RHSOPT->isObjCBuiltinType() ? RHSTy : LHSTy;
+    } else if (Context.canAssignObjCInterfaces(RHSOPT, LHSOPT)) {
+      compositeType = LHSOPT->isObjCBuiltinType() ? LHSTy : RHSTy;
+    } else if ((LHSTy->isObjCQualifiedIdType() ||
+                RHSTy->isObjCQualifiedIdType()) &&
+               Context.ObjCQualifiedIdTypesAreCompatible(LHSTy, RHSTy, true)) {
+      // Need to handle "id<xx>" explicitly.
+      // GCC allows qualified id and any Objective-C type to devolve to
+      // id. Currently localizing to here until clear this should be
+      // part of ObjCQualifiedIdTypesAreCompatible.
+      compositeType = Context.getObjCIdType();
+    } else if (LHSTy->isObjCIdType() || RHSTy->isObjCIdType()) {
+      compositeType = Context.getObjCIdType();
+    } else if (!(compositeType = 
+                 Context.areCommonBaseCompatible(LHSOPT, RHSOPT)).isNull())
+      ;
+    else {
+      Diag(QuestionLoc, diag::ext_typecheck_cond_incompatible_operands)
+      << LHSTy << RHSTy
+      << LHS->getSourceRange() << RHS->getSourceRange();
+      QualType incompatTy = Context.getObjCIdType();
+      ImpCastExprToType(LHS, incompatTy, CastExpr::CK_BitCast);
+      ImpCastExprToType(RHS, incompatTy, CastExpr::CK_BitCast);
+      return incompatTy;
+    }
+    // The object pointer types are compatible.
+    ImpCastExprToType(LHS, compositeType, CastExpr::CK_BitCast);
+    ImpCastExprToType(RHS, compositeType, CastExpr::CK_BitCast);
+    return compositeType;
+  }
+  // Check Objective-C object pointer types and 'void *'
+  if (LHSTy->isVoidPointerType() && RHSTy->isObjCObjectPointerType()) {
+    QualType lhptee = LHSTy->getAs<PointerType>()->getPointeeType();
+    QualType rhptee = RHSTy->getAs<ObjCObjectPointerType>()->getPointeeType();
+    QualType destPointee
+    = Context.getQualifiedType(lhptee, rhptee.getQualifiers());
+    QualType destType = Context.getPointerType(destPointee);
+    // Add qualifiers if necessary.
+    ImpCastExprToType(LHS, destType, CastExpr::CK_NoOp);
+    // Promote to void*.
+    ImpCastExprToType(RHS, destType, CastExpr::CK_BitCast);
+    return destType;
+  }
+  if (LHSTy->isObjCObjectPointerType() && RHSTy->isVoidPointerType()) {
+    QualType lhptee = LHSTy->getAs<ObjCObjectPointerType>()->getPointeeType();
+    QualType rhptee = RHSTy->getAs<PointerType>()->getPointeeType();
+    QualType destPointee
+    = Context.getQualifiedType(rhptee, lhptee.getQualifiers());
+    QualType destType = Context.getPointerType(destPointee);
+    // Add qualifiers if necessary.
+    ImpCastExprToType(RHS, destType, CastExpr::CK_NoOp);
+    // Promote to void*.
+    ImpCastExprToType(LHS, destType, CastExpr::CK_BitCast);
+    return destType;
+  }
+  return QualType();
+}
+
+/// ActOnConditionalOp - Parse a ?: operation.  Note that 'LHS' may be null
+/// in the case of a the GNU conditional expr extension.
+Action::OwningExprResult Sema::ActOnConditionalOp(SourceLocation QuestionLoc,
+                                                  SourceLocation ColonLoc,
+                                                  ExprArg Cond, ExprArg LHS,
+                                                  ExprArg RHS) {
+  Expr *CondExpr = (Expr *) Cond.get();
+  Expr *LHSExpr = (Expr *) LHS.get(), *RHSExpr = (Expr *) RHS.get();
+
+  // If this is the gnu "x ?: y" extension, analyze the types as though the LHS
+  // was the condition.
+  bool isLHSNull = LHSExpr == 0;
+  if (isLHSNull)
+    LHSExpr = CondExpr;
+
+  QualType result = CheckConditionalOperands(CondExpr, LHSExpr,
+                                             RHSExpr, QuestionLoc);
+  if (result.isNull())
+    return ExprError();
+
+  Cond.release();
+  LHS.release();
+  RHS.release();
+  return Owned(new (Context) ConditionalOperator(CondExpr, QuestionLoc,
+                                                 isLHSNull ? 0 : LHSExpr,
+                                                 ColonLoc, RHSExpr, result));
+}
+
+// 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::AssignConvertType
+Sema::CheckPointerTypesForAssignment(QualType lhsType, QualType rhsType) {
+  QualType lhptee, rhptee;
+
+  if ((lhsType->isObjCClassType() &&
+       (rhsType.getDesugaredType() == Context.ObjCClassRedefinitionType)) ||
+     (rhsType->isObjCClassType() &&
+       (lhsType.getDesugaredType() == Context.ObjCClassRedefinitionType))) {
+      return Compatible;
+  }
+
+  // get the "pointed to" type (ignoring qualifiers at the top level)
+  lhptee = lhsType->getAs<PointerType>()->getPointeeType();
+  rhptee = rhsType->getAs<PointerType>()->getPointeeType();
+
+  // make sure we operate on the canonical type
+  lhptee = Context.getCanonicalType(lhptee);
+  rhptee = Context.getCanonicalType(rhptee);
+
+  AssignConvertType ConvTy = 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;
+  // FIXME: Handle ExtQualType
+  if (!lhptee.isAtLeastAsQualifiedAs(rhptee))
+    ConvTy = 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->isVoidType()) {
+    if (rhptee->isIncompleteOrObjectType())
+      return ConvTy;
+
+    // As an extension, we allow cast to/from void* to function pointer.
+    assert(rhptee->isFunctionType());
+    return FunctionVoidPointer;
+  }
+
+  if (rhptee->isVoidType()) {
+    if (lhptee->isIncompleteOrObjectType())
+      return ConvTy;
+
+    // As an extension, we allow cast to/from void* to function pointer.
+    assert(lhptee->isFunctionType());
+    return FunctionVoidPointer;
+  }
+  // C99 6.5.16.1p1 (constraint 3): both operands are pointers to qualified or
+  // unqualified versions of compatible types, ...
+  lhptee = lhptee.getUnqualifiedType();
+  rhptee = rhptee.getUnqualifiedType();
+  if (!Context.typesAreCompatible(lhptee, rhptee)) {
+    // Check if the pointee types are compatible ignoring the sign.
+    // We explicitly check for char so that we catch "char" vs
+    // "unsigned char" on systems where "char" is unsigned.
+    if (lhptee->isCharType())
+      lhptee = Context.UnsignedCharTy;
+    else if (lhptee->isSignedIntegerType())
+      lhptee = Context.getCorrespondingUnsignedType(lhptee);
+    
+    if (rhptee->isCharType())
+      rhptee = Context.UnsignedCharTy;
+    else if (rhptee->isSignedIntegerType())
+      rhptee = Context.getCorrespondingUnsignedType(rhptee);
+
+    if (lhptee == rhptee) {
+      // Types are compatible ignoring the sign. Qualifier incompatibility
+      // takes priority over sign incompatibility because the sign
+      // warning can be disabled.
+      if (ConvTy != Compatible)
+        return ConvTy;
+      return IncompatiblePointerSign;
+    }
+    
+    // If we are a multi-level pointer, it's possible that our issue is simply
+    // one of qualification - e.g. char ** -> const char ** is not allowed. If
+    // the eventual target type is the same and the pointers have the same
+    // level of indirection, this must be the issue.
+    if (lhptee->isPointerType() && rhptee->isPointerType()) {
+      do {
+        lhptee = lhptee->getAs<PointerType>()->getPointeeType();
+        rhptee = rhptee->getAs<PointerType>()->getPointeeType();
+      
+        lhptee = Context.getCanonicalType(lhptee);
+        rhptee = Context.getCanonicalType(rhptee);
+      } while (lhptee->isPointerType() && rhptee->isPointerType());
+      
+      if (Context.hasSameUnqualifiedType(lhptee, rhptee))
+        return IncompatibleNestedPointerQualifiers;
+    }
+    
+    // General pointer incompatibility takes priority over qualifiers.
+    return IncompatiblePointer;
+  }
+  return ConvTy;
+}
+
+/// CheckBlockPointerTypesForAssignment - This routine determines whether two
+/// block pointer types are compatible or whether a block and normal pointer
+/// are compatible. It is more restrict than comparing two function pointer
+// types.
+Sema::AssignConvertType
+Sema::CheckBlockPointerTypesForAssignment(QualType lhsType,
+                                          QualType rhsType) {
+  QualType lhptee, rhptee;
+
+  // get the "pointed to" type (ignoring qualifiers at the top level)
+  lhptee = lhsType->getAs<BlockPointerType>()->getPointeeType();
+  rhptee = rhsType->getAs<BlockPointerType>()->getPointeeType();
+
+  // make sure we operate on the canonical type
+  lhptee = Context.getCanonicalType(lhptee);
+  rhptee = Context.getCanonicalType(rhptee);
+
+  AssignConvertType ConvTy = Compatible;
+
+  // For blocks we enforce that qualifiers are identical.
+  if (lhptee.getLocalCVRQualifiers() != rhptee.getLocalCVRQualifiers())
+    ConvTy = CompatiblePointerDiscardsQualifiers;
+
+  if (!Context.typesAreCompatible(lhptee, rhptee))
+    return IncompatibleBlockPointer;
+  return ConvTy;
+}
+
+/// CheckObjCPointerTypesForAssignment - Compares two objective-c pointer types
+/// for assignment compatibility.
+Sema::AssignConvertType
+Sema::CheckObjCPointerTypesForAssignment(QualType lhsType, QualType rhsType) {
+  if (lhsType->isObjCBuiltinType() || rhsType->isObjCBuiltinType())
+    return Compatible;
+  QualType lhptee = 
+  lhsType->getAs<ObjCObjectPointerType>()->getPointeeType();
+  QualType rhptee = 
+  rhsType->getAs<ObjCObjectPointerType>()->getPointeeType();
+  // make sure we operate on the canonical type
+  lhptee = Context.getCanonicalType(lhptee);
+  rhptee = Context.getCanonicalType(rhptee);
+  if (!lhptee.isAtLeastAsQualifiedAs(rhptee))
+    return CompatiblePointerDiscardsQualifiers;
+  
+  if (Context.typesAreCompatible(lhsType, rhsType))
+    return Compatible;
+  if (lhsType->isObjCQualifiedIdType() || rhsType->isObjCQualifiedIdType())
+    return IncompatibleObjCQualifiedId;
+  return IncompatiblePointer;  
+}
+
+/// 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.
+///
+Sema::AssignConvertType
+Sema::CheckAssignmentConstraints(QualType lhsType, QualType rhsType) {
+  // Get canonical types.  We're not formatting these types, just comparing
+  // them.
+  lhsType = Context.getCanonicalType(lhsType).getUnqualifiedType();
+  rhsType = Context.getCanonicalType(rhsType).getUnqualifiedType();
+
+  if (lhsType == rhsType)
+    return Compatible; // Common case: fast path an exact match.
+
+  if ((lhsType->isObjCClassType() &&
+       (rhsType.getDesugaredType() == Context.ObjCClassRedefinitionType)) ||
+     (rhsType->isObjCClassType() &&
+       (lhsType.getDesugaredType() == Context.ObjCClassRedefinitionType))) {
+      return Compatible;
+  }
+
+  // If the left-hand side is a reference type, then we are in a
+  // (rare!) case where we've allowed the use of references in C,
+  // e.g., as a parameter type in a built-in function. In this case,
+  // just make sure that the type referenced is compatible with the
+  // right-hand side type. The caller is responsible for adjusting
+  // lhsType so that the resulting expression does not have reference
+  // type.
+  if (const ReferenceType *lhsTypeRef = lhsType->getAs<ReferenceType>()) {
+    if (Context.typesAreCompatible(lhsTypeRef->getPointeeType(), rhsType))
+      return Compatible;
+    return Incompatible;
+  }
+  // Allow scalar to ExtVector assignments, and assignments of an ExtVector type
+  // to the same ExtVector type.
+  if (lhsType->isExtVectorType()) {
+    if (rhsType->isExtVectorType())
+      return lhsType == rhsType ? Compatible : Incompatible;
+    if (!rhsType->isVectorType() && rhsType->isArithmeticType())
+      return Compatible;
+  }
+
+  if (lhsType->isVectorType() || rhsType->isVectorType()) {
+    // If we are allowing lax vector conversions, and LHS and RHS are both
+    // vectors, the total size only needs to be the same. This is a bitcast;
+    // no bits are changed but the result type is different.
+    if (getLangOptions().LaxVectorConversions &&
+        lhsType->isVectorType() && rhsType->isVectorType()) {
+      if (Context.getTypeSize(lhsType) == Context.getTypeSize(rhsType))
+        return IncompatibleVectors;
+    }
+    return Incompatible;
+  }
+
+  if (lhsType->isArithmeticType() && rhsType->isArithmeticType())
+    return Compatible;
+
+  if (isa<PointerType>(lhsType)) {
+    if (rhsType->isIntegerType())
+      return IntToPointer;
+
+    if (isa<PointerType>(rhsType))
+      return CheckPointerTypesForAssignment(lhsType, rhsType);
+
+    // In general, C pointers are not compatible with ObjC object pointers.
+    if (isa<ObjCObjectPointerType>(rhsType)) {
+      if (lhsType->isVoidPointerType()) // an exception to the rule.
+        return Compatible;
+      return IncompatiblePointer;
+    }
+    if (rhsType->getAs<BlockPointerType>()) {
+      if (lhsType->getAs<PointerType>()->getPointeeType()->isVoidType())
+        return Compatible;
+
+      // Treat block pointers as objects.
+      if (getLangOptions().ObjC1 && lhsType->isObjCIdType())
+        return Compatible;
+    }
+    return Incompatible;
+  }
+
+  if (isa<BlockPointerType>(lhsType)) {
+    if (rhsType->isIntegerType())
+      return IntToBlockPointer;
+
+    // Treat block pointers as objects.
+    if (getLangOptions().ObjC1 && rhsType->isObjCIdType())
+      return Compatible;
+
+    if (rhsType->isBlockPointerType())
+      return CheckBlockPointerTypesForAssignment(lhsType, rhsType);
+
+    if (const PointerType *RHSPT = rhsType->getAs<PointerType>()) {
+      if (RHSPT->getPointeeType()->isVoidType())
+        return Compatible;
+    }
+    return Incompatible;
+  }
+
+  if (isa<ObjCObjectPointerType>(lhsType)) {
+    if (rhsType->isIntegerType())
+      return IntToPointer;
+
+    // In general, C pointers are not compatible with ObjC object pointers.
+    if (isa<PointerType>(rhsType)) {
+      if (rhsType->isVoidPointerType()) // an exception to the rule.
+        return Compatible;
+      return IncompatiblePointer;
+    }
+    if (rhsType->isObjCObjectPointerType()) {
+      return CheckObjCPointerTypesForAssignment(lhsType, rhsType);
+    }
+    if (const PointerType *RHSPT = rhsType->getAs<PointerType>()) {
+      if (RHSPT->getPointeeType()->isVoidType())
+        return Compatible;
+    }
+    // Treat block pointers as objects.
+    if (rhsType->isBlockPointerType())
+      return Compatible;
+    return Incompatible;
+  }
+  if (isa<PointerType>(rhsType)) {
+    // C99 6.5.16.1p1: the left operand is _Bool and the right is a pointer.
+    if (lhsType == Context.BoolTy)
+      return Compatible;
+
+    if (lhsType->isIntegerType())
+      return PointerToInt;
+
+    if (isa<PointerType>(lhsType))
+      return CheckPointerTypesForAssignment(lhsType, rhsType);
+
+    if (isa<BlockPointerType>(lhsType) &&
+        rhsType->getAs<PointerType>()->getPointeeType()->isVoidType())
+      return Compatible;
+    return Incompatible;
+  }
+  if (isa<ObjCObjectPointerType>(rhsType)) {
+    // C99 6.5.16.1p1: the left operand is _Bool and the right is a pointer.
+    if (lhsType == Context.BoolTy)
+      return Compatible;
+
+    if (lhsType->isIntegerType())
+      return PointerToInt;
+
+    // In general, C pointers are not compatible with ObjC object pointers.
+    if (isa<PointerType>(lhsType)) {
+      if (lhsType->isVoidPointerType()) // an exception to the rule.
+        return Compatible;
+      return IncompatiblePointer;
+    }
+    if (isa<BlockPointerType>(lhsType) &&
+        rhsType->getAs<PointerType>()->getPointeeType()->isVoidType())
+      return Compatible;
+    return Incompatible;
+  }
+
+  if (isa<TagType>(lhsType) && isa<TagType>(rhsType)) {
+    if (Context.typesAreCompatible(lhsType, rhsType))
+      return Compatible;
+  }
+  return Incompatible;
+}
+
+/// \brief Constructs a transparent union from an expression that is
+/// used to initialize the transparent union.
+static void ConstructTransparentUnion(ASTContext &C, Expr *&E,
+                                      QualType UnionType, FieldDecl *Field) {
+  // Build an initializer list that designates the appropriate member
+  // of the transparent union.
+  InitListExpr *Initializer = new (C) InitListExpr(SourceLocation(),
+                                                   &E, 1,
+                                                   SourceLocation());
+  Initializer->setType(UnionType);
+  Initializer->setInitializedFieldInUnion(Field);
+
+  // Build a compound literal constructing a value of the transparent
+  // union type from this initializer list.
+  TypeSourceInfo *unionTInfo = C.getTrivialTypeSourceInfo(UnionType);
+  E = new (C) CompoundLiteralExpr(SourceLocation(), unionTInfo, UnionType,
+                                  Initializer, false);
+}
+
+Sema::AssignConvertType
+Sema::CheckTransparentUnionArgumentConstraints(QualType ArgType, Expr *&rExpr) {
+  QualType FromType = rExpr->getType();
+
+  // If the ArgType is a Union type, we want to handle a potential
+  // transparent_union GCC extension.
+  const RecordType *UT = ArgType->getAsUnionType();
+  if (!UT || !UT->getDecl()->hasAttr<TransparentUnionAttr>())
+    return Incompatible;
+
+  // The field to initialize within the transparent union.
+  RecordDecl *UD = UT->getDecl();
+  FieldDecl *InitField = 0;
+  // It's compatible if the expression matches any of the fields.
+  for (RecordDecl::field_iterator it = UD->field_begin(),
+         itend = UD->field_end();
+       it != itend; ++it) {
+    if (it->getType()->isPointerType()) {
+      // If the transparent union contains a pointer type, we allow:
+      // 1) void pointer
+      // 2) null pointer constant
+      if (FromType->isPointerType())
+        if (FromType->getAs<PointerType>()->getPointeeType()->isVoidType()) {
+          ImpCastExprToType(rExpr, it->getType(), CastExpr::CK_BitCast);
+          InitField = *it;
+          break;
+        }
+
+      if (rExpr->isNullPointerConstant(Context, 
+                                       Expr::NPC_ValueDependentIsNull)) {
+        ImpCastExprToType(rExpr, it->getType(), CastExpr::CK_IntegralToPointer);
+        InitField = *it;
+        break;
+      }
+    }
+
+    if (CheckAssignmentConstraints(it->getType(), rExpr->getType())
+          == Compatible) {
+      InitField = *it;
+      break;
+    }
+  }
+
+  if (!InitField)
+    return Incompatible;
+
+  ConstructTransparentUnion(Context, rExpr, ArgType, InitField);
+  return Compatible;
+}
+
+Sema::AssignConvertType
+Sema::CheckSingleAssignmentConstraints(QualType lhsType, Expr *&rExpr) {
+  if (getLangOptions().CPlusPlus) {
+    if (!lhsType->isRecordType()) {
+      // C++ 5.17p3: If the left operand is not of class type, the
+      // expression is implicitly converted (C++ 4) to the
+      // cv-unqualified type of the left operand.
+      if (PerformImplicitConversion(rExpr, lhsType.getUnqualifiedType(),
+                                    AA_Assigning))
+        return Incompatible;
+      return Compatible;
+    }
+
+    // FIXME: Currently, we fall through and treat C++ classes like C
+    // structures.
+  }
+
+  // C99 6.5.16.1p1: the left operand is a pointer and the right is
+  // a null pointer constant.
+  if ((lhsType->isPointerType() ||
+       lhsType->isObjCObjectPointerType() ||
+       lhsType->isBlockPointerType())
+      && rExpr->isNullPointerConstant(Context, 
+                                      Expr::NPC_ValueDependentIsNull)) {
+    ImpCastExprToType(rExpr, lhsType, CastExpr::CK_Unknown);
+    return Compatible;
+  }
+
+  // This check seems unnatural, however it is necessary to ensure the proper
+  // conversion of functions/arrays. If the conversion were done for all
+  // DeclExpr's (created by ActOnIdExpression), it would mess up the unary
+  // expressions that surpress this implicit conversion (&, sizeof).
+  //
+  // Suppress this for references: C++ 8.5.3p5.
+  if (!lhsType->isReferenceType())
+    DefaultFunctionArrayLvalueConversion(rExpr);
+
+  Sema::AssignConvertType result =
+    CheckAssignmentConstraints(lhsType, rExpr->getType());
+
+  // C99 6.5.16.1p2: The value of the right operand is converted to the
+  // type of the assignment expression.
+  // CheckAssignmentConstraints allows the left-hand side to be a reference,
+  // so that we can use references in built-in functions even in C.
+  // The getNonReferenceType() call makes sure that the resulting expression
+  // does not have reference type.
+  if (result != Incompatible && rExpr->getType() != lhsType)
+    ImpCastExprToType(rExpr, lhsType.getNonReferenceType(),
+                      CastExpr::CK_Unknown);
+  return result;
+}
+
+QualType Sema::InvalidOperands(SourceLocation Loc, Expr *&lex, Expr *&rex) {
+  Diag(Loc, diag::err_typecheck_invalid_operands)
+    << lex->getType() << rex->getType()
+    << lex->getSourceRange() << rex->getSourceRange();
+  return QualType();
+}
+
+QualType Sema::CheckVectorOperands(SourceLocation Loc, Expr *&lex, Expr *&rex) {
+  // For conversion purposes, we ignore any qualifiers.
+  // For example, "const float" and "float" are equivalent.
+  QualType lhsType =
+    Context.getCanonicalType(lex->getType()).getUnqualifiedType();
+  QualType rhsType =
+    Context.getCanonicalType(rex->getType()).getUnqualifiedType();
+
+  // If the vector types are identical, return.
+  if (lhsType == rhsType)
+    return lhsType;
+
+  // Handle the case of a vector & extvector type of the same size and element
+  // type.  It would be nice if we only had one vector type someday.
+  if (getLangOptions().LaxVectorConversions) {
+    // FIXME: Should we warn here?
+    if (const VectorType *LV = lhsType->getAs<VectorType>()) {
+      if (const VectorType *RV = rhsType->getAs<VectorType>())
+        if (LV->getElementType() == RV->getElementType() &&
+            LV->getNumElements() == RV->getNumElements()) {
+          return lhsType->isExtVectorType() ? lhsType : rhsType;
+        }
+    }
+  }
+
+  // Canonicalize the ExtVector to the LHS, remember if we swapped so we can
+  // swap back (so that we don't reverse the inputs to a subtract, for instance.
+  bool swapped = false;
+  if (rhsType->isExtVectorType()) {
+    swapped = true;
+    std::swap(rex, lex);
+    std::swap(rhsType, lhsType);
+  }
+
+  // Handle the case of an ext vector and scalar.
+  if (const ExtVectorType *LV = lhsType->getAs<ExtVectorType>()) {
+    QualType EltTy = LV->getElementType();
+    if (EltTy->isIntegralType() && rhsType->isIntegralType()) {
+      if (Context.getIntegerTypeOrder(EltTy, rhsType) >= 0) {
+        ImpCastExprToType(rex, lhsType, CastExpr::CK_IntegralCast);
+        if (swapped) std::swap(rex, lex);
+        return lhsType;
+      }
+    }
+    if (EltTy->isRealFloatingType() && rhsType->isScalarType() &&
+        rhsType->isRealFloatingType()) {
+      if (Context.getFloatingTypeOrder(EltTy, rhsType) >= 0) {
+        ImpCastExprToType(rex, lhsType, CastExpr::CK_FloatingCast);
+        if (swapped) std::swap(rex, lex);
+        return lhsType;
+      }
+    }
+  }
+
+  // Vectors of different size or scalar and non-ext-vector are errors.
+  Diag(Loc, diag::err_typecheck_vector_not_convertable)
+    << lex->getType() << rex->getType()
+    << lex->getSourceRange() << rex->getSourceRange();
+  return QualType();
+}
+
+QualType Sema::CheckMultiplyDivideOperands(
+  Expr *&lex, Expr *&rex, SourceLocation Loc, bool isCompAssign, bool isDiv) {
+  if (lex->getType()->isVectorType() || rex->getType()->isVectorType())
+    return CheckVectorOperands(Loc, lex, rex);
+
+  QualType compType = UsualArithmeticConversions(lex, rex, isCompAssign);
+
+  if (!lex->getType()->isArithmeticType() ||
+      !rex->getType()->isArithmeticType())
+    return InvalidOperands(Loc, lex, rex);
+  
+  // Check for division by zero.
+  if (isDiv &&
+      rex->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNotNull))
+    DiagRuntimeBehavior(Loc, PDiag(diag::warn_division_by_zero) 
+                                     << rex->getSourceRange());
+  
+  return compType;
+}
+
+QualType Sema::CheckRemainderOperands(
+  Expr *&lex, Expr *&rex, SourceLocation Loc, bool isCompAssign) {
+  if (lex->getType()->isVectorType() || rex->getType()->isVectorType()) {
+    if (lex->getType()->isIntegerType() && rex->getType()->isIntegerType())
+      return CheckVectorOperands(Loc, lex, rex);
+    return InvalidOperands(Loc, lex, rex);
+  }
+
+  QualType compType = UsualArithmeticConversions(lex, rex, isCompAssign);
+
+  if (!lex->getType()->isIntegerType() || !rex->getType()->isIntegerType())
+    return InvalidOperands(Loc, lex, rex);
+  
+  // Check for remainder by zero.
+  if (rex->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNotNull))
+    DiagRuntimeBehavior(Loc, PDiag(diag::warn_remainder_by_zero)
+                                 << rex->getSourceRange());
+  
+  return compType;
+}
+
+QualType Sema::CheckAdditionOperands( // C99 6.5.6
+  Expr *&lex, Expr *&rex, SourceLocation Loc, QualType* CompLHSTy) {
+  if (lex->getType()->isVectorType() || rex->getType()->isVectorType()) {
+    QualType compType = CheckVectorOperands(Loc, lex, rex);
+    if (CompLHSTy) *CompLHSTy = compType;
+    return compType;
+  }
+
+  QualType compType = UsualArithmeticConversions(lex, rex, CompLHSTy);
+
+  // handle the common case first (both operands are arithmetic).
+  if (lex->getType()->isArithmeticType() &&
+      rex->getType()->isArithmeticType()) {
+    if (CompLHSTy) *CompLHSTy = compType;
+    return compType;
+  }
+
+  // Put any potential pointer into PExp
+  Expr* PExp = lex, *IExp = rex;
+  if (IExp->getType()->isAnyPointerType())
+    std::swap(PExp, IExp);
+
+  if (PExp->getType()->isAnyPointerType()) {
+
+    if (IExp->getType()->isIntegerType()) {
+      QualType PointeeTy = PExp->getType()->getPointeeType();
+
+      // Check for arithmetic on pointers to incomplete types.
+      if (PointeeTy->isVoidType()) {
+        if (getLangOptions().CPlusPlus) {
+          Diag(Loc, diag::err_typecheck_pointer_arith_void_type)
+            << lex->getSourceRange() << rex->getSourceRange();
+          return QualType();
+        }
+
+        // GNU extension: arithmetic on pointer to void
+        Diag(Loc, diag::ext_gnu_void_ptr)
+          << lex->getSourceRange() << rex->getSourceRange();
+      } else if (PointeeTy->isFunctionType()) {
+        if (getLangOptions().CPlusPlus) {
+          Diag(Loc, diag::err_typecheck_pointer_arith_function_type)
+            << lex->getType() << lex->getSourceRange();
+          return QualType();
+        }
+
+        // GNU extension: arithmetic on pointer to function
+        Diag(Loc, diag::ext_gnu_ptr_func_arith)
+          << lex->getType() << lex->getSourceRange();
+      } else {
+        // Check if we require a complete type.
+        if (((PExp->getType()->isPointerType() &&
+              !PExp->getType()->isDependentType()) ||
+              PExp->getType()->isObjCObjectPointerType()) &&
+             RequireCompleteType(Loc, PointeeTy,
+                           PDiag(diag::err_typecheck_arithmetic_incomplete_type)
+                             << PExp->getSourceRange()
+                             << PExp->getType()))
+          return QualType();
+      }
+      // Diagnose bad cases where we step over interface counts.
+      if (PointeeTy->isObjCInterfaceType() && LangOpts.ObjCNonFragileABI) {
+        Diag(Loc, diag::err_arithmetic_nonfragile_interface)
+          << PointeeTy << PExp->getSourceRange();
+        return QualType();
+      }
+
+      if (CompLHSTy) {
+        QualType LHSTy = Context.isPromotableBitField(lex);
+        if (LHSTy.isNull()) {
+          LHSTy = lex->getType();
+          if (LHSTy->isPromotableIntegerType())
+            LHSTy = Context.getPromotedIntegerType(LHSTy);
+        }
+        *CompLHSTy = LHSTy;
+      }
+      return PExp->getType();
+    }
+  }
+
+  return InvalidOperands(Loc, lex, rex);
+}
+
+// C99 6.5.6
+QualType Sema::CheckSubtractionOperands(Expr *&lex, Expr *&rex,
+                                        SourceLocation Loc, QualType* CompLHSTy) {
+  if (lex->getType()->isVectorType() || rex->getType()->isVectorType()) {
+    QualType compType = CheckVectorOperands(Loc, lex, rex);
+    if (CompLHSTy) *CompLHSTy = compType;
+    return compType;
+  }
+
+  QualType compType = UsualArithmeticConversions(lex, rex, CompLHSTy);
+
+  // Enforce type constraints: C99 6.5.6p3.
+
+  // Handle the common case first (both operands are arithmetic).
+  if (lex->getType()->isArithmeticType()
+      && rex->getType()->isArithmeticType()) {
+    if (CompLHSTy) *CompLHSTy = compType;
+    return compType;
+  }
+
+  // Either ptr - int   or   ptr - ptr.
+  if (lex->getType()->isAnyPointerType()) {
+    QualType lpointee = lex->getType()->getPointeeType();
+
+    // The LHS must be an completely-defined object type.
+
+    bool ComplainAboutVoid = false;
+    Expr *ComplainAboutFunc = 0;
+    if (lpointee->isVoidType()) {
+      if (getLangOptions().CPlusPlus) {
+        Diag(Loc, diag::err_typecheck_pointer_arith_void_type)
+          << lex->getSourceRange() << rex->getSourceRange();
+        return QualType();
+      }
+
+      // GNU C extension: arithmetic on pointer to void
+      ComplainAboutVoid = true;
+    } else if (lpointee->isFunctionType()) {
+      if (getLangOptions().CPlusPlus) {
+        Diag(Loc, diag::err_typecheck_pointer_arith_function_type)
+          << lex->getType() << lex->getSourceRange();
+        return QualType();
+      }
+
+      // GNU C extension: arithmetic on pointer to function
+      ComplainAboutFunc = lex;
+    } else if (!lpointee->isDependentType() &&
+               RequireCompleteType(Loc, lpointee,
+                                   PDiag(diag::err_typecheck_sub_ptr_object)
+                                     << lex->getSourceRange()
+                                     << lex->getType()))
+      return QualType();
+
+    // Diagnose bad cases where we step over interface counts.
+    if (lpointee->isObjCInterfaceType() && LangOpts.ObjCNonFragileABI) {
+      Diag(Loc, diag::err_arithmetic_nonfragile_interface)
+        << lpointee << lex->getSourceRange();
+      return QualType();
+    }
+
+    // The result type of a pointer-int computation is the pointer type.
+    if (rex->getType()->isIntegerType()) {
+      if (ComplainAboutVoid)
+        Diag(Loc, diag::ext_gnu_void_ptr)
+          << lex->getSourceRange() << rex->getSourceRange();
+      if (ComplainAboutFunc)
+        Diag(Loc, diag::ext_gnu_ptr_func_arith)
+          << ComplainAboutFunc->getType()
+          << ComplainAboutFunc->getSourceRange();
+
+      if (CompLHSTy) *CompLHSTy = lex->getType();
+      return lex->getType();
+    }
+
+    // Handle pointer-pointer subtractions.
+    if (const PointerType *RHSPTy = rex->getType()->getAs<PointerType>()) {
+      QualType rpointee = RHSPTy->getPointeeType();
+
+      // RHS must be a completely-type object type.
+      // Handle the GNU void* extension.
+      if (rpointee->isVoidType()) {
+        if (getLangOptions().CPlusPlus) {
+          Diag(Loc, diag::err_typecheck_pointer_arith_void_type)
+            << lex->getSourceRange() << rex->getSourceRange();
+          return QualType();
+        }
+
+        ComplainAboutVoid = true;
+      } else if (rpointee->isFunctionType()) {
+        if (getLangOptions().CPlusPlus) {
+          Diag(Loc, diag::err_typecheck_pointer_arith_function_type)
+            << rex->getType() << rex->getSourceRange();
+          return QualType();
+        }
+
+        // GNU extension: arithmetic on pointer to function
+        if (!ComplainAboutFunc)
+          ComplainAboutFunc = rex;
+      } else if (!rpointee->isDependentType() &&
+                 RequireCompleteType(Loc, rpointee,
+                                     PDiag(diag::err_typecheck_sub_ptr_object)
+                                       << rex->getSourceRange()
+                                       << rex->getType()))
+        return QualType();
+
+      if (getLangOptions().CPlusPlus) {
+        // Pointee types must be the same: C++ [expr.add]
+        if (!Context.hasSameUnqualifiedType(lpointee, rpointee)) {
+          Diag(Loc, diag::err_typecheck_sub_ptr_compatible)
+            << lex->getType() << rex->getType()
+            << lex->getSourceRange() << rex->getSourceRange();
+          return QualType();
+        }
+      } else {
+        // Pointee types must be compatible C99 6.5.6p3
+        if (!Context.typesAreCompatible(
+                Context.getCanonicalType(lpointee).getUnqualifiedType(),
+                Context.getCanonicalType(rpointee).getUnqualifiedType())) {
+          Diag(Loc, diag::err_typecheck_sub_ptr_compatible)
+            << lex->getType() << rex->getType()
+            << lex->getSourceRange() << rex->getSourceRange();
+          return QualType();
+        }
+      }
+
+      if (ComplainAboutVoid)
+        Diag(Loc, diag::ext_gnu_void_ptr)
+          << lex->getSourceRange() << rex->getSourceRange();
+      if (ComplainAboutFunc)
+        Diag(Loc, diag::ext_gnu_ptr_func_arith)
+          << ComplainAboutFunc->getType()
+          << ComplainAboutFunc->getSourceRange();
+
+      if (CompLHSTy) *CompLHSTy = lex->getType();
+      return Context.getPointerDiffType();
+    }
+  }
+
+  return InvalidOperands(Loc, lex, rex);
+}
+
+// C99 6.5.7
+QualType Sema::CheckShiftOperands(Expr *&lex, Expr *&rex, SourceLocation Loc,
+                                  bool isCompAssign) {
+  // C99 6.5.7p2: Each of the operands shall have integer type.
+  if (!lex->getType()->isIntegerType() || !rex->getType()->isIntegerType())
+    return InvalidOperands(Loc, lex, rex);
+
+  // Vector shifts promote their scalar inputs to vector type.
+  if (lex->getType()->isVectorType() || rex->getType()->isVectorType())
+    return CheckVectorOperands(Loc, lex, rex);
+
+  // Shifts don't perform usual arithmetic conversions, they just do integer
+  // promotions on each operand. C99 6.5.7p3
+  QualType LHSTy = Context.isPromotableBitField(lex);
+  if (LHSTy.isNull()) {
+    LHSTy = lex->getType();
+    if (LHSTy->isPromotableIntegerType())
+      LHSTy = Context.getPromotedIntegerType(LHSTy);
+  }
+  if (!isCompAssign)
+    ImpCastExprToType(lex, LHSTy, CastExpr::CK_IntegralCast);
+
+  UsualUnaryConversions(rex);
+
+  // Sanity-check shift operands
+  llvm::APSInt Right;
+  // Check right/shifter operand
+  if (!rex->isValueDependent() &&
+      rex->isIntegerConstantExpr(Right, Context)) {
+    if (Right.isNegative())
+      Diag(Loc, diag::warn_shift_negative) << rex->getSourceRange();
+    else {
+      llvm::APInt LeftBits(Right.getBitWidth(),
+                          Context.getTypeSize(lex->getType()));
+      if (Right.uge(LeftBits))
+        Diag(Loc, diag::warn_shift_gt_typewidth) << rex->getSourceRange();
+    }
+  }
+
+  // "The type of the result is that of the promoted left operand."
+  return LHSTy;
+}
+
+// C99 6.5.8, C++ [expr.rel]
+QualType Sema::CheckCompareOperands(Expr *&lex, Expr *&rex, SourceLocation Loc,
+                                    unsigned OpaqueOpc, bool isRelational) {
+  BinaryOperator::Opcode Opc = (BinaryOperator::Opcode)OpaqueOpc;
+
+  // Handle vector comparisons separately.
+  if (lex->getType()->isVectorType() || rex->getType()->isVectorType())
+    return CheckVectorCompareOperands(lex, rex, Loc, isRelational);
+
+  CheckSignCompare(lex, rex, Loc, diag::warn_mixed_sign_comparison,
+                   (Opc == BinaryOperator::EQ || Opc == BinaryOperator::NE));
+
+  // C99 6.5.8p3 / C99 6.5.9p4
+  if (lex->getType()->isArithmeticType() && rex->getType()->isArithmeticType())
+    UsualArithmeticConversions(lex, rex);
+  else {
+    UsualUnaryConversions(lex);
+    UsualUnaryConversions(rex);
+  }
+  QualType lType = lex->getType();
+  QualType rType = rex->getType();
+
+  if (!lType->isFloatingType()
+      && !(lType->isBlockPointerType() && isRelational)) {
+    // For non-floating point types, check for self-comparisons of the form
+    // x == x, x != x, x < x, etc.  These always evaluate to a constant, and
+    // often indicate logic errors in the program.
+    // NOTE: Don't warn about comparisons of enum constants. These can arise
+    //  from macro expansions, and are usually quite deliberate.
+    Expr *LHSStripped = lex->IgnoreParens();
+    Expr *RHSStripped = rex->IgnoreParens();
+    if (DeclRefExpr* DRL = dyn_cast<DeclRefExpr>(LHSStripped))
+      if (DeclRefExpr* DRR = dyn_cast<DeclRefExpr>(RHSStripped))
+        if (DRL->getDecl() == DRR->getDecl() &&
+            !isa<EnumConstantDecl>(DRL->getDecl()))
+          DiagRuntimeBehavior(Loc, PDiag(diag::warn_selfcomparison));
+
+    if (isa<CastExpr>(LHSStripped))
+      LHSStripped = LHSStripped->IgnoreParenCasts();
+    if (isa<CastExpr>(RHSStripped))
+      RHSStripped = RHSStripped->IgnoreParenCasts();
+
+    // Warn about comparisons against a string constant (unless the other
+    // operand is null), the user probably wants strcmp.
+    Expr *literalString = 0;
+    Expr *literalStringStripped = 0;
+    if ((isa<StringLiteral>(LHSStripped) || isa<ObjCEncodeExpr>(LHSStripped)) &&
+        !RHSStripped->isNullPointerConstant(Context, 
+                                            Expr::NPC_ValueDependentIsNull)) {
+      literalString = lex;
+      literalStringStripped = LHSStripped;
+    } else if ((isa<StringLiteral>(RHSStripped) ||
+                isa<ObjCEncodeExpr>(RHSStripped)) &&
+               !LHSStripped->isNullPointerConstant(Context, 
+                                            Expr::NPC_ValueDependentIsNull)) {
+      literalString = rex;
+      literalStringStripped = RHSStripped;
+    }
+
+    if (literalString) {
+      std::string resultComparison;
+      switch (Opc) {
+      case BinaryOperator::LT: resultComparison = ") < 0"; break;
+      case BinaryOperator::GT: resultComparison = ") > 0"; break;
+      case BinaryOperator::LE: resultComparison = ") <= 0"; break;
+      case BinaryOperator::GE: resultComparison = ") >= 0"; break;
+      case BinaryOperator::EQ: resultComparison = ") == 0"; break;
+      case BinaryOperator::NE: resultComparison = ") != 0"; break;
+      default: assert(false && "Invalid comparison operator");
+      }
+      
+      DiagRuntimeBehavior(Loc,
+        PDiag(diag::warn_stringcompare)
+          << isa<ObjCEncodeExpr>(literalStringStripped)
+          << literalString->getSourceRange()
+          << CodeModificationHint::CreateReplacement(SourceRange(Loc), ", ")
+          << CodeModificationHint::CreateInsertion(lex->getLocStart(),
+                                                   "strcmp(")
+          << CodeModificationHint::CreateInsertion(
+                                         PP.getLocForEndOfToken(rex->getLocEnd()),
+                                         resultComparison));
+    }
+  }
+
+  // The result of comparisons is 'bool' in C++, 'int' in C.
+  QualType ResultTy = getLangOptions().CPlusPlus ? Context.BoolTy:Context.IntTy;
+
+  if (isRelational) {
+    if (lType->isRealType() && rType->isRealType())
+      return ResultTy;
+  } else {
+    // Check for comparisons of floating point operands using != and ==.
+    if (lType->isFloatingType() && rType->isFloatingType())
+      CheckFloatComparison(Loc,lex,rex);
+
+    if (lType->isArithmeticType() && rType->isArithmeticType())
+      return ResultTy;
+  }
+
+  bool LHSIsNull = lex->isNullPointerConstant(Context, 
+                                              Expr::NPC_ValueDependentIsNull);
+  bool RHSIsNull = rex->isNullPointerConstant(Context, 
+                                              Expr::NPC_ValueDependentIsNull);
+
+  // All of the following pointer related warnings are GCC extensions, except
+  // when handling null pointer constants. One day, we can consider making them
+  // errors (when -pedantic-errors is enabled).
+  if (lType->isPointerType() && rType->isPointerType()) { // C99 6.5.8p2
+    QualType LCanPointeeTy =
+      Context.getCanonicalType(lType->getAs<PointerType>()->getPointeeType());
+    QualType RCanPointeeTy =
+      Context.getCanonicalType(rType->getAs<PointerType>()->getPointeeType());
+
+    if (getLangOptions().CPlusPlus) {
+      if (LCanPointeeTy == RCanPointeeTy)
+        return ResultTy;
+      if (!isRelational &&
+          (LCanPointeeTy->isVoidType() || RCanPointeeTy->isVoidType())) {
+        // Valid unless comparison between non-null pointer and function pointer
+        // This is a gcc extension compatibility comparison.
+        if ((LCanPointeeTy->isFunctionType() || RCanPointeeTy->isFunctionType())
+            && !LHSIsNull && !RHSIsNull) {
+          Diag(Loc, diag::ext_typecheck_comparison_of_fptr_to_void)
+            << lType << rType << lex->getSourceRange() << rex->getSourceRange();
+          ImpCastExprToType(rex, lType, CastExpr::CK_BitCast);
+          return ResultTy;
+        }
+      }
+      // C++ [expr.rel]p2:
+      //   [...] Pointer conversions (4.10) and qualification
+      //   conversions (4.4) are performed on pointer operands (or on
+      //   a pointer operand and a null pointer constant) to bring
+      //   them to their composite pointer type. [...]
+      //
+      // C++ [expr.eq]p1 uses the same notion for (in)equality
+      // comparisons of pointers.
+      QualType T = FindCompositePointerType(lex, rex);
+      if (T.isNull()) {
+        Diag(Loc, diag::err_typecheck_comparison_of_distinct_pointers)
+          << lType << rType << lex->getSourceRange() << rex->getSourceRange();
+        return QualType();
+      }
+
+      ImpCastExprToType(lex, T, CastExpr::CK_BitCast);
+      ImpCastExprToType(rex, T, CastExpr::CK_BitCast);
+      return ResultTy;
+    }
+    // C99 6.5.9p2 and C99 6.5.8p2
+    if (Context.typesAreCompatible(LCanPointeeTy.getUnqualifiedType(),
+                                   RCanPointeeTy.getUnqualifiedType())) {
+      // Valid unless a relational comparison of function pointers
+      if (isRelational && LCanPointeeTy->isFunctionType()) {
+        Diag(Loc, diag::ext_typecheck_ordered_comparison_of_function_pointers)
+          << lType << rType << lex->getSourceRange() << rex->getSourceRange();
+      }
+    } else if (!isRelational &&
+               (LCanPointeeTy->isVoidType() || RCanPointeeTy->isVoidType())) {
+      // Valid unless comparison between non-null pointer and function pointer
+      if ((LCanPointeeTy->isFunctionType() || RCanPointeeTy->isFunctionType())
+          && !LHSIsNull && !RHSIsNull) {
+        Diag(Loc, diag::ext_typecheck_comparison_of_fptr_to_void)
+          << lType << rType << lex->getSourceRange() << rex->getSourceRange();
+      }
+    } else {
+      // Invalid
+      Diag(Loc, diag::ext_typecheck_comparison_of_distinct_pointers)
+        << lType << rType << lex->getSourceRange() << rex->getSourceRange();
+    }
+    if (LCanPointeeTy != RCanPointeeTy)
+      ImpCastExprToType(rex, lType, CastExpr::CK_BitCast);
+    return ResultTy;
+  }
+
+  if (getLangOptions().CPlusPlus) {
+    // Comparison of pointers with null pointer constants and equality
+    // comparisons of member pointers to null pointer constants.
+    if (RHSIsNull &&
+        (lType->isPointerType() ||
+         (!isRelational && lType->isMemberPointerType()))) {
+      ImpCastExprToType(rex, lType, CastExpr::CK_NullToMemberPointer);
+      return ResultTy;
+    }
+    if (LHSIsNull &&
+        (rType->isPointerType() ||
+         (!isRelational && rType->isMemberPointerType()))) {
+      ImpCastExprToType(lex, rType, CastExpr::CK_NullToMemberPointer);
+      return ResultTy;
+    }
+
+    // Comparison of member pointers.
+    if (!isRelational &&
+        lType->isMemberPointerType() && rType->isMemberPointerType()) {
+      // C++ [expr.eq]p2:
+      //   In addition, pointers to members can be compared, or a pointer to
+      //   member and a null pointer constant. Pointer to member conversions
+      //   (4.11) and qualification conversions (4.4) are performed to bring
+      //   them to a common type. If one operand is a null pointer constant,
+      //   the common type is the type of the other operand. Otherwise, the
+      //   common type is a pointer to member type similar (4.4) to the type
+      //   of one of the operands, with a cv-qualification signature (4.4)
+      //   that is the union of the cv-qualification signatures of the operand
+      //   types.
+      QualType T = FindCompositePointerType(lex, rex);
+      if (T.isNull()) {
+        Diag(Loc, diag::err_typecheck_comparison_of_distinct_pointers)
+        << lType << rType << lex->getSourceRange() << rex->getSourceRange();
+        return QualType();
+      }
+
+      ImpCastExprToType(lex, T, CastExpr::CK_BitCast);
+      ImpCastExprToType(rex, T, CastExpr::CK_BitCast);
+      return ResultTy;
+    }
+
+    // Comparison of nullptr_t with itself.
+    if (lType->isNullPtrType() && rType->isNullPtrType())
+      return ResultTy;
+  }
+
+  // Handle block pointer types.
+  if (!isRelational && lType->isBlockPointerType() && rType->isBlockPointerType()) {
+    QualType lpointee = lType->getAs<BlockPointerType>()->getPointeeType();
+    QualType rpointee = rType->getAs<BlockPointerType>()->getPointeeType();
+
+    if (!LHSIsNull && !RHSIsNull &&
+        !Context.typesAreCompatible(lpointee, rpointee)) {
+      Diag(Loc, diag::err_typecheck_comparison_of_distinct_blocks)
+        << lType << rType << lex->getSourceRange() << rex->getSourceRange();
+    }
+    ImpCastExprToType(rex, lType, CastExpr::CK_BitCast);
+    return ResultTy;
+  }
+  // Allow block pointers to be compared with null pointer constants.
+  if (!isRelational
+      && ((lType->isBlockPointerType() && rType->isPointerType())
+          || (lType->isPointerType() && rType->isBlockPointerType()))) {
+    if (!LHSIsNull && !RHSIsNull) {
+      if (!((rType->isPointerType() && rType->getAs<PointerType>()
+             ->getPointeeType()->isVoidType())
+            || (lType->isPointerType() && lType->getAs<PointerType>()
+                ->getPointeeType()->isVoidType())))
+        Diag(Loc, diag::err_typecheck_comparison_of_distinct_blocks)
+          << lType << rType << lex->getSourceRange() << rex->getSourceRange();
+    }
+    ImpCastExprToType(rex, lType, CastExpr::CK_BitCast);
+    return ResultTy;
+  }
+
+  if ((lType->isObjCObjectPointerType() || rType->isObjCObjectPointerType())) {
+    if (lType->isPointerType() || rType->isPointerType()) {
+      const PointerType *LPT = lType->getAs<PointerType>();
+      const PointerType *RPT = rType->getAs<PointerType>();
+      bool LPtrToVoid = LPT ?
+        Context.getCanonicalType(LPT->getPointeeType())->isVoidType() : false;
+      bool RPtrToVoid = RPT ?
+        Context.getCanonicalType(RPT->getPointeeType())->isVoidType() : false;
+
+      if (!LPtrToVoid && !RPtrToVoid &&
+          !Context.typesAreCompatible(lType, rType)) {
+        Diag(Loc, diag::ext_typecheck_comparison_of_distinct_pointers)
+          << lType << rType << lex->getSourceRange() << rex->getSourceRange();
+      }
+      ImpCastExprToType(rex, lType, CastExpr::CK_BitCast);
+      return ResultTy;
+    }
+    if (lType->isObjCObjectPointerType() && rType->isObjCObjectPointerType()) {
+      if (!Context.areComparableObjCPointerTypes(lType, rType))
+        Diag(Loc, diag::ext_typecheck_comparison_of_distinct_pointers)
+          << lType << rType << lex->getSourceRange() << rex->getSourceRange();
+      ImpCastExprToType(rex, lType, CastExpr::CK_BitCast);
+      return ResultTy;
+    }
+  }
+  if (lType->isAnyPointerType() && rType->isIntegerType()) {
+    unsigned DiagID = 0;
+    if (RHSIsNull) {
+      if (isRelational)
+        DiagID = diag::ext_typecheck_ordered_comparison_of_pointer_and_zero;
+    } else if (isRelational)
+      DiagID = diag::ext_typecheck_ordered_comparison_of_pointer_integer;
+    else
+      DiagID = diag::ext_typecheck_comparison_of_pointer_integer;
+
+    if (DiagID) {
+      Diag(Loc, DiagID)
+        << lType << rType << lex->getSourceRange() << rex->getSourceRange();
+    }
+    ImpCastExprToType(rex, lType, CastExpr::CK_IntegralToPointer);
+    return ResultTy;
+  }
+  if (lType->isIntegerType() && rType->isAnyPointerType()) {
+    unsigned DiagID = 0;
+    if (LHSIsNull) {
+      if (isRelational)
+        DiagID = diag::ext_typecheck_ordered_comparison_of_pointer_and_zero;
+    } else if (isRelational)
+      DiagID = diag::ext_typecheck_ordered_comparison_of_pointer_integer;
+    else
+      DiagID = diag::ext_typecheck_comparison_of_pointer_integer;
+
+    if (DiagID) {
+      Diag(Loc, DiagID)
+        << lType << rType << lex->getSourceRange() << rex->getSourceRange();
+    }
+    ImpCastExprToType(lex, rType, CastExpr::CK_IntegralToPointer);
+    return ResultTy;
+  }
+  // Handle block pointers.
+  if (!isRelational && RHSIsNull
+      && lType->isBlockPointerType() && rType->isIntegerType()) {
+    ImpCastExprToType(rex, lType, CastExpr::CK_IntegralToPointer);
+    return ResultTy;
+  }
+  if (!isRelational && LHSIsNull
+      && lType->isIntegerType() && rType->isBlockPointerType()) {
+    ImpCastExprToType(lex, rType, CastExpr::CK_IntegralToPointer);
+    return ResultTy;
+  }
+  return InvalidOperands(Loc, lex, rex);
+}
+
+/// CheckVectorCompareOperands - vector comparisons are a clang extension that
+/// operates on extended vector types.  Instead of producing an IntTy result,
+/// like a scalar comparison, a vector comparison produces a vector of integer
+/// types.
+QualType Sema::CheckVectorCompareOperands(Expr *&lex, Expr *&rex,
+                                          SourceLocation Loc,
+                                          bool isRelational) {
+  // Check to make sure we're operating on vectors of the same type and width,
+  // Allowing one side to be a scalar of element type.
+  QualType vType = CheckVectorOperands(Loc, lex, rex);
+  if (vType.isNull())
+    return vType;
+
+  QualType lType = lex->getType();
+  QualType rType = rex->getType();
+
+  // For non-floating point types, check for self-comparisons of the form
+  // x == x, x != x, x < x, etc.  These always evaluate to a constant, and
+  // often indicate logic errors in the program.
+  if (!lType->isFloatingType()) {
+    if (DeclRefExpr* DRL = dyn_cast<DeclRefExpr>(lex->IgnoreParens()))
+      if (DeclRefExpr* DRR = dyn_cast<DeclRefExpr>(rex->IgnoreParens()))
+        if (DRL->getDecl() == DRR->getDecl())
+          DiagRuntimeBehavior(Loc, PDiag(diag::warn_selfcomparison));
+  }
+
+  // Check for comparisons of floating point operands using != and ==.
+  if (!isRelational && lType->isFloatingType()) {
+    assert (rType->isFloatingType());
+    CheckFloatComparison(Loc,lex,rex);
+  }
+
+  // Return the type for the comparison, which is the same as vector type for
+  // integer vectors, or an integer type of identical size and number of
+  // elements for floating point vectors.
+  if (lType->isIntegerType())
+    return lType;
+
+  const VectorType *VTy = lType->getAs<VectorType>();
+  unsigned TypeSize = Context.getTypeSize(VTy->getElementType());
+  if (TypeSize == Context.getTypeSize(Context.IntTy))
+    return Context.getExtVectorType(Context.IntTy, VTy->getNumElements());
+  if (TypeSize == Context.getTypeSize(Context.LongTy))
+    return Context.getExtVectorType(Context.LongTy, VTy->getNumElements());
+
+  assert(TypeSize == Context.getTypeSize(Context.LongLongTy) &&
+         "Unhandled vector element size in vector compare");
+  return Context.getExtVectorType(Context.LongLongTy, VTy->getNumElements());
+}
+
+inline QualType Sema::CheckBitwiseOperands(
+  Expr *&lex, Expr *&rex, SourceLocation Loc, bool isCompAssign) {
+  if (lex->getType()->isVectorType() || rex->getType()->isVectorType())
+    return CheckVectorOperands(Loc, lex, rex);
+
+  QualType compType = UsualArithmeticConversions(lex, rex, isCompAssign);
+
+  if (lex->getType()->isIntegerType() && rex->getType()->isIntegerType())
+    return compType;
+  return InvalidOperands(Loc, lex, rex);
+}
+
+inline QualType Sema::CheckLogicalOperands( // C99 6.5.[13,14]
+  Expr *&lex, Expr *&rex, SourceLocation Loc) {
+  if (!Context.getLangOptions().CPlusPlus) {
+    UsualUnaryConversions(lex);
+    UsualUnaryConversions(rex);
+
+    if (!lex->getType()->isScalarType() || !rex->getType()->isScalarType())
+      return InvalidOperands(Loc, lex, rex);
+    
+    return Context.IntTy;
+  }
+  
+  // C++ [expr.log.and]p1
+  // C++ [expr.log.or]p1
+  // The operands are both implicitly converted to type bool (clause 4).
+  StandardConversionSequence LHS;
+  if (!IsStandardConversion(lex, Context.BoolTy,
+                            /*InOverloadResolution=*/false, LHS))
+    return InvalidOperands(Loc, lex, rex);
+
+  if (PerformImplicitConversion(lex, Context.BoolTy, LHS,
+                                AA_Passing, /*IgnoreBaseAccess=*/false))
+    return InvalidOperands(Loc, lex, rex);
+  
+  StandardConversionSequence RHS;
+  if (!IsStandardConversion(rex, Context.BoolTy,
+                            /*InOverloadResolution=*/false, RHS))
+    return InvalidOperands(Loc, lex, rex);
+  
+  if (PerformImplicitConversion(rex, Context.BoolTy, RHS,
+                                AA_Passing, /*IgnoreBaseAccess=*/false))
+    return InvalidOperands(Loc, lex, rex);
+  
+  // C++ [expr.log.and]p2
+  // C++ [expr.log.or]p2
+  // The result is a bool.
+  return Context.BoolTy;
+}
+
+/// IsReadonlyProperty - Verify that otherwise a valid l-value expression
+/// is a read-only property; return true if so. A readonly property expression
+/// depends on various declarations and thus must be treated specially.
+///
+static bool IsReadonlyProperty(Expr *E, Sema &S) {
+  if (E->getStmtClass() == Expr::ObjCPropertyRefExprClass) {
+    const ObjCPropertyRefExpr* PropExpr = cast<ObjCPropertyRefExpr>(E);
+    if (ObjCPropertyDecl *PDecl = PropExpr->getProperty()) {
+      QualType BaseType = PropExpr->getBase()->getType();
+      if (const ObjCObjectPointerType *OPT =
+            BaseType->getAsObjCInterfacePointerType())
+        if (ObjCInterfaceDecl *IFace = OPT->getInterfaceDecl())
+          if (S.isPropertyReadonly(PDecl, IFace))
+            return true;
+    }
+  }
+  return false;
+}
+
+/// CheckForModifiableLvalue - Verify that E is a modifiable lvalue.  If not,
+/// emit an error and return true.  If so, return false.
+static bool CheckForModifiableLvalue(Expr *E, SourceLocation Loc, Sema &S) {
+  SourceLocation OrigLoc = Loc;
+  Expr::isModifiableLvalueResult IsLV = E->isModifiableLvalue(S.Context,
+                                                              &Loc);
+  if (IsLV == Expr::MLV_Valid && IsReadonlyProperty(E, S))
+    IsLV = Expr::MLV_ReadonlyProperty;
+  if (IsLV == Expr::MLV_Valid)
+    return false;
+
+  unsigned Diag = 0;
+  bool NeedType = false;
+  switch (IsLV) { // C99 6.5.16p2
+  default: assert(0 && "Unknown result from isModifiableLvalue!");
+  case Expr::MLV_ConstQualified: Diag = diag::err_typecheck_assign_const; break;
+  case Expr::MLV_ArrayType:
+    Diag = diag::err_typecheck_array_not_modifiable_lvalue;
+    NeedType = true;
+    break;
+  case Expr::MLV_NotObjectType:
+    Diag = diag::err_typecheck_non_object_not_modifiable_lvalue;
+    NeedType = true;
+    break;
+  case Expr::MLV_LValueCast:
+    Diag = diag::err_typecheck_lvalue_casts_not_supported;
+    break;
+  case Expr::MLV_InvalidExpression:
+    Diag = diag::err_typecheck_expression_not_modifiable_lvalue;
+    break;
+  case Expr::MLV_IncompleteType:
+  case Expr::MLV_IncompleteVoidType:
+    return S.RequireCompleteType(Loc, E->getType(),
+                PDiag(diag::err_typecheck_incomplete_type_not_modifiable_lvalue)
+                  << E->getSourceRange());
+  case Expr::MLV_DuplicateVectorComponents:
+    Diag = diag::err_typecheck_duplicate_vector_components_not_mlvalue;
+    break;
+  case Expr::MLV_NotBlockQualified:
+    Diag = diag::err_block_decl_ref_not_modifiable_lvalue;
+    break;
+  case Expr::MLV_ReadonlyProperty:
+    Diag = diag::error_readonly_property_assignment;
+    break;
+  case Expr::MLV_NoSetterProperty:
+    Diag = diag::error_nosetter_property_assignment;
+    break;
+  case Expr::MLV_SubObjCPropertySetting:
+    Diag = diag::error_no_subobject_property_setting;
+    break;
+  }
+
+  SourceRange Assign;
+  if (Loc != OrigLoc)
+    Assign = SourceRange(OrigLoc, OrigLoc);
+  if (NeedType)
+    S.Diag(Loc, Diag) << E->getType() << E->getSourceRange() << Assign;
+  else
+    S.Diag(Loc, Diag) << E->getSourceRange() << Assign;
+  return true;
+}
+
+
+
+// C99 6.5.16.1
+QualType Sema::CheckAssignmentOperands(Expr *LHS, Expr *&RHS,
+                                       SourceLocation Loc,
+                                       QualType CompoundType) {
+  // Verify that LHS is a modifiable lvalue, and emit error if not.
+  if (CheckForModifiableLvalue(LHS, Loc, *this))
+    return QualType();
+
+  QualType LHSType = LHS->getType();
+  QualType RHSType = CompoundType.isNull() ? RHS->getType() : CompoundType;
+
+  AssignConvertType ConvTy;
+  if (CompoundType.isNull()) {
+    // Simple assignment "x = y".
+    ConvTy = CheckSingleAssignmentConstraints(LHSType, RHS);
+    // Special case of NSObject attributes on c-style pointer types.
+    if (ConvTy == IncompatiblePointer &&
+        ((Context.isObjCNSObjectType(LHSType) &&
+          RHSType->isObjCObjectPointerType()) ||
+         (Context.isObjCNSObjectType(RHSType) &&
+          LHSType->isObjCObjectPointerType())))
+      ConvTy = Compatible;
+
+    // If the RHS is a unary plus or minus, check to see if they = and + are
+    // right next to each other.  If so, the user may have typo'd "x =+ 4"
+    // instead of "x += 4".
+    Expr *RHSCheck = RHS;
+    if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(RHSCheck))
+      RHSCheck = ICE->getSubExpr();
+    if (UnaryOperator *UO = dyn_cast<UnaryOperator>(RHSCheck)) {
+      if ((UO->getOpcode() == UnaryOperator::Plus ||
+           UO->getOpcode() == UnaryOperator::Minus) &&
+          Loc.isFileID() && UO->getOperatorLoc().isFileID() &&
+          // Only if the two operators are exactly adjacent.
+          Loc.getFileLocWithOffset(1) == UO->getOperatorLoc() &&
+          // And there is a space or other character before the subexpr of the
+          // unary +/-.  We don't want to warn on "x=-1".
+          Loc.getFileLocWithOffset(2) != UO->getSubExpr()->getLocStart() &&
+          UO->getSubExpr()->getLocStart().isFileID()) {
+        Diag(Loc, diag::warn_not_compound_assign)
+          << (UO->getOpcode() == UnaryOperator::Plus ? "+" : "-")
+          << SourceRange(UO->getOperatorLoc(), UO->getOperatorLoc());
+      }
+    }
+  } else {
+    // Compound assignment "x += y"
+    ConvTy = CheckAssignmentConstraints(LHSType, RHSType);
+  }
+
+  if (DiagnoseAssignmentResult(ConvTy, Loc, LHSType, RHSType,
+                               RHS, AA_Assigning))
+    return QualType();
+
+  // 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
+  // operand.
+  return LHSType.getUnqualifiedType();
+}
+
+// C99 6.5.17
+QualType Sema::CheckCommaOperands(Expr *LHS, Expr *&RHS, SourceLocation Loc) {
+  // Comma performs lvalue conversion (C99 6.3.2.1), but not unary conversions.
+  // C++ does not perform this conversion (C++ [expr.comma]p1).
+  if (!getLangOptions().CPlusPlus)
+    DefaultFunctionArrayLvalueConversion(RHS);
+
+  // FIXME: Check that RHS type is complete in C mode (it's legal for it to be
+  // incomplete in C++).
+
+  return RHS->getType();
+}
+
+/// CheckIncrementDecrementOperand - unlike most "Check" methods, this routine
+/// doesn't need to call UsualUnaryConversions or UsualArithmeticConversions.
+QualType Sema::CheckIncrementDecrementOperand(Expr *Op, SourceLocation OpLoc,
+                                              bool isInc) {
+  if (Op->isTypeDependent())
+    return Context.DependentTy;
+
+  QualType ResType = Op->getType();
+  assert(!ResType.isNull() && "no type for increment/decrement expression");
+
+  if (getLangOptions().CPlusPlus && ResType->isBooleanType()) {
+    // Decrement of bool is not allowed.
+    if (!isInc) {
+      Diag(OpLoc, diag::err_decrement_bool) << Op->getSourceRange();
+      return QualType();
+    }
+    // Increment of bool sets it to true, but is deprecated.
+    Diag(OpLoc, diag::warn_increment_bool) << Op->getSourceRange();
+  } else if (ResType->isRealType()) {
+    // OK!
+  } else if (ResType->isAnyPointerType()) {
+    QualType PointeeTy = ResType->getPointeeType();
+
+    // C99 6.5.2.4p2, 6.5.6p2
+    if (PointeeTy->isVoidType()) {
+      if (getLangOptions().CPlusPlus) {
+        Diag(OpLoc, diag::err_typecheck_pointer_arith_void_type)
+          << Op->getSourceRange();
+        return QualType();
+      }
+
+      // Pointer to void is a GNU extension in C.
+      Diag(OpLoc, diag::ext_gnu_void_ptr) << Op->getSourceRange();
+    } else if (PointeeTy->isFunctionType()) {
+      if (getLangOptions().CPlusPlus) {
+        Diag(OpLoc, diag::err_typecheck_pointer_arith_function_type)
+          << Op->getType() << Op->getSourceRange();
+        return QualType();
+      }
+
+      Diag(OpLoc, diag::ext_gnu_ptr_func_arith)
+        << ResType << Op->getSourceRange();
+    } else if (RequireCompleteType(OpLoc, PointeeTy,
+                           PDiag(diag::err_typecheck_arithmetic_incomplete_type)
+                             << Op->getSourceRange()
+                             << ResType))
+      return QualType();
+    // Diagnose bad cases where we step over interface counts.
+    else if (PointeeTy->isObjCInterfaceType() && LangOpts.ObjCNonFragileABI) {
+      Diag(OpLoc, diag::err_arithmetic_nonfragile_interface)
+        << PointeeTy << Op->getSourceRange();
+      return QualType();
+    }
+  } else if (ResType->isAnyComplexType()) {
+    // C99 does not support ++/-- on complex types, we allow as an extension.
+    Diag(OpLoc, diag::ext_integer_increment_complex)
+      << ResType << Op->getSourceRange();
+  } else {
+    Diag(OpLoc, diag::err_typecheck_illegal_increment_decrement)
+      << ResType << int(isInc) << Op->getSourceRange();
+    return QualType();
+  }
+  // At this point, we know we have a real, complex or pointer type.
+  // Now make sure the operand is a modifiable lvalue.
+  if (CheckForModifiableLvalue(Op, OpLoc, *this))
+    return QualType();
+  return ResType;
+}
+
+/// getPrimaryDecl - Helper function for CheckAddressOfOperand().
+/// This routine allows us to typecheck complex/recursive expressions
+/// where the declaration is needed for type checking. We only need to
+/// handle cases when the expression references a function designator
+/// or is an lvalue. Here are some examples:
+///  - &(x) => x
+///  - &*****f => f for f a function designator.
+///  - &s.xx => s
+///  - &s.zz[1].yy -> s, if zz is an array
+///  - *(x + 1) -> x, if x is an array
+///  - &"123"[2] -> 0
+///  - & __real__ x -> x
+static NamedDecl *getPrimaryDecl(Expr *E) {
+  switch (E->getStmtClass()) {
+  case Stmt::DeclRefExprClass:
+    return cast<DeclRefExpr>(E)->getDecl();
+  case Stmt::MemberExprClass:
+    // If this is an arrow operator, the address is an offset from
+    // the base's value, so the object the base refers to is
+    // irrelevant.
+    if (cast<MemberExpr>(E)->isArrow())
+      return 0;
+    // Otherwise, the expression refers to a part of the base
+    return getPrimaryDecl(cast<MemberExpr>(E)->getBase());
+  case Stmt::ArraySubscriptExprClass: {
+    // FIXME: This code shouldn't be necessary!  We should catch the implicit
+    // promotion of register arrays earlier.
+    Expr* Base = cast<ArraySubscriptExpr>(E)->getBase();
+    if (ImplicitCastExpr* ICE = dyn_cast<ImplicitCastExpr>(Base)) {
+      if (ICE->getSubExpr()->getType()->isArrayType())
+        return getPrimaryDecl(ICE->getSubExpr());
+    }
+    return 0;
+  }
+  case Stmt::UnaryOperatorClass: {
+    UnaryOperator *UO = cast<UnaryOperator>(E);
+
+    switch(UO->getOpcode()) {
+    case UnaryOperator::Real:
+    case UnaryOperator::Imag:
+    case UnaryOperator::Extension:
+      return getPrimaryDecl(UO->getSubExpr());
+    default:
+      return 0;
+    }
+  }
+  case Stmt::ParenExprClass:
+    return getPrimaryDecl(cast<ParenExpr>(E)->getSubExpr());
+  case Stmt::ImplicitCastExprClass:
+    // If the result of an implicit cast is an l-value, we care about
+    // the sub-expression; otherwise, the result here doesn't matter.
+    return getPrimaryDecl(cast<ImplicitCastExpr>(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.
+/// In C++, the operand might be an overloaded function name, in which case
+/// we allow the '&' but retain the overloaded-function type.
+QualType Sema::CheckAddressOfOperand(Expr *op, SourceLocation OpLoc) {
+  // Make sure to ignore parentheses in subsequent checks
+  op = op->IgnoreParens();
+
+  if (op->isTypeDependent())
+    return Context.DependentTy;
+
+  if (getLangOptions().C99) {
+    // Implement C99-only parts of addressof rules.
+    if (UnaryOperator* uOp = dyn_cast<UnaryOperator>(op)) {
+      if (uOp->getOpcode() == UnaryOperator::Deref)
+        // Per C99 6.5.3.2, the address of a deref always returns a valid result
+        // (assuming the deref expression is valid).
+        return uOp->getSubExpr()->getType();
+    }
+    // Technically, there should be a check for array subscript
+    // expressions here, but the result of one is always an lvalue anyway.
+  }
+  NamedDecl *dcl = getPrimaryDecl(op);
+  Expr::isLvalueResult lval = op->isLvalue(Context);
+
+  MemberExpr *ME = dyn_cast<MemberExpr>(op);
+  if (lval == Expr::LV_MemberFunction && ME &&
+      isa<CXXMethodDecl>(ME->getMemberDecl())) {
+    ValueDecl *dcl = cast<MemberExpr>(op)->getMemberDecl();
+    // &f where f is a member of the current object, or &o.f, or &p->f
+    // All these are not allowed, and we need to catch them before the dcl
+    // branch of the if, below.
+    Diag(OpLoc, diag::err_unqualified_pointer_member_function)
+        << dcl;
+    // FIXME: Improve this diagnostic and provide a fixit.
+
+    // Now recover by acting as if the function had been accessed qualified.
+    return Context.getMemberPointerType(op->getType(),
+                Context.getTypeDeclType(cast<RecordDecl>(dcl->getDeclContext()))
+                       .getTypePtr());
+  } else if (lval != Expr::LV_Valid && lval != Expr::LV_IncompleteVoidType) {
+    // C99 6.5.3.2p1
+    // The operand must be either an l-value or a function designator
+    if (!op->getType()->isFunctionType()) {
+      // FIXME: emit more specific diag...
+      Diag(OpLoc, diag::err_typecheck_invalid_lvalue_addrof)
+        << op->getSourceRange();
+      return QualType();
+    }
+  } else if (op->getBitField()) { // C99 6.5.3.2p1
+    // The operand cannot be a bit-field
+    Diag(OpLoc, diag::err_typecheck_address_of)
+      << "bit-field" << op->getSourceRange();
+        return QualType();
+  } else if (op->refersToVectorElement()) {
+    // The operand cannot be an element of a vector
+    Diag(OpLoc, diag::err_typecheck_address_of)
+      << "vector element" << op->getSourceRange();
+    return QualType();
+  } else if (isa<ObjCPropertyRefExpr>(op)) {
+    // cannot take address of a property expression.
+    Diag(OpLoc, diag::err_typecheck_address_of)
+      << "property expression" << op->getSourceRange();
+    return QualType();
+  } else if (ConditionalOperator *CO = dyn_cast<ConditionalOperator>(op)) {
+    // FIXME: Can LHS ever be null here?
+    if (!CheckAddressOfOperand(CO->getTrueExpr(), OpLoc).isNull())
+      return CheckAddressOfOperand(CO->getFalseExpr(), OpLoc);
+  } else if (isa<UnresolvedLookupExpr>(op)) {
+    return Context.OverloadTy;
+  } else if (dcl) { // C99 6.5.3.2p1
+    // 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 variable" << op->getSourceRange();
+        return QualType();
+      }
+    } else if (isa<FunctionTemplateDecl>(dcl)) {
+      return Context.OverloadTy;
+    } else if (FieldDecl *FD = dyn_cast<FieldDecl>(dcl)) {
+      // Okay: we can take the address of a field.
+      // Could be a pointer to member, though, if there is an explicit
+      // scope qualifier for the class.
+      if (isa<DeclRefExpr>(op) && cast<DeclRefExpr>(op)->getQualifier()) {
+        DeclContext *Ctx = dcl->getDeclContext();
+        if (Ctx && Ctx->isRecord()) {
+          if (FD->getType()->isReferenceType()) {
+            Diag(OpLoc,
+                 diag::err_cannot_form_pointer_to_member_of_reference_type)
+              << FD->getDeclName() << FD->getType();
+            return QualType();
+          }
+
+          return Context.getMemberPointerType(op->getType(),
+                Context.getTypeDeclType(cast<RecordDecl>(Ctx)).getTypePtr());
+        }
+      }
+    } else if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(dcl)) {
+      // Okay: we can take the address of a function.
+      // As above.
+      if (isa<DeclRefExpr>(op) && cast<DeclRefExpr>(op)->getQualifier() &&
+          MD->isInstance())
+        return Context.getMemberPointerType(op->getType(),
+              Context.getTypeDeclType(MD->getParent()).getTypePtr());
+    } else if (!isa<FunctionDecl>(dcl))
+      assert(0 && "Unknown/unexpected decl type");
+  }
+
+  if (lval == Expr::LV_IncompleteVoidType) {
+    // Taking the address of a void variable is technically illegal, but we
+    // allow it in cases which are otherwise valid.
+    // Example: "extern void x; void* y = &x;".
+    Diag(OpLoc, diag::ext_typecheck_addrof_void) << op->getSourceRange();
+  }
+
+  // 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) {
+  if (Op->isTypeDependent())
+    return Context.DependentTy;
+
+  UsualUnaryConversions(Op);
+  QualType Ty = Op->getType();
+
+  // Note that per both C89 and C99, this is always legal, even if ptype is an
+  // incomplete type or void.  It would be possible to warn about dereferencing
+  // a void pointer, but it's completely well-defined, and such a warning is
+  // unlikely to catch any mistakes.
+  if (const PointerType *PT = Ty->getAs<PointerType>())
+    return PT->getPointeeType();
+
+  if (const ObjCObjectPointerType *OPT = Ty->getAs<ObjCObjectPointerType>())
+    return OPT->getPointeeType();
+
+  Diag(OpLoc, diag::err_typecheck_indirection_requires_pointer)
+    << Ty << Op->getSourceRange();
+  return QualType();
+}
+
+static inline BinaryOperator::Opcode ConvertTokenKindToBinaryOpcode(
+  tok::TokenKind Kind) {
+  BinaryOperator::Opcode Opc;
+  switch (Kind) {
+  default: assert(0 && "Unknown binop!");
+  case tok::periodstar:           Opc = BinaryOperator::PtrMemD; break;
+  case tok::arrowstar:            Opc = BinaryOperator::PtrMemI; break;
+  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___real:    Opc = UnaryOperator::Real; break;
+  case tok::kw___imag:    Opc = UnaryOperator::Imag; break;
+  case tok::kw___extension__: Opc = UnaryOperator::Extension; break;
+  }
+  return Opc;
+}
+
+/// CreateBuiltinBinOp - Creates a new built-in binary operation with
+/// operator @p Opc at location @c TokLoc. This routine only supports
+/// built-in operations; ActOnBinOp handles overloaded operators.
+Action::OwningExprResult Sema::CreateBuiltinBinOp(SourceLocation OpLoc,
+                                                  unsigned Op,
+                                                  Expr *lhs, Expr *rhs) {
+  QualType ResultTy;     // Result type of the binary operator.
+  BinaryOperator::Opcode Opc = (BinaryOperator::Opcode)Op;
+  // The following two variables are used for compound assignment operators
+  QualType CompLHSTy;    // Type of LHS after promotions for computation
+  QualType CompResultTy; // Type of computation result
+
+  switch (Opc) {
+  case BinaryOperator::Assign:
+    ResultTy = CheckAssignmentOperands(lhs, rhs, OpLoc, QualType());
+    break;
+  case BinaryOperator::PtrMemD:
+  case BinaryOperator::PtrMemI:
+    ResultTy = CheckPointerToMemberOperands(lhs, rhs, OpLoc,
+                                            Opc == BinaryOperator::PtrMemI);
+    break;
+  case BinaryOperator::Mul:
+  case BinaryOperator::Div:
+    ResultTy = CheckMultiplyDivideOperands(lhs, rhs, OpLoc, false,
+                                           Opc == BinaryOperator::Div);
+    break;
+  case BinaryOperator::Rem:
+    ResultTy = CheckRemainderOperands(lhs, rhs, OpLoc);
+    break;
+  case BinaryOperator::Add:
+    ResultTy = CheckAdditionOperands(lhs, rhs, OpLoc);
+    break;
+  case BinaryOperator::Sub:
+    ResultTy = CheckSubtractionOperands(lhs, rhs, OpLoc);
+    break;
+  case BinaryOperator::Shl:
+  case BinaryOperator::Shr:
+    ResultTy = CheckShiftOperands(lhs, rhs, OpLoc);
+    break;
+  case BinaryOperator::LE:
+  case BinaryOperator::LT:
+  case BinaryOperator::GE:
+  case BinaryOperator::GT:
+    ResultTy = CheckCompareOperands(lhs, rhs, OpLoc, Opc, true);
+    break;
+  case BinaryOperator::EQ:
+  case BinaryOperator::NE:
+    ResultTy = CheckCompareOperands(lhs, rhs, OpLoc, Opc, false);
+    break;
+  case BinaryOperator::And:
+  case BinaryOperator::Xor:
+  case BinaryOperator::Or:
+    ResultTy = CheckBitwiseOperands(lhs, rhs, OpLoc);
+    break;
+  case BinaryOperator::LAnd:
+  case BinaryOperator::LOr:
+    ResultTy = CheckLogicalOperands(lhs, rhs, OpLoc);
+    break;
+  case BinaryOperator::MulAssign:
+  case BinaryOperator::DivAssign:
+    CompResultTy = CheckMultiplyDivideOperands(lhs, rhs, OpLoc, true,
+                                              Opc == BinaryOperator::DivAssign);
+    CompLHSTy = CompResultTy;
+    if (!CompResultTy.isNull())
+      ResultTy = CheckAssignmentOperands(lhs, rhs, OpLoc, CompResultTy);
+    break;
+  case BinaryOperator::RemAssign:
+    CompResultTy = CheckRemainderOperands(lhs, rhs, OpLoc, true);
+    CompLHSTy = CompResultTy;
+    if (!CompResultTy.isNull())
+      ResultTy = CheckAssignmentOperands(lhs, rhs, OpLoc, CompResultTy);
+    break;
+  case BinaryOperator::AddAssign:
+    CompResultTy = CheckAdditionOperands(lhs, rhs, OpLoc, &CompLHSTy);
+    if (!CompResultTy.isNull())
+      ResultTy = CheckAssignmentOperands(lhs, rhs, OpLoc, CompResultTy);
+    break;
+  case BinaryOperator::SubAssign:
+    CompResultTy = CheckSubtractionOperands(lhs, rhs, OpLoc, &CompLHSTy);
+    if (!CompResultTy.isNull())
+      ResultTy = CheckAssignmentOperands(lhs, rhs, OpLoc, CompResultTy);
+    break;
+  case BinaryOperator::ShlAssign:
+  case BinaryOperator::ShrAssign:
+    CompResultTy = CheckShiftOperands(lhs, rhs, OpLoc, true);
+    CompLHSTy = CompResultTy;
+    if (!CompResultTy.isNull())
+      ResultTy = CheckAssignmentOperands(lhs, rhs, OpLoc, CompResultTy);
+    break;
+  case BinaryOperator::AndAssign:
+  case BinaryOperator::XorAssign:
+  case BinaryOperator::OrAssign:
+    CompResultTy = CheckBitwiseOperands(lhs, rhs, OpLoc, true);
+    CompLHSTy = CompResultTy;
+    if (!CompResultTy.isNull())
+      ResultTy = CheckAssignmentOperands(lhs, rhs, OpLoc, CompResultTy);
+    break;
+  case BinaryOperator::Comma:
+    ResultTy = CheckCommaOperands(lhs, rhs, OpLoc);
+    break;
+  }
+  if (ResultTy.isNull())
+    return ExprError();
+  if (CompResultTy.isNull())
+    return Owned(new (Context) BinaryOperator(lhs, rhs, Opc, ResultTy, OpLoc));
+  else
+    return Owned(new (Context) CompoundAssignOperator(lhs, rhs, Opc, ResultTy,
+                                                      CompLHSTy, CompResultTy,
+                                                      OpLoc));
+}
+
+/// SuggestParentheses - Emit a diagnostic together with a fixit hint that wraps
+/// ParenRange in parentheses.
+static void SuggestParentheses(Sema &Self, SourceLocation Loc,
+                               const PartialDiagnostic &PD,
+                               SourceRange ParenRange,
+                      const PartialDiagnostic &SecondPD = PartialDiagnostic(0),
+                               SourceRange SecondParenRange = SourceRange()) {
+  SourceLocation EndLoc = Self.PP.getLocForEndOfToken(ParenRange.getEnd());
+  if (!ParenRange.getEnd().isFileID() || EndLoc.isInvalid()) {
+    // We can't display the parentheses, so just dig the
+    // warning/error and return.
+    Self.Diag(Loc, PD);
+    return;
+  }
+
+  Self.Diag(Loc, PD)
+    << CodeModificationHint::CreateInsertion(ParenRange.getBegin(), "(")
+    << CodeModificationHint::CreateInsertion(EndLoc, ")");
+  
+  if (!SecondPD.getDiagID())
+    return;
+  
+  EndLoc = Self.PP.getLocForEndOfToken(SecondParenRange.getEnd());
+  if (!SecondParenRange.getEnd().isFileID() || EndLoc.isInvalid()) {
+    // We can't display the parentheses, so just dig the
+    // warning/error and return.
+    Self.Diag(Loc, SecondPD);
+    return;
+  }
+  
+  Self.Diag(Loc, SecondPD)
+    << CodeModificationHint::CreateInsertion(SecondParenRange.getBegin(), "(")
+    << CodeModificationHint::CreateInsertion(EndLoc, ")");
+}
+
+/// DiagnoseBitwisePrecedence - Emit a warning when bitwise and comparison
+/// operators are mixed in a way that suggests that the programmer forgot that
+/// comparison operators have higher precedence. The most typical example of
+/// such code is "flags & 0x0020 != 0", which is equivalent to "flags & 1".
+static void DiagnoseBitwisePrecedence(Sema &Self, BinaryOperator::Opcode Opc,
+                                      SourceLocation OpLoc,Expr *lhs,Expr *rhs){
+  typedef BinaryOperator BinOp;
+  BinOp::Opcode lhsopc = static_cast<BinOp::Opcode>(-1),
+                rhsopc = static_cast<BinOp::Opcode>(-1);
+  if (BinOp *BO = dyn_cast<BinOp>(lhs))
+    lhsopc = BO->getOpcode();
+  if (BinOp *BO = dyn_cast<BinOp>(rhs))
+    rhsopc = BO->getOpcode();
+
+  // Subs are not binary operators.
+  if (lhsopc == -1 && rhsopc == -1)
+    return;
+
+  // Bitwise operations are sometimes used as eager logical ops.
+  // Don't diagnose this.
+  if ((BinOp::isComparisonOp(lhsopc) || BinOp::isBitwiseOp(lhsopc)) &&
+      (BinOp::isComparisonOp(rhsopc) || BinOp::isBitwiseOp(rhsopc)))
+    return;
+
+  if (BinOp::isComparisonOp(lhsopc))
+    SuggestParentheses(Self, OpLoc,
+      PDiag(diag::warn_precedence_bitwise_rel)
+          << SourceRange(lhs->getLocStart(), OpLoc)
+          << BinOp::getOpcodeStr(Opc) << BinOp::getOpcodeStr(lhsopc),
+      lhs->getSourceRange(),
+      PDiag(diag::note_precedence_bitwise_first)
+          << BinOp::getOpcodeStr(Opc),
+      SourceRange(cast<BinOp>(lhs)->getRHS()->getLocStart(), rhs->getLocEnd()));
+  else if (BinOp::isComparisonOp(rhsopc))
+    SuggestParentheses(Self, OpLoc,
+      PDiag(diag::warn_precedence_bitwise_rel)
+          << SourceRange(OpLoc, rhs->getLocEnd())
+          << BinOp::getOpcodeStr(Opc) << BinOp::getOpcodeStr(rhsopc),
+      rhs->getSourceRange(),
+      PDiag(diag::note_precedence_bitwise_first)
+        << BinOp::getOpcodeStr(Opc),
+      SourceRange(lhs->getLocEnd(), cast<BinOp>(rhs)->getLHS()->getLocStart()));
+}
+
+/// DiagnoseBinOpPrecedence - Emit warnings for expressions with tricky
+/// precedence. This currently diagnoses only "arg1 'bitwise' arg2 'eq' arg3".
+/// But it could also warn about arg1 && arg2 || arg3, as GCC 4.3+ does.
+static void DiagnoseBinOpPrecedence(Sema &Self, BinaryOperator::Opcode Opc,
+                                    SourceLocation OpLoc, Expr *lhs, Expr *rhs){
+  if (BinaryOperator::isBitwiseOp(Opc))
+    DiagnoseBitwisePrecedence(Self, Opc, OpLoc, lhs, rhs);
+}
+
+// Binary Operators.  'Tok' is the token for the operator.
+Action::OwningExprResult Sema::ActOnBinOp(Scope *S, SourceLocation TokLoc,
+                                          tok::TokenKind Kind,
+                                          ExprArg LHS, ExprArg RHS) {
+  BinaryOperator::Opcode Opc = ConvertTokenKindToBinaryOpcode(Kind);
+  Expr *lhs = LHS.takeAs<Expr>(), *rhs = RHS.takeAs<Expr>();
+
+  assert((lhs != 0) && "ActOnBinOp(): missing left expression");
+  assert((rhs != 0) && "ActOnBinOp(): missing right expression");
+
+  // Emit warnings for tricky precedence issues, e.g. "bitfield & 0x4 == 0"
+  DiagnoseBinOpPrecedence(*this, Opc, TokLoc, lhs, rhs);
+
+  return BuildBinOp(S, TokLoc, Opc, lhs, rhs);
+}
+
+Action::OwningExprResult Sema::BuildBinOp(Scope *S, SourceLocation OpLoc,
+                                          BinaryOperator::Opcode Opc,
+                                          Expr *lhs, Expr *rhs) {
+  if (getLangOptions().CPlusPlus &&
+      (lhs->getType()->isOverloadableType() ||
+       rhs->getType()->isOverloadableType())) {
+    // Find all of the overloaded operators visible from this
+    // point. We perform both an operator-name lookup from the local
+    // scope and an argument-dependent lookup based on the types of
+    // the arguments.
+    UnresolvedSet<16> Functions;
+    OverloadedOperatorKind OverOp = BinaryOperator::getOverloadedOperator(Opc);
+    if (S && OverOp != OO_None)
+      LookupOverloadedOperatorName(OverOp, S, lhs->getType(), rhs->getType(),
+                                   Functions);
+    
+    // Build the (potentially-overloaded, potentially-dependent)
+    // binary operation.
+    return CreateOverloadedBinOp(OpLoc, Opc, Functions, lhs, rhs);
+  }
+  
+  // Build a built-in binary operation.
+  return CreateBuiltinBinOp(OpLoc, Opc, lhs, rhs);
+}
+
+Action::OwningExprResult Sema::CreateBuiltinUnaryOp(SourceLocation OpLoc,
+                                                    unsigned OpcIn,
+                                                    ExprArg InputArg) {
+  UnaryOperator::Opcode Opc = static_cast<UnaryOperator::Opcode>(OpcIn);
+
+  // FIXME: Input is modified below, but InputArg is not updated appropriately.
+  Expr *Input = (Expr *)InputArg.get();
+  QualType resultType;
+  switch (Opc) {
+  case UnaryOperator::OffsetOf:
+    assert(false && "Invalid unary operator");
+    break;
+
+  case UnaryOperator::PreInc:
+  case UnaryOperator::PreDec:
+  case UnaryOperator::PostInc:
+  case UnaryOperator::PostDec:
+    resultType = CheckIncrementDecrementOperand(Input, OpLoc,
+                                                Opc == UnaryOperator::PreInc ||
+                                                Opc == UnaryOperator::PostInc);
+    break;
+  case UnaryOperator::AddrOf:
+    resultType = CheckAddressOfOperand(Input, OpLoc);
+    break;
+  case UnaryOperator::Deref:
+    DefaultFunctionArrayLvalueConversion(Input);
+    resultType = CheckIndirectionOperand(Input, OpLoc);
+    break;
+  case UnaryOperator::Plus:
+  case UnaryOperator::Minus:
+    UsualUnaryConversions(Input);
+    resultType = Input->getType();
+    if (resultType->isDependentType())
+      break;
+    if (resultType->isArithmeticType()) // C99 6.5.3.3p1
+      break;
+    else if (getLangOptions().CPlusPlus && // C++ [expr.unary.op]p6-7
+             resultType->isEnumeralType())
+      break;
+    else if (getLangOptions().CPlusPlus && // C++ [expr.unary.op]p6
+             Opc == UnaryOperator::Plus &&
+             resultType->isPointerType())
+      break;
+
+    return ExprError(Diag(OpLoc, diag::err_typecheck_unary_expr)
+      << resultType << Input->getSourceRange());
+  case UnaryOperator::Not: // bitwise complement
+    UsualUnaryConversions(Input);
+    resultType = Input->getType();
+    if (resultType->isDependentType())
+      break;
+    // C99 6.5.3.3p1. We allow complex int and float as a GCC extension.
+    if (resultType->isComplexType() || resultType->isComplexIntegerType())
+      // C99 does not support '~' for complex conjugation.
+      Diag(OpLoc, diag::ext_integer_complement_complex)
+        << resultType << Input->getSourceRange();
+    else if (!resultType->isIntegerType())
+      return ExprError(Diag(OpLoc, diag::err_typecheck_unary_expr)
+        << resultType << Input->getSourceRange());
+    break;
+  case UnaryOperator::LNot: // logical negation
+    // Unlike +/-/~, integer promotions aren't done here (C99 6.5.3.3p5).
+    DefaultFunctionArrayLvalueConversion(Input);
+    resultType = Input->getType();
+    if (resultType->isDependentType())
+      break;
+    if (!resultType->isScalarType()) // C99 6.5.3.3p1
+      return ExprError(Diag(OpLoc, diag::err_typecheck_unary_expr)
+        << resultType << Input->getSourceRange());
+    // LNot always has type int. C99 6.5.3.3p5.
+    // In C++, it's bool. C++ 5.3.1p8
+    resultType = getLangOptions().CPlusPlus ? Context.BoolTy : Context.IntTy;
+    break;
+  case UnaryOperator::Real:
+  case UnaryOperator::Imag:
+    resultType = CheckRealImagOperand(Input, OpLoc, Opc == UnaryOperator::Real);
+    break;
+  case UnaryOperator::Extension:
+    resultType = Input->getType();
+    break;
+  }
+  if (resultType.isNull())
+    return ExprError();
+
+  InputArg.release();
+  return Owned(new (Context) UnaryOperator(Input, Opc, resultType, OpLoc));
+}
+
+Action::OwningExprResult Sema::BuildUnaryOp(Scope *S, SourceLocation OpLoc,
+                                            UnaryOperator::Opcode Opc,
+                                            ExprArg input) {
+  Expr *Input = (Expr*)input.get();
+  if (getLangOptions().CPlusPlus && Input->getType()->isOverloadableType() &&
+      Opc != UnaryOperator::Extension) {
+    // Find all of the overloaded operators visible from this
+    // point. We perform both an operator-name lookup from the local
+    // scope and an argument-dependent lookup based on the types of
+    // the arguments.
+    UnresolvedSet<16> Functions;
+    OverloadedOperatorKind OverOp = UnaryOperator::getOverloadedOperator(Opc);
+    if (S && OverOp != OO_None)
+      LookupOverloadedOperatorName(OverOp, S, Input->getType(), QualType(),
+                                   Functions);
+    
+    return CreateOverloadedUnaryOp(OpLoc, Opc, Functions, move(input));
+  }
+  
+  return CreateBuiltinUnaryOp(OpLoc, Opc, move(input));
+}
+
+// Unary Operators.  'Tok' is the token for the operator.
+Action::OwningExprResult Sema::ActOnUnaryOp(Scope *S, SourceLocation OpLoc,
+                                            tok::TokenKind Op, ExprArg input) {
+  return BuildUnaryOp(S, OpLoc, ConvertTokenKindToUnaryOpcode(Op), move(input));
+}
+
+/// ActOnAddrLabel - Parse the GNU address of label extension: "&&foo".
+Sema::OwningExprResult Sema::ActOnAddrLabel(SourceLocation OpLoc,
+                                            SourceLocation LabLoc,
+                                            IdentifierInfo *LabelII) {
+  // Look up the record for this label identifier.
+  LabelStmt *&LabelDecl = getLabelMap()[LabelII];
+
+  // If we haven't seen this label yet, create a forward reference. It
+  // will be validated and/or cleaned up in ActOnFinishFunctionBody.
+  if (LabelDecl == 0)
+    LabelDecl = new (Context) LabelStmt(LabLoc, LabelII, 0);
+
+  // Create the AST node.  The address of a label always has type 'void*'.
+  return Owned(new (Context) AddrLabelExpr(OpLoc, LabLoc, LabelDecl,
+                                       Context.getPointerType(Context.VoidTy)));
+}
+
+Sema::OwningExprResult
+Sema::ActOnStmtExpr(SourceLocation LPLoc, StmtArg substmt,
+                    SourceLocation RPLoc) { // "({..})"
+  Stmt *SubStmt = static_cast<Stmt*>(substmt.get());
+  assert(SubStmt && isa<CompoundStmt>(SubStmt) && "Invalid action invocation!");
+  CompoundStmt *Compound = cast<CompoundStmt>(SubStmt);
+
+  bool isFileScope = getCurFunctionOrMethodDecl() == 0;
+  if (isFileScope)
+    return ExprError(Diag(LPLoc, diag::err_stmtexpr_file_scope));
+
+  // FIXME: there are a variety of strange constraints to enforce here, for
+  // example, it is not possible to goto into a stmt expression apparently.
+  // More semantic analysis is needed.
+
+  // If there are sub stmts in the compound stmt, take the type of the last one
+  // as the type of the stmtexpr.
+  QualType Ty = Context.VoidTy;
+
+  if (!Compound->body_empty()) {
+    Stmt *LastStmt = Compound->body_back();
+    // If LastStmt is a label, skip down through into the body.
+    while (LabelStmt *Label = dyn_cast<LabelStmt>(LastStmt))
+      LastStmt = Label->getSubStmt();
+
+    if (Expr *LastExpr = dyn_cast<Expr>(LastStmt))
+      Ty = LastExpr->getType();
+  }
+
+  // FIXME: Check that expression type is complete/non-abstract; statement
+  // expressions are not lvalues.
+
+  substmt.release();
+  return Owned(new (Context) StmtExpr(Compound, Ty, LPLoc, RPLoc));
+}
+
+Sema::OwningExprResult Sema::ActOnBuiltinOffsetOf(Scope *S,
+                                                  SourceLocation BuiltinLoc,
+                                                  SourceLocation TypeLoc,
+                                                  TypeTy *argty,
+                                                  OffsetOfComponent *CompPtr,
+                                                  unsigned NumComponents,
+                                                  SourceLocation RPLoc) {
+  // FIXME: This function leaks all expressions in the offset components on
+  // error.
+  // FIXME: Preserve type source info.
+  QualType ArgTy = GetTypeFromParser(argty);
+  assert(!ArgTy.isNull() && "Missing type argument!");
+
+  bool Dependent = ArgTy->isDependentType();
+
+  // We must have at least one component that refers to the type, and the first
+  // one is known to be a field designator.  Verify that the ArgTy represents
+  // a struct/union/class.
+  if (!Dependent && !ArgTy->isRecordType())
+    return ExprError(Diag(TypeLoc, diag::err_offsetof_record_type) << ArgTy);
+
+  // FIXME: Type must be complete per C99 7.17p3 because a declaring a variable
+  // with an incomplete type would be illegal.
+
+  // Otherwise, create a null pointer as the base, and iteratively process
+  // the offsetof designators.
+  QualType ArgTyPtr = Context.getPointerType(ArgTy);
+  Expr* Res = new (Context) ImplicitValueInitExpr(ArgTyPtr);
+  Res = new (Context) UnaryOperator(Res, UnaryOperator::Deref,
+                                    ArgTy, SourceLocation());
+
+  // offsetof with non-identifier designators (e.g. "offsetof(x, a.b[c])") are a
+  // GCC extension, diagnose them.
+  // FIXME: This diagnostic isn't actually visible because the location is in
+  // a system header!
+  if (NumComponents != 1)
+    Diag(BuiltinLoc, diag::ext_offsetof_extended_field_designator)
+      << SourceRange(CompPtr[1].LocStart, CompPtr[NumComponents-1].LocEnd);
+
+  if (!Dependent) {
+    bool DidWarnAboutNonPOD = false;
+
+    if (RequireCompleteType(TypeLoc, Res->getType(),
+                            diag::err_offsetof_incomplete_type))
+      return ExprError();
+
+    // FIXME: Dependent case loses a lot of information here. And probably
+    // leaks like a sieve.
+    for (unsigned i = 0; i != NumComponents; ++i) {
+      const OffsetOfComponent &OC = CompPtr[i];
+      if (OC.isBrackets) {
+        // Offset of an array sub-field.  TODO: Should we allow vector elements?
+        const ArrayType *AT = Context.getAsArrayType(Res->getType());
+        if (!AT) {
+          Res->Destroy(Context);
+          return ExprError(Diag(OC.LocEnd, diag::err_offsetof_array_type)
+            << Res->getType());
+        }
+
+        // FIXME: C++: Verify that operator[] isn't overloaded.
+
+        // Promote the array so it looks more like a normal array subscript
+        // expression.
+        DefaultFunctionArrayLvalueConversion(Res);
+
+        // C99 6.5.2.1p1
+        Expr *Idx = static_cast<Expr*>(OC.U.E);
+        // FIXME: Leaks Res
+        if (!Idx->isTypeDependent() && !Idx->getType()->isIntegerType())
+          return ExprError(Diag(Idx->getLocStart(),
+                                diag::err_typecheck_subscript_not_integer)
+            << Idx->getSourceRange());
+
+        Res = new (Context) ArraySubscriptExpr(Res, Idx, AT->getElementType(),
+                                               OC.LocEnd);
+        continue;
+      }
+
+      const RecordType *RC = Res->getType()->getAs<RecordType>();
+      if (!RC) {
+        Res->Destroy(Context);
+        return ExprError(Diag(OC.LocEnd, diag::err_offsetof_record_type)
+          << Res->getType());
+      }
+
+      // Get the decl corresponding to this.
+      RecordDecl *RD = RC->getDecl();
+      if (CXXRecordDecl *CRD = dyn_cast<CXXRecordDecl>(RD)) {
+        if (!CRD->isPOD() && !DidWarnAboutNonPOD &&
+            DiagRuntimeBehavior(BuiltinLoc,
+                                PDiag(diag::warn_offsetof_non_pod_type)
+                                  << SourceRange(CompPtr[0].LocStart, OC.LocEnd)
+                                  << Res->getType()))
+          DidWarnAboutNonPOD = true;
+      }
+
+      LookupResult R(*this, OC.U.IdentInfo, OC.LocStart, LookupMemberName);
+      LookupQualifiedName(R, RD);
+
+      FieldDecl *MemberDecl = R.getAsSingle<FieldDecl>();
+      // FIXME: Leaks Res
+      if (!MemberDecl)
+        return ExprError(Diag(BuiltinLoc, diag::err_no_member)
+         << OC.U.IdentInfo << RD << SourceRange(OC.LocStart, OC.LocEnd));
+
+      // FIXME: C++: Verify that MemberDecl isn't a static field.
+      // FIXME: Verify that MemberDecl isn't a bitfield.
+      if (cast<RecordDecl>(MemberDecl->getDeclContext())->isAnonymousStructOrUnion()) {
+        Res = BuildAnonymousStructUnionMemberReference(
+            OC.LocEnd, MemberDecl, Res, OC.LocEnd).takeAs<Expr>();
+      } else {
+        PerformObjectMemberConversion(Res, MemberDecl);
+        // MemberDecl->getType() doesn't get the right qualifiers, but it
+        // doesn't matter here.
+        Res = new (Context) MemberExpr(Res, false, MemberDecl, OC.LocEnd,
+                MemberDecl->getType().getNonReferenceType());
+      }
+    }
+  }
+
+  return Owned(new (Context) UnaryOperator(Res, UnaryOperator::OffsetOf,
+                                           Context.getSizeType(), BuiltinLoc));
+}
+
+
+Sema::OwningExprResult Sema::ActOnTypesCompatibleExpr(SourceLocation BuiltinLoc,
+                                                      TypeTy *arg1,TypeTy *arg2,
+                                                      SourceLocation RPLoc) {
+  // FIXME: Preserve type source info.
+  QualType argT1 = GetTypeFromParser(arg1);
+  QualType argT2 = GetTypeFromParser(arg2);
+
+  assert((!argT1.isNull() && !argT2.isNull()) && "Missing type argument(s)");
+
+  if (getLangOptions().CPlusPlus) {
+    Diag(BuiltinLoc, diag::err_types_compatible_p_in_cplusplus)
+      << SourceRange(BuiltinLoc, RPLoc);
+    return ExprError();
+  }
+
+  return Owned(new (Context) TypesCompatibleExpr(Context.IntTy, BuiltinLoc,
+                                                 argT1, argT2, RPLoc));
+}
+
+Sema::OwningExprResult Sema::ActOnChooseExpr(SourceLocation BuiltinLoc,
+                                             ExprArg cond,
+                                             ExprArg expr1, ExprArg expr2,
+                                             SourceLocation RPLoc) {
+  Expr *CondExpr = static_cast<Expr*>(cond.get());
+  Expr *LHSExpr = static_cast<Expr*>(expr1.get());
+  Expr *RHSExpr = static_cast<Expr*>(expr2.get());
+
+  assert((CondExpr && LHSExpr && RHSExpr) && "Missing type argument(s)");
+
+  QualType resType;
+  bool ValueDependent = false;
+  if (CondExpr->isTypeDependent() || CondExpr->isValueDependent()) {
+    resType = Context.DependentTy;
+    ValueDependent = true;
+  } else {
+    // The conditional expression is required to be a constant expression.
+    llvm::APSInt condEval(32);
+    SourceLocation ExpLoc;
+    if (!CondExpr->isIntegerConstantExpr(condEval, Context, &ExpLoc))
+      return ExprError(Diag(ExpLoc,
+                       diag::err_typecheck_choose_expr_requires_constant)
+        << CondExpr->getSourceRange());
+
+    // If the condition is > zero, then the AST type is the same as the LSHExpr.
+    resType = condEval.getZExtValue() ? LHSExpr->getType() : RHSExpr->getType();
+    ValueDependent = condEval.getZExtValue() ? LHSExpr->isValueDependent()
+                                             : RHSExpr->isValueDependent();
+  }
+
+  cond.release(); expr1.release(); expr2.release();
+  return Owned(new (Context) ChooseExpr(BuiltinLoc, CondExpr, LHSExpr, RHSExpr,
+                                        resType, RPLoc,
+                                        resType->isDependentType(),
+                                        ValueDependent));
+}
+
+//===----------------------------------------------------------------------===//
+// Clang Extensions.
+//===----------------------------------------------------------------------===//
+
+/// ActOnBlockStart - This callback is invoked when a block literal is started.
+void Sema::ActOnBlockStart(SourceLocation CaretLoc, Scope *BlockScope) {
+  // Analyze block parameters.
+  BlockSemaInfo *BSI = new BlockSemaInfo();
+
+  // Add BSI to CurBlock.
+  BSI->PrevBlockInfo = CurBlock;
+  CurBlock = BSI;
+
+  BSI->ReturnType = QualType();
+  BSI->TheScope = BlockScope;
+  BSI->hasBlockDeclRefExprs = false;
+  BSI->hasPrototype = false;
+  BSI->SavedFunctionNeedsScopeChecking = CurFunctionNeedsScopeChecking;
+  CurFunctionNeedsScopeChecking = false;
+
+  BSI->TheDecl = BlockDecl::Create(Context, CurContext, CaretLoc);
+  CurContext->addDecl(BSI->TheDecl);
+  PushDeclContext(BlockScope, BSI->TheDecl);
+}
+
+void Sema::ActOnBlockArguments(Declarator &ParamInfo, Scope *CurScope) {
+  assert(ParamInfo.getIdentifier()==0 && "block-id should have no identifier!");
+
+  if (ParamInfo.getNumTypeObjects() == 0
+      || ParamInfo.getTypeObject(0).Kind != DeclaratorChunk::Function) {
+    ProcessDeclAttributes(CurScope, CurBlock->TheDecl, ParamInfo);
+    QualType T = GetTypeForDeclarator(ParamInfo, CurScope);
+
+    if (T->isArrayType()) {
+      Diag(ParamInfo.getSourceRange().getBegin(),
+           diag::err_block_returns_array);
+      return;
+    }
+
+    // The parameter list is optional, if there was none, assume ().
+    if (!T->isFunctionType())
+      T = Context.getFunctionType(T, NULL, 0, 0, 0);
+
+    CurBlock->hasPrototype = true;
+    CurBlock->isVariadic = false;
+    // Check for a valid sentinel attribute on this block.
+    if (CurBlock->TheDecl->getAttr<SentinelAttr>()) {
+      Diag(ParamInfo.getAttributes()->getLoc(),
+           diag::warn_attribute_sentinel_not_variadic) << 1;
+      // FIXME: remove the attribute.
+    }
+    QualType RetTy = T.getTypePtr()->getAs<FunctionType>()->getResultType();
+
+    // Do not allow returning a objc interface by-value.
+    if (RetTy->isObjCInterfaceType()) {
+      Diag(ParamInfo.getSourceRange().getBegin(),
+           diag::err_object_cannot_be_passed_returned_by_value) << 0 << RetTy;
+      return;
+    }
+
+    CurBlock->ReturnType = RetTy;
+    return;
+  }
+
+  // Analyze arguments to block.
+  assert(ParamInfo.getTypeObject(0).Kind == DeclaratorChunk::Function &&
+         "Not a function declarator!");
+  DeclaratorChunk::FunctionTypeInfo &FTI = ParamInfo.getTypeObject(0).Fun;
+
+  CurBlock->hasPrototype = FTI.hasPrototype;
+  CurBlock->isVariadic = true;
+
+  // 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.hasPrototype &&
+      FTI.NumArgs == 1 && !FTI.isVariadic && FTI.ArgInfo[0].Ident == 0 &&
+     (!FTI.ArgInfo[0].Param.getAs<ParmVarDecl>()->getType().getCVRQualifiers()&&
+        FTI.ArgInfo[0].Param.getAs<ParmVarDecl>()->getType()->isVoidType())) {
+    // empty arg list, don't push any params.
+    CurBlock->isVariadic = false;
+  } else if (FTI.hasPrototype) {
+    for (unsigned i = 0, e = FTI.NumArgs; i != e; ++i)
+      CurBlock->Params.push_back(FTI.ArgInfo[i].Param.getAs<ParmVarDecl>());
+    CurBlock->isVariadic = FTI.isVariadic;
+  }
+  CurBlock->TheDecl->setParams(Context, CurBlock->Params.data(),
+                               CurBlock->Params.size());
+  CurBlock->TheDecl->setIsVariadic(CurBlock->isVariadic);
+  ProcessDeclAttributes(CurScope, CurBlock->TheDecl, ParamInfo);
+  for (BlockDecl::param_iterator AI = CurBlock->TheDecl->param_begin(),
+         E = CurBlock->TheDecl->param_end(); AI != E; ++AI) {
+    (*AI)->setOwningFunction(CurBlock->TheDecl);
+
+    // If this has an identifier, add it to the scope stack.
+    if ((*AI)->getIdentifier())
+      PushOnScopeChains(*AI, CurBlock->TheScope);
+  }
+
+  // Check for a valid sentinel attribute on this block.
+  if (!CurBlock->isVariadic &&
+      CurBlock->TheDecl->getAttr<SentinelAttr>()) {
+    Diag(ParamInfo.getAttributes()->getLoc(),
+         diag::warn_attribute_sentinel_not_variadic) << 1;
+    // FIXME: remove the attribute.
+  }
+
+  // Analyze the return type.
+  QualType T = GetTypeForDeclarator(ParamInfo, CurScope);
+  QualType RetTy = T->getAs<FunctionType>()->getResultType();
+
+  // Do not allow returning a objc interface by-value.
+  if (RetTy->isObjCInterfaceType()) {
+    Diag(ParamInfo.getSourceRange().getBegin(),
+         diag::err_object_cannot_be_passed_returned_by_value) << 0 << RetTy;
+  } else if (!RetTy->isDependentType())
+    CurBlock->ReturnType = RetTy;
+}
+
+/// ActOnBlockError - If there is an error parsing a block, this callback
+/// is invoked to pop the information about the block from the action impl.
+void Sema::ActOnBlockError(SourceLocation CaretLoc, Scope *CurScope) {
+  // Ensure that CurBlock is deleted.
+  llvm::OwningPtr<BlockSemaInfo> CC(CurBlock);
+
+  CurFunctionNeedsScopeChecking = CurBlock->SavedFunctionNeedsScopeChecking;
+
+  // Pop off CurBlock, handle nested blocks.
+  PopDeclContext();
+  CurBlock = CurBlock->PrevBlockInfo;
+  // FIXME: Delete the ParmVarDecl objects as well???
+}
+
+/// ActOnBlockStmtExpr - This is called when the body of a block statement
+/// literal was successfully completed.  ^(int x){...}
+Sema::OwningExprResult Sema::ActOnBlockStmtExpr(SourceLocation CaretLoc,
+                                                StmtArg body, Scope *CurScope) {
+  // If blocks are disabled, emit an error.
+  if (!LangOpts.Blocks)
+    Diag(CaretLoc, diag::err_blocks_disable);
+
+  // Ensure that CurBlock is deleted.
+  llvm::OwningPtr<BlockSemaInfo> BSI(CurBlock);
+
+  PopDeclContext();
+
+  // Pop off CurBlock, handle nested blocks.
+  CurBlock = CurBlock->PrevBlockInfo;
+
+  QualType RetTy = Context.VoidTy;
+  if (!BSI->ReturnType.isNull())
+    RetTy = BSI->ReturnType;
+
+  llvm::SmallVector<QualType, 8> ArgTypes;
+  for (unsigned i = 0, e = BSI->Params.size(); i != e; ++i)
+    ArgTypes.push_back(BSI->Params[i]->getType());
+
+  bool NoReturn = BSI->TheDecl->getAttr<NoReturnAttr>();
+  QualType BlockTy;
+  if (!BSI->hasPrototype)
+    BlockTy = Context.getFunctionType(RetTy, 0, 0, false, 0, false, false, 0, 0,
+                                      NoReturn);
+  else
+    BlockTy = Context.getFunctionType(RetTy, ArgTypes.data(), ArgTypes.size(),
+                                      BSI->isVariadic, 0, false, false, 0, 0,
+                                      NoReturn);
+
+  // FIXME: Check that return/parameter types are complete/non-abstract
+  DiagnoseUnusedParameters(BSI->Params.begin(), BSI->Params.end());
+  BlockTy = Context.getBlockPointerType(BlockTy);
+
+  // If needed, diagnose invalid gotos and switches in the block.
+  if (CurFunctionNeedsScopeChecking)
+    DiagnoseInvalidJumps(static_cast<CompoundStmt*>(body.get()));
+  CurFunctionNeedsScopeChecking = BSI->SavedFunctionNeedsScopeChecking;
+
+  BSI->TheDecl->setBody(body.takeAs<CompoundStmt>());
+
+  bool Good = true;
+  // Check goto/label use.
+  for (llvm::DenseMap<IdentifierInfo*, LabelStmt*>::iterator
+         I = BSI->LabelMap.begin(), E = BSI->LabelMap.end(); I != E; ++I) {
+    LabelStmt *L = I->second;
+
+    // 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.
+    if (L->getSubStmt() != 0)
+      continue;
+
+    // Emit error.
+    Diag(L->getIdentLoc(), diag::err_undeclared_label_use) << L->getName();
+    Good = false;
+  }
+  BSI->LabelMap.clear();
+  if (!Good)
+    return ExprError();
+
+  AnalysisContext AC(BSI->TheDecl);
+  CheckFallThroughForBlock(BlockTy, BSI->TheDecl->getBody(), AC);
+  CheckUnreachable(AC);
+  return Owned(new (Context) BlockExpr(BSI->TheDecl, BlockTy,
+                                       BSI->hasBlockDeclRefExprs));
+}
+
+Sema::OwningExprResult Sema::ActOnVAArg(SourceLocation BuiltinLoc,
+                                        ExprArg expr, TypeTy *type,
+                                        SourceLocation RPLoc) {
+  QualType T = GetTypeFromParser(type);
+  Expr *E = static_cast<Expr*>(expr.get());
+  Expr *OrigExpr = E;
+
+  InitBuiltinVaListType();
+
+  // Get the va_list type
+  QualType VaListType = Context.getBuiltinVaListType();
+  if (VaListType->isArrayType()) {
+    // Deal with implicit array decay; for example, on x86-64,
+    // va_list is an array, but it's supposed to decay to
+    // a pointer for va_arg.
+    VaListType = Context.getArrayDecayedType(VaListType);
+    // Make sure the input expression also decays appropriately.
+    UsualUnaryConversions(E);
+  } else {
+    // Otherwise, the va_list argument must be an l-value because
+    // it is modified by va_arg.
+    if (!E->isTypeDependent() &&
+        CheckForModifiableLvalue(E, BuiltinLoc, *this))
+      return ExprError();
+  }
+
+  if (!E->isTypeDependent() &&
+      !Context.hasSameType(VaListType, E->getType())) {
+    return ExprError(Diag(E->getLocStart(),
+                         diag::err_first_argument_to_va_arg_not_of_type_va_list)
+      << OrigExpr->getType() << E->getSourceRange());
+  }
+
+  // FIXME: Check that type is complete/non-abstract
+  // FIXME: Warn if a non-POD type is passed in.
+
+  expr.release();
+  return Owned(new (Context) VAArgExpr(BuiltinLoc, E, T.getNonReferenceType(),
+                                       RPLoc));
+}
+
+Sema::OwningExprResult Sema::ActOnGNUNullExpr(SourceLocation TokenLoc) {
+  // The type of __null will be int or long, depending on the size of
+  // pointers on the target.
+  QualType Ty;
+  if (Context.Target.getPointerWidth(0) == Context.Target.getIntWidth())
+    Ty = Context.IntTy;
+  else
+    Ty = Context.LongTy;
+
+  return Owned(new (Context) GNUNullExpr(Ty, TokenLoc));
+}
+
+static void 
+MakeObjCStringLiteralCodeModificationHint(Sema& SemaRef,
+                                          QualType DstType,
+                                          Expr *SrcExpr,
+                                          CodeModificationHint &Hint) {
+  if (!SemaRef.getLangOptions().ObjC1)
+    return;
+  
+  const ObjCObjectPointerType *PT = DstType->getAs<ObjCObjectPointerType>();
+  if (!PT)
+    return;
+
+  // Check if the destination is of type 'id'.
+  if (!PT->isObjCIdType()) {
+    // Check if the destination is the 'NSString' interface.
+    const ObjCInterfaceDecl *ID = PT->getInterfaceDecl();
+    if (!ID || !ID->getIdentifier()->isStr("NSString"))
+      return;
+  }
+  
+  // Strip off any parens and casts.
+  StringLiteral *SL = dyn_cast<StringLiteral>(SrcExpr->IgnoreParenCasts());
+  if (!SL || SL->isWide())
+    return;
+  
+  Hint = CodeModificationHint::CreateInsertion(SL->getLocStart(), "@");
+}
+
+bool Sema::DiagnoseAssignmentResult(AssignConvertType ConvTy,
+                                    SourceLocation Loc,
+                                    QualType DstType, QualType SrcType,
+                                    Expr *SrcExpr, AssignmentAction Action) {
+  // Decode the result (notice that AST's are still created for extensions).
+  bool isInvalid = false;
+  unsigned DiagKind;
+  CodeModificationHint Hint;
+  
+  switch (ConvTy) {
+  default: assert(0 && "Unknown conversion type");
+  case Compatible: return false;
+  case PointerToInt:
+    DiagKind = diag::ext_typecheck_convert_pointer_int;
+    break;
+  case IntToPointer:
+    DiagKind = diag::ext_typecheck_convert_int_pointer;
+    break;
+  case IncompatiblePointer:
+    MakeObjCStringLiteralCodeModificationHint(*this, DstType, SrcExpr, Hint);
+    DiagKind = diag::ext_typecheck_convert_incompatible_pointer;
+    break;
+  case IncompatiblePointerSign:
+    DiagKind = diag::ext_typecheck_convert_incompatible_pointer_sign;
+    break;
+  case FunctionVoidPointer:
+    DiagKind = diag::ext_typecheck_convert_pointer_void_func;
+    break;
+  case CompatiblePointerDiscardsQualifiers:
+    // If the qualifiers lost were because we were applying the
+    // (deprecated) C++ conversion from a string literal to a char*
+    // (or wchar_t*), then there was no error (C++ 4.2p2).  FIXME:
+    // Ideally, this check would be performed in
+    // CheckPointerTypesForAssignment. However, that would require a
+    // bit of refactoring (so that the second argument is an
+    // expression, rather than a type), which should be done as part
+    // of a larger effort to fix CheckPointerTypesForAssignment for
+    // C++ semantics.
+    if (getLangOptions().CPlusPlus &&
+        IsStringLiteralToNonConstPointerConversion(SrcExpr, DstType))
+      return false;
+    DiagKind = diag::ext_typecheck_convert_discards_qualifiers;
+    break;
+  case IncompatibleNestedPointerQualifiers:
+    DiagKind = diag::ext_nested_pointer_qualifier_mismatch;
+    break;
+  case IntToBlockPointer:
+    DiagKind = diag::err_int_to_block_pointer;
+    break;
+  case IncompatibleBlockPointer:
+    DiagKind = diag::err_typecheck_convert_incompatible_block_pointer;
+    break;
+  case IncompatibleObjCQualifiedId:
+    // FIXME: Diagnose the problem in ObjCQualifiedIdTypesAreCompatible, since
+    // it can give a more specific diagnostic.
+    DiagKind = diag::warn_incompatible_qualified_id;
+    break;
+  case IncompatibleVectors:
+    DiagKind = diag::warn_incompatible_vectors;
+    break;
+  case Incompatible:
+    DiagKind = diag::err_typecheck_convert_incompatible;
+    isInvalid = true;
+    break;
+  }
+
+  Diag(Loc, DiagKind) << DstType << SrcType << Action
+    << SrcExpr->getSourceRange() << Hint;
+  return isInvalid;
+}
+
+bool Sema::VerifyIntegerConstantExpression(const Expr *E, llvm::APSInt *Result){
+  llvm::APSInt ICEResult;
+  if (E->isIntegerConstantExpr(ICEResult, Context)) {
+    if (Result)
+      *Result = ICEResult;
+    return false;
+  }
+
+  Expr::EvalResult EvalResult;
+
+  if (!E->Evaluate(EvalResult, Context) || !EvalResult.Val.isInt() ||
+      EvalResult.HasSideEffects) {
+    Diag(E->getExprLoc(), diag::err_expr_not_ice) << E->getSourceRange();
+
+    if (EvalResult.Diag) {
+      // We only show the note if it's not the usual "invalid subexpression"
+      // or if it's actually in a subexpression.
+      if (EvalResult.Diag != diag::note_invalid_subexpr_in_ice ||
+          E->IgnoreParens() != EvalResult.DiagExpr->IgnoreParens())
+        Diag(EvalResult.DiagLoc, EvalResult.Diag);
+    }
+
+    return true;
+  }
+
+  Diag(E->getExprLoc(), diag::ext_expr_not_ice) <<
+    E->getSourceRange();
+
+  if (EvalResult.Diag &&
+      Diags.getDiagnosticLevel(diag::ext_expr_not_ice) != Diagnostic::Ignored)
+    Diag(EvalResult.DiagLoc, EvalResult.Diag);
+
+  if (Result)
+    *Result = EvalResult.Val.getInt();
+  return false;
+}
+
+void
+Sema::PushExpressionEvaluationContext(ExpressionEvaluationContext NewContext) {
+  ExprEvalContexts.push_back(
+        ExpressionEvaluationContextRecord(NewContext, ExprTemporaries.size()));
+}
+
+void
+Sema::PopExpressionEvaluationContext() {
+  // Pop the current expression evaluation context off the stack.
+  ExpressionEvaluationContextRecord Rec = ExprEvalContexts.back();
+  ExprEvalContexts.pop_back();
+
+  if (Rec.Context == PotentiallyPotentiallyEvaluated) {
+    if (Rec.PotentiallyReferenced) {
+      // Mark any remaining declarations in the current position of the stack
+      // as "referenced". If they were not meant to be referenced, semantic
+      // analysis would have eliminated them (e.g., in ActOnCXXTypeId).
+      for (PotentiallyReferencedDecls::iterator 
+             I = Rec.PotentiallyReferenced->begin(),
+             IEnd = Rec.PotentiallyReferenced->end();
+           I != IEnd; ++I)
+        MarkDeclarationReferenced(I->first, I->second);
+    }
+
+    if (Rec.PotentiallyDiagnosed) {
+      // Emit any pending diagnostics.
+      for (PotentiallyEmittedDiagnostics::iterator
+                I = Rec.PotentiallyDiagnosed->begin(),
+             IEnd = Rec.PotentiallyDiagnosed->end();
+           I != IEnd; ++I)
+        Diag(I->first, I->second);
+    }
+  } 
+
+  // When are coming out of an unevaluated context, clear out any
+  // temporaries that we may have created as part of the evaluation of
+  // the expression in that context: they aren't relevant because they
+  // will never be constructed.
+  if (Rec.Context == Unevaluated && 
+      ExprTemporaries.size() > Rec.NumTemporaries)
+    ExprTemporaries.erase(ExprTemporaries.begin() + Rec.NumTemporaries,
+                          ExprTemporaries.end());
+
+  // Destroy the popped expression evaluation record.
+  Rec.Destroy();
+}
+
+/// \brief Note that the given declaration was referenced in the source code.
+///
+/// This routine should be invoke whenever a given declaration is referenced
+/// in the source code, and where that reference occurred. If this declaration
+/// reference means that the the declaration is used (C++ [basic.def.odr]p2,
+/// C99 6.9p3), then the declaration will be marked as used.
+///
+/// \param Loc the location where the declaration was referenced.
+///
+/// \param D the declaration that has been referenced by the source code.
+void Sema::MarkDeclarationReferenced(SourceLocation Loc, Decl *D) {
+  assert(D && "No declaration?");
+
+  if (D->isUsed())
+    return;
+
+  // Mark a parameter or variable declaration "used", regardless of whether we're in a
+  // template or not. The reason for this is that unevaluated expressions
+  // (e.g. (void)sizeof()) constitute a use for warning purposes (-Wunused-variables and
+  // -Wunused-parameters)
+  if (isa<ParmVarDecl>(D) || 
+      (isa<VarDecl>(D) && D->getDeclContext()->isFunctionOrMethod()))
+    D->setUsed(true);
+
+  // Do not mark anything as "used" within a dependent context; wait for
+  // an instantiation.
+  if (CurContext->isDependentContext())
+    return;
+
+  switch (ExprEvalContexts.back().Context) {
+    case Unevaluated:
+      // We are in an expression that is not potentially evaluated; do nothing.
+      return;
+
+    case PotentiallyEvaluated:
+      // We are in a potentially-evaluated expression, so this declaration is
+      // "used"; handle this below.
+      break;
+
+    case PotentiallyPotentiallyEvaluated:
+      // We are in an expression that may be potentially evaluated; queue this
+      // declaration reference until we know whether the expression is
+      // potentially evaluated.
+      ExprEvalContexts.back().addReferencedDecl(Loc, D);
+      return;
+  }
+
+  // Note that this declaration has been used.
+  if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(D)) {
+    unsigned TypeQuals;
+    if (Constructor->isImplicit() && Constructor->isDefaultConstructor()) {
+        if (!Constructor->isUsed())
+          DefineImplicitDefaultConstructor(Loc, Constructor);
+    } else if (Constructor->isImplicit() &&
+               Constructor->isCopyConstructor(TypeQuals)) {
+      if (!Constructor->isUsed())
+        DefineImplicitCopyConstructor(Loc, Constructor, TypeQuals);
+    }
+    
+    MaybeMarkVirtualMembersReferenced(Loc, Constructor);
+  } else if (CXXDestructorDecl *Destructor = dyn_cast<CXXDestructorDecl>(D)) {
+    if (Destructor->isImplicit() && !Destructor->isUsed())
+      DefineImplicitDestructor(Loc, Destructor);
+
+  } else if (CXXMethodDecl *MethodDecl = dyn_cast<CXXMethodDecl>(D)) {
+    if (MethodDecl->isImplicit() && MethodDecl->isOverloadedOperator() &&
+        MethodDecl->getOverloadedOperator() == OO_Equal) {
+      if (!MethodDecl->isUsed())
+        DefineImplicitOverloadedAssign(Loc, MethodDecl);
+    }
+  }
+  if (FunctionDecl *Function = dyn_cast<FunctionDecl>(D)) {
+    // Implicit instantiation of function templates and member functions of
+    // class templates.
+    if (!Function->getBody() && Function->isImplicitlyInstantiable()) {
+      bool AlreadyInstantiated = false;
+      if (FunctionTemplateSpecializationInfo *SpecInfo
+                                = Function->getTemplateSpecializationInfo()) {
+        if (SpecInfo->getPointOfInstantiation().isInvalid())
+          SpecInfo->setPointOfInstantiation(Loc);
+        else if (SpecInfo->getTemplateSpecializationKind() 
+                   == TSK_ImplicitInstantiation)
+          AlreadyInstantiated = true;
+      } else if (MemberSpecializationInfo *MSInfo 
+                                  = Function->getMemberSpecializationInfo()) {
+        if (MSInfo->getPointOfInstantiation().isInvalid())
+          MSInfo->setPointOfInstantiation(Loc);
+        else if (MSInfo->getTemplateSpecializationKind() 
+                   == TSK_ImplicitInstantiation)
+          AlreadyInstantiated = true;
+      }
+      
+      if (!AlreadyInstantiated) {
+        if (isa<CXXRecordDecl>(Function->getDeclContext()) &&
+            cast<CXXRecordDecl>(Function->getDeclContext())->isLocalClass())
+          PendingLocalImplicitInstantiations.push_back(std::make_pair(Function,
+                                                                      Loc));
+        else
+          PendingImplicitInstantiations.push_back(std::make_pair(Function, 
+                                                                 Loc));
+      }
+    }
+    
+    // FIXME: keep track of references to static functions
+    Function->setUsed(true);
+    return;
+  }
+
+  if (VarDecl *Var = dyn_cast<VarDecl>(D)) {
+    // Implicit instantiation of static data members of class templates.
+    if (Var->isStaticDataMember() &&
+        Var->getInstantiatedFromStaticDataMember()) {
+      MemberSpecializationInfo *MSInfo = Var->getMemberSpecializationInfo();
+      assert(MSInfo && "Missing member specialization information?");
+      if (MSInfo->getPointOfInstantiation().isInvalid() &&
+          MSInfo->getTemplateSpecializationKind()== TSK_ImplicitInstantiation) {
+        MSInfo->setPointOfInstantiation(Loc);
+        PendingImplicitInstantiations.push_back(std::make_pair(Var, Loc));
+      }
+    }
+
+    // FIXME: keep track of references to static data?
+
+    D->setUsed(true);
+    return;
+  }
+}
+
+/// \brief Emit a diagnostic that describes an effect on the run-time behavior
+/// of the program being compiled.
+///
+/// This routine emits the given diagnostic when the code currently being
+/// type-checked is "potentially evaluated", meaning that there is a 
+/// possibility that the code will actually be executable. Code in sizeof()
+/// expressions, code used only during overload resolution, etc., are not
+/// potentially evaluated. This routine will suppress such diagnostics or,
+/// in the absolutely nutty case of potentially potentially evaluated
+/// expressions (C++ typeid), queue the diagnostic to potentially emit it 
+/// later.
+/// 
+/// This routine should be used for all diagnostics that describe the run-time
+/// behavior of a program, such as passing a non-POD value through an ellipsis.
+/// Failure to do so will likely result in spurious diagnostics or failures
+/// during overload resolution or within sizeof/alignof/typeof/typeid.
+bool Sema::DiagRuntimeBehavior(SourceLocation Loc, 
+                               const PartialDiagnostic &PD) {
+  switch (ExprEvalContexts.back().Context ) {
+  case Unevaluated:
+    // The argument will never be evaluated, so don't complain.
+    break;
+      
+  case PotentiallyEvaluated:
+    Diag(Loc, PD);
+    return true;
+      
+  case PotentiallyPotentiallyEvaluated:
+    ExprEvalContexts.back().addDiagnostic(Loc, PD);
+    break;
+  }
+
+  return false;
+}
+
+bool Sema::CheckCallReturnType(QualType ReturnType, SourceLocation Loc,
+                               CallExpr *CE, FunctionDecl *FD) {
+  if (ReturnType->isVoidType() || !ReturnType->isIncompleteType())
+    return false;
+
+  PartialDiagnostic Note =
+    FD ? PDiag(diag::note_function_with_incomplete_return_type_declared_here)
+    << FD->getDeclName() : PDiag();
+  SourceLocation NoteLoc = FD ? FD->getLocation() : SourceLocation();
+  
+  if (RequireCompleteType(Loc, ReturnType,
+                          FD ? 
+                          PDiag(diag::err_call_function_incomplete_return)
+                            << CE->getSourceRange() << FD->getDeclName() :
+                          PDiag(diag::err_call_incomplete_return) 
+                            << CE->getSourceRange(),
+                          std::make_pair(NoteLoc, Note)))
+    return true;
+
+  return false;
+}
+
+// Diagnose the common s/=/==/ typo.  Note that adding parentheses
+// will prevent this condition from triggering, which is what we want.
+void Sema::DiagnoseAssignmentAsCondition(Expr *E) {
+  SourceLocation Loc;
+
+  unsigned diagnostic = diag::warn_condition_is_assignment;
+
+  if (isa<BinaryOperator>(E)) {
+    BinaryOperator *Op = cast<BinaryOperator>(E);
+    if (Op->getOpcode() != BinaryOperator::Assign)
+      return;
+
+    // Greylist some idioms by putting them into a warning subcategory.
+    if (ObjCMessageExpr *ME
+          = dyn_cast<ObjCMessageExpr>(Op->getRHS()->IgnoreParenCasts())) {
+      Selector Sel = ME->getSelector();
+
+      // self = [<foo> init...]
+      if (isSelfExpr(Op->getLHS())
+          && Sel.getIdentifierInfoForSlot(0)->getName().startswith("init"))
+        diagnostic = diag::warn_condition_is_idiomatic_assignment;
+
+      // <foo> = [<bar> nextObject]
+      else if (Sel.isUnarySelector() &&
+               Sel.getIdentifierInfoForSlot(0)->getName() == "nextObject")
+        diagnostic = diag::warn_condition_is_idiomatic_assignment;
+    }
+
+    Loc = Op->getOperatorLoc();
+  } else if (isa<CXXOperatorCallExpr>(E)) {
+    CXXOperatorCallExpr *Op = cast<CXXOperatorCallExpr>(E);
+    if (Op->getOperator() != OO_Equal)
+      return;
+
+    Loc = Op->getOperatorLoc();
+  } else {
+    // Not an assignment.
+    return;
+  }
+
+  SourceLocation Open = E->getSourceRange().getBegin();
+  SourceLocation Close = PP.getLocForEndOfToken(E->getSourceRange().getEnd());
+  
+  Diag(Loc, diagnostic)
+    << E->getSourceRange()
+    << CodeModificationHint::CreateInsertion(Open, "(")
+    << CodeModificationHint::CreateInsertion(Close, ")");
+  Diag(Loc, diag::note_condition_assign_to_comparison)
+    << CodeModificationHint::CreateReplacement(Loc, "==");
+}
+
+bool Sema::CheckBooleanCondition(Expr *&E, SourceLocation Loc) {
+  DiagnoseAssignmentAsCondition(E);
+
+  if (!E->isTypeDependent()) {
+    DefaultFunctionArrayLvalueConversion(E);
+
+    QualType T = E->getType();
+
+    if (getLangOptions().CPlusPlus) {
+      if (CheckCXXBooleanCondition(E)) // C++ 6.4p4
+        return true;
+    } else if (!T->isScalarType()) { // C99 6.8.4.1p1
+      Diag(Loc, diag::err_typecheck_statement_requires_scalar)
+        << T << E->getSourceRange();
+      return true;
+    }
+  }
+
+  return false;
+}
diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp
new file mode 100644
index 0000000..e27308a
--- /dev/null
+++ b/lib/Sema/SemaExprCXX.cpp
@@ -0,0 +1,2196 @@
+//===--- SemaExprCXX.cpp - Semantic Analysis for Expressions --------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+//  This file implements semantic analysis for C++ expressions.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Sema.h"
+#include "SemaInit.h"
+#include "Lookup.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/CXXInheritance.h"
+#include "clang/AST/ExprCXX.h"
+#include "clang/Basic/PartialDiagnostic.h"
+#include "clang/Basic/TargetInfo.h"
+#include "clang/Lex/Preprocessor.h"
+#include "clang/Parse/DeclSpec.h"
+#include "llvm/ADT/STLExtras.h"
+using namespace clang;
+
+/// ActOnCXXTypeidOfType - Parse typeid( type-id ).
+Action::OwningExprResult
+Sema::ActOnCXXTypeid(SourceLocation OpLoc, SourceLocation LParenLoc,
+                     bool isType, void *TyOrExpr, SourceLocation RParenLoc) {
+  if (!StdNamespace)
+    return ExprError(Diag(OpLoc, diag::err_need_header_before_typeid));
+
+  if (isType) {
+    // C++ [expr.typeid]p4:
+    //   The top-level cv-qualifiers of the lvalue expression or the type-id 
+    //   that is the operand of typeid are always ignored.
+    // FIXME: Preserve type source info.
+    // FIXME: Preserve the type before we stripped the cv-qualifiers?
+    QualType T = GetTypeFromParser(TyOrExpr);
+    if (T.isNull())
+      return ExprError();
+    
+    // C++ [expr.typeid]p4:
+    //   If the type of the type-id is a class type or a reference to a class 
+    //   type, the class shall be completely-defined.
+    QualType CheckT = T;
+    if (const ReferenceType *RefType = CheckT->getAs<ReferenceType>())
+      CheckT = RefType->getPointeeType();
+    
+    if (CheckT->getAs<RecordType>() &&
+        RequireCompleteType(OpLoc, CheckT, diag::err_incomplete_typeid))
+      return ExprError();
+    
+    TyOrExpr = T.getUnqualifiedType().getAsOpaquePtr();
+  }
+
+  IdentifierInfo *TypeInfoII = &PP.getIdentifierTable().get("type_info");
+  LookupResult R(*this, TypeInfoII, SourceLocation(), LookupTagName);
+  LookupQualifiedName(R, StdNamespace);
+  RecordDecl *TypeInfoRecordDecl = R.getAsSingle<RecordDecl>();
+  if (!TypeInfoRecordDecl)
+    return ExprError(Diag(OpLoc, diag::err_need_header_before_typeid));
+
+  QualType TypeInfoType = Context.getTypeDeclType(TypeInfoRecordDecl);
+
+  if (!isType) {
+    bool isUnevaluatedOperand = true;
+    Expr *E = static_cast<Expr *>(TyOrExpr);
+    if (E && !E->isTypeDependent()) {
+      QualType T = E->getType();
+      if (const RecordType *RecordT = T->getAs<RecordType>()) {
+        CXXRecordDecl *RecordD = cast<CXXRecordDecl>(RecordT->getDecl());
+        // C++ [expr.typeid]p3:
+        //   [...] If the type of the expression is a class type, the class
+        //   shall be completely-defined.
+        if (RequireCompleteType(OpLoc, T, diag::err_incomplete_typeid))
+          return ExprError();
+
+        // C++ [expr.typeid]p3:
+        //   When typeid is applied to an expression other than an lvalue of a
+        //   polymorphic class type [...] [the] expression is an unevaluated
+        //   operand. [...]
+        if (RecordD->isPolymorphic() && E->isLvalue(Context) == Expr::LV_Valid)
+          isUnevaluatedOperand = false;
+      }
+
+      // C++ [expr.typeid]p4:
+      //   [...] If the type of the type-id is a reference to a possibly
+      //   cv-qualified type, the result of the typeid expression refers to a 
+      //   std::type_info object representing the cv-unqualified referenced 
+      //   type.
+      if (T.hasQualifiers()) {
+        ImpCastExprToType(E, T.getUnqualifiedType(), CastExpr::CK_NoOp,
+                          E->isLvalue(Context));
+        TyOrExpr = E;
+      }
+    }
+
+    // If this is an unevaluated operand, clear out the set of
+    // declaration references we have been computing and eliminate any
+    // temporaries introduced in its computation.
+    if (isUnevaluatedOperand)
+      ExprEvalContexts.back().Context = Unevaluated;
+  }
+
+  return Owned(new (Context) CXXTypeidExpr(isType, TyOrExpr,
+                                           TypeInfoType.withConst(),
+                                           SourceRange(OpLoc, RParenLoc)));
+}
+
+/// ActOnCXXBoolLiteral - Parse {true,false} literals.
+Action::OwningExprResult
+Sema::ActOnCXXBoolLiteral(SourceLocation OpLoc, tok::TokenKind Kind) {
+  assert((Kind == tok::kw_true || Kind == tok::kw_false) &&
+         "Unknown C++ Boolean value!");
+  return Owned(new (Context) CXXBoolLiteralExpr(Kind == tok::kw_true,
+                                                Context.BoolTy, OpLoc));
+}
+
+/// ActOnCXXNullPtrLiteral - Parse 'nullptr'.
+Action::OwningExprResult
+Sema::ActOnCXXNullPtrLiteral(SourceLocation Loc) {
+  return Owned(new (Context) CXXNullPtrLiteralExpr(Context.NullPtrTy, Loc));
+}
+
+/// ActOnCXXThrow - Parse throw expressions.
+Action::OwningExprResult
+Sema::ActOnCXXThrow(SourceLocation OpLoc, ExprArg E) {
+  Expr *Ex = E.takeAs<Expr>();
+  if (Ex && !Ex->isTypeDependent() && CheckCXXThrowOperand(OpLoc, Ex))
+    return ExprError();
+  return Owned(new (Context) CXXThrowExpr(Ex, Context.VoidTy, OpLoc));
+}
+
+/// CheckCXXThrowOperand - Validate the operand of a throw.
+bool Sema::CheckCXXThrowOperand(SourceLocation ThrowLoc, Expr *&E) {
+  // C++ [except.throw]p3:
+  //   A throw-expression initializes a temporary object, called the exception
+  //   object, the type of which is determined by removing any top-level
+  //   cv-qualifiers from the static type of the operand of throw and adjusting
+  //   the type from "array of T" or "function returning T" to "pointer to T" 
+  //   or "pointer to function returning T", [...]
+  if (E->getType().hasQualifiers())
+    ImpCastExprToType(E, E->getType().getUnqualifiedType(), CastExpr::CK_NoOp,
+                      E->isLvalue(Context) == Expr::LV_Valid);
+  
+  DefaultFunctionArrayConversion(E);
+
+  //   If the type of the exception would be an incomplete type or a pointer
+  //   to an incomplete type other than (cv) void the program is ill-formed.
+  QualType Ty = E->getType();
+  int isPointer = 0;
+  if (const PointerType* Ptr = Ty->getAs<PointerType>()) {
+    Ty = Ptr->getPointeeType();
+    isPointer = 1;
+  }
+  if (!isPointer || !Ty->isVoidType()) {
+    if (RequireCompleteType(ThrowLoc, Ty,
+                            PDiag(isPointer ? diag::err_throw_incomplete_ptr
+                                            : diag::err_throw_incomplete)
+                              << E->getSourceRange()))
+      return true;
+  }
+
+  // FIXME: Construct a temporary here.
+  return false;
+}
+
+Action::OwningExprResult Sema::ActOnCXXThis(SourceLocation ThisLoc) {
+  /// C++ 9.3.2: In the body of a non-static member function, the keyword this
+  /// is a non-lvalue expression whose value is the address of the object for
+  /// which the function is called.
+
+  if (!isa<FunctionDecl>(CurContext))
+    return ExprError(Diag(ThisLoc, diag::err_invalid_this_use));
+
+  if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(CurContext))
+    if (MD->isInstance())
+      return Owned(new (Context) CXXThisExpr(ThisLoc,
+                                             MD->getThisType(Context),
+                                             /*isImplicit=*/false));
+
+  return ExprError(Diag(ThisLoc, diag::err_invalid_this_use));
+}
+
+/// ActOnCXXTypeConstructExpr - Parse construction of a specified type.
+/// Can be interpreted either as function-style casting ("int(x)")
+/// or class type construction ("ClassType(x,y,z)")
+/// or creation of a value-initialized type ("int()").
+Action::OwningExprResult
+Sema::ActOnCXXTypeConstructExpr(SourceRange TypeRange, TypeTy *TypeRep,
+                                SourceLocation LParenLoc,
+                                MultiExprArg exprs,
+                                SourceLocation *CommaLocs,
+                                SourceLocation RParenLoc) {
+  if (!TypeRep)
+    return ExprError();
+
+  TypeSourceInfo *TInfo;
+  QualType Ty = GetTypeFromParser(TypeRep, &TInfo);
+  if (!TInfo)
+    TInfo = Context.getTrivialTypeSourceInfo(Ty, SourceLocation());
+  unsigned NumExprs = exprs.size();
+  Expr **Exprs = (Expr**)exprs.get();
+  SourceLocation TyBeginLoc = TypeRange.getBegin();
+  SourceRange FullRange = SourceRange(TyBeginLoc, RParenLoc);
+
+  if (Ty->isDependentType() ||
+      CallExpr::hasAnyTypeDependentArguments(Exprs, NumExprs)) {
+    exprs.release();
+
+    return Owned(CXXUnresolvedConstructExpr::Create(Context,
+                                                    TypeRange.getBegin(), Ty,
+                                                    LParenLoc,
+                                                    Exprs, NumExprs,
+                                                    RParenLoc));
+  }
+
+  if (Ty->isArrayType())
+    return ExprError(Diag(TyBeginLoc,
+                          diag::err_value_init_for_array_type) << FullRange);
+  if (!Ty->isVoidType() &&
+      RequireCompleteType(TyBeginLoc, Ty,
+                          PDiag(diag::err_invalid_incomplete_type_use)
+                            << FullRange))
+    return ExprError();
+  
+  if (RequireNonAbstractType(TyBeginLoc, Ty,
+                             diag::err_allocation_of_abstract_type))
+    return ExprError();
+
+
+  // C++ [expr.type.conv]p1:
+  // If the expression list is a single expression, the type conversion
+  // expression is equivalent (in definedness, and if defined in meaning) to the
+  // corresponding cast expression.
+  //
+  if (NumExprs == 1) {
+    CastExpr::CastKind Kind = CastExpr::CK_Unknown;
+    CXXMethodDecl *Method = 0;
+    if (CheckCastTypes(TypeRange, Ty, Exprs[0], Kind, Method,
+                       /*FunctionalStyle=*/true))
+      return ExprError();
+
+    exprs.release();
+    if (Method) {
+      OwningExprResult CastArg 
+        = BuildCXXCastArgument(TypeRange.getBegin(), Ty.getNonReferenceType(), 
+                               Kind, Method, Owned(Exprs[0]));
+      if (CastArg.isInvalid())
+        return ExprError();
+
+      Exprs[0] = CastArg.takeAs<Expr>();
+    }
+
+    return Owned(new (Context) CXXFunctionalCastExpr(Ty.getNonReferenceType(),
+                                                     TInfo, TyBeginLoc, Kind,
+                                                     Exprs[0], RParenLoc));
+  }
+
+  if (const RecordType *RT = Ty->getAs<RecordType>()) {
+    CXXRecordDecl *Record = cast<CXXRecordDecl>(RT->getDecl());
+
+    if (NumExprs > 1 || !Record->hasTrivialConstructor() ||
+        !Record->hasTrivialDestructor()) {
+      InitializedEntity Entity = InitializedEntity::InitializeTemporary(Ty);
+      InitializationKind Kind
+        = NumExprs ? InitializationKind::CreateDirect(TypeRange.getBegin(), 
+                                                      LParenLoc, RParenLoc)
+                   : InitializationKind::CreateValue(TypeRange.getBegin(), 
+                                                     LParenLoc, RParenLoc);
+      InitializationSequence InitSeq(*this, Entity, Kind, Exprs, NumExprs);
+      OwningExprResult Result = InitSeq.Perform(*this, Entity, Kind,
+                                                move(exprs));
+
+      // FIXME: Improve AST representation?
+      return move(Result);
+    }
+
+    // Fall through to value-initialize an object of class type that
+    // doesn't have a user-declared default constructor.
+  }
+
+  // C++ [expr.type.conv]p1:
+  // If the expression list specifies more than a single value, the type shall
+  // be a class with a suitably declared constructor.
+  //
+  if (NumExprs > 1)
+    return ExprError(Diag(CommaLocs[0],
+                          diag::err_builtin_func_cast_more_than_one_arg)
+      << FullRange);
+
+  assert(NumExprs == 0 && "Expected 0 expressions");
+  // C++ [expr.type.conv]p2:
+  // The expression T(), where T is a simple-type-specifier for a non-array
+  // complete object type or the (possibly cv-qualified) void type, creates an
+  // rvalue of the specified type, which is value-initialized.
+  //
+  exprs.release();
+  return Owned(new (Context) CXXZeroInitValueExpr(Ty, TyBeginLoc, RParenLoc));
+}
+
+
+/// ActOnCXXNew - Parsed a C++ 'new' expression (C++ 5.3.4), as in e.g.:
+/// @code new (memory) int[size][4] @endcode
+/// or
+/// @code ::new Foo(23, "hello") @endcode
+/// For the interpretation of this heap of arguments, consult the base version.
+Action::OwningExprResult
+Sema::ActOnCXXNew(SourceLocation StartLoc, bool UseGlobal,
+                  SourceLocation PlacementLParen, MultiExprArg PlacementArgs,
+                  SourceLocation PlacementRParen, bool ParenTypeId,
+                  Declarator &D, SourceLocation ConstructorLParen,
+                  MultiExprArg ConstructorArgs,
+                  SourceLocation ConstructorRParen) {
+  Expr *ArraySize = 0;
+  // If the specified type is an array, unwrap it and save the expression.
+  if (D.getNumTypeObjects() > 0 &&
+      D.getTypeObject(0).Kind == DeclaratorChunk::Array) {
+    DeclaratorChunk &Chunk = D.getTypeObject(0);
+    if (Chunk.Arr.hasStatic)
+      return ExprError(Diag(Chunk.Loc, diag::err_static_illegal_in_new)
+        << D.getSourceRange());
+    if (!Chunk.Arr.NumElts)
+      return ExprError(Diag(Chunk.Loc, diag::err_array_new_needs_size)
+        << D.getSourceRange());
+
+    if (ParenTypeId) {
+      // Can't have dynamic array size when the type-id is in parentheses.
+      Expr *NumElts = (Expr *)Chunk.Arr.NumElts;
+      if (!NumElts->isTypeDependent() && !NumElts->isValueDependent() &&
+          !NumElts->isIntegerConstantExpr(Context)) {
+        Diag(D.getTypeObject(0).Loc, diag::err_new_paren_array_nonconst)
+          << NumElts->getSourceRange();
+        return ExprError();
+      }
+    }
+
+    ArraySize = static_cast<Expr*>(Chunk.Arr.NumElts);
+    D.DropFirstTypeObject();
+  }
+
+  // Every dimension shall be of constant size.
+  if (ArraySize) {
+    for (unsigned I = 0, N = D.getNumTypeObjects(); I < N; ++I) {
+      if (D.getTypeObject(I).Kind != DeclaratorChunk::Array)
+        break;
+
+      DeclaratorChunk::ArrayTypeInfo &Array = D.getTypeObject(I).Arr;
+      if (Expr *NumElts = (Expr *)Array.NumElts) {
+        if (!NumElts->isTypeDependent() && !NumElts->isValueDependent() &&
+            !NumElts->isIntegerConstantExpr(Context)) {
+          Diag(D.getTypeObject(I).Loc, diag::err_new_array_nonconst)
+            << NumElts->getSourceRange();
+          return ExprError();
+        }
+      }
+    }
+  }
+
+  //FIXME: Store TypeSourceInfo in CXXNew expression.
+  TypeSourceInfo *TInfo = 0;
+  QualType AllocType = GetTypeForDeclarator(D, /*Scope=*/0, &TInfo);
+  if (D.isInvalidType())
+    return ExprError();
+    
+  return BuildCXXNew(StartLoc, UseGlobal,
+                     PlacementLParen,
+                     move(PlacementArgs),
+                     PlacementRParen,
+                     ParenTypeId,
+                     AllocType,
+                     D.getSourceRange().getBegin(),
+                     D.getSourceRange(),
+                     Owned(ArraySize),
+                     ConstructorLParen,
+                     move(ConstructorArgs),
+                     ConstructorRParen);
+}
+
+Sema::OwningExprResult
+Sema::BuildCXXNew(SourceLocation StartLoc, bool UseGlobal,
+                  SourceLocation PlacementLParen,
+                  MultiExprArg PlacementArgs,
+                  SourceLocation PlacementRParen,
+                  bool ParenTypeId,
+                  QualType AllocType,
+                  SourceLocation TypeLoc,
+                  SourceRange TypeRange,
+                  ExprArg ArraySizeE,
+                  SourceLocation ConstructorLParen,
+                  MultiExprArg ConstructorArgs,
+                  SourceLocation ConstructorRParen) {
+  if (CheckAllocatedType(AllocType, TypeLoc, TypeRange))
+    return ExprError();
+
+  QualType ResultType = Context.getPointerType(AllocType);
+
+  // That every array dimension except the first is constant was already
+  // checked by the type check above.
+
+  // C++ 5.3.4p6: "The expression in a direct-new-declarator shall have integral
+  //   or enumeration type with a non-negative value."
+  Expr *ArraySize = (Expr *)ArraySizeE.get();
+  if (ArraySize && !ArraySize->isTypeDependent()) {
+    QualType SizeType = ArraySize->getType();
+    if (!SizeType->isIntegralType() && !SizeType->isEnumeralType())
+      return ExprError(Diag(ArraySize->getSourceRange().getBegin(),
+                            diag::err_array_size_not_integral)
+        << SizeType << ArraySize->getSourceRange());
+    // Let's see if this is a constant < 0. If so, we reject it out of hand.
+    // We don't care about special rules, so we tell the machinery it's not
+    // evaluated - it gives us a result in more cases.
+    if (!ArraySize->isValueDependent()) {
+      llvm::APSInt Value;
+      if (ArraySize->isIntegerConstantExpr(Value, Context, 0, false)) {
+        if (Value < llvm::APSInt(
+                        llvm::APInt::getNullValue(Value.getBitWidth()), 
+                                 Value.isUnsigned()))
+          return ExprError(Diag(ArraySize->getSourceRange().getBegin(),
+                           diag::err_typecheck_negative_array_size)
+            << ArraySize->getSourceRange());
+      }
+    }
+    
+    ImpCastExprToType(ArraySize, Context.getSizeType(),
+                      CastExpr::CK_IntegralCast);
+  }
+
+  FunctionDecl *OperatorNew = 0;
+  FunctionDecl *OperatorDelete = 0;
+  Expr **PlaceArgs = (Expr**)PlacementArgs.get();
+  unsigned NumPlaceArgs = PlacementArgs.size();
+  
+  if (!AllocType->isDependentType() &&
+      !Expr::hasAnyTypeDependentArguments(PlaceArgs, NumPlaceArgs) &&
+      FindAllocationFunctions(StartLoc,
+                              SourceRange(PlacementLParen, PlacementRParen),
+                              UseGlobal, AllocType, ArraySize, PlaceArgs,
+                              NumPlaceArgs, OperatorNew, OperatorDelete))
+    return ExprError();
+  llvm::SmallVector<Expr *, 8> AllPlaceArgs;
+  if (OperatorNew) {
+    // Add default arguments, if any.
+    const FunctionProtoType *Proto = 
+      OperatorNew->getType()->getAs<FunctionProtoType>();
+    VariadicCallType CallType = 
+      Proto->isVariadic() ? VariadicFunction : VariadicDoesNotApply;
+    bool Invalid = GatherArgumentsForCall(PlacementLParen, OperatorNew,
+                                          Proto, 1, PlaceArgs, NumPlaceArgs, 
+                                          AllPlaceArgs, CallType);
+    if (Invalid)
+      return ExprError();
+    
+    NumPlaceArgs = AllPlaceArgs.size();
+    if (NumPlaceArgs > 0)
+      PlaceArgs = &AllPlaceArgs[0];
+  }
+  
+  bool Init = ConstructorLParen.isValid();
+  // --- Choosing a constructor ---
+  CXXConstructorDecl *Constructor = 0;
+  Expr **ConsArgs = (Expr**)ConstructorArgs.get();
+  unsigned NumConsArgs = ConstructorArgs.size();
+  ASTOwningVector<&ActionBase::DeleteExpr> ConvertedConstructorArgs(*this);
+
+  if (!AllocType->isDependentType() &&
+      !Expr::hasAnyTypeDependentArguments(ConsArgs, NumConsArgs)) {
+    // C++0x [expr.new]p15:
+    //   A new-expression that creates an object of type T initializes that
+    //   object as follows:
+    InitializationKind Kind
+    //     - If the new-initializer is omitted, the object is default-
+    //       initialized (8.5); if no initialization is performed,
+    //       the object has indeterminate value
+      = !Init? InitializationKind::CreateDefault(TypeLoc)
+    //     - Otherwise, the new-initializer is interpreted according to the 
+    //       initialization rules of 8.5 for direct-initialization.
+             : InitializationKind::CreateDirect(TypeLoc,
+                                                ConstructorLParen, 
+                                                ConstructorRParen);
+    
+    InitializedEntity Entity
+      = InitializedEntity::InitializeNew(StartLoc, AllocType);
+    InitializationSequence InitSeq(*this, Entity, Kind, ConsArgs, NumConsArgs);
+    OwningExprResult FullInit = InitSeq.Perform(*this, Entity, Kind, 
+                                                move(ConstructorArgs));
+    if (FullInit.isInvalid())
+      return ExprError();
+    
+    // FullInit is our initializer; walk through it to determine if it's a 
+    // constructor call, which CXXNewExpr handles directly.
+    if (Expr *FullInitExpr = (Expr *)FullInit.get()) {
+      if (CXXBindTemporaryExpr *Binder
+            = dyn_cast<CXXBindTemporaryExpr>(FullInitExpr))
+        FullInitExpr = Binder->getSubExpr();
+      if (CXXConstructExpr *Construct
+                    = dyn_cast<CXXConstructExpr>(FullInitExpr)) {
+        Constructor = Construct->getConstructor();
+        for (CXXConstructExpr::arg_iterator A = Construct->arg_begin(),
+                                         AEnd = Construct->arg_end();
+             A != AEnd; ++A)
+          ConvertedConstructorArgs.push_back(A->Retain());
+      } else {
+        // Take the converted initializer.
+        ConvertedConstructorArgs.push_back(FullInit.release());
+      }
+    } else {
+      // No initialization required.
+    }
+    
+    // Take the converted arguments and use them for the new expression.
+    NumConsArgs = ConvertedConstructorArgs.size();
+    ConsArgs = (Expr **)ConvertedConstructorArgs.take();
+  }
+  
+  // FIXME: Also check that the destructor is accessible. (C++ 5.3.4p16)
+  
+  PlacementArgs.release();
+  ConstructorArgs.release();
+  ArraySizeE.release();
+  return Owned(new (Context) CXXNewExpr(UseGlobal, OperatorNew, PlaceArgs,
+                        NumPlaceArgs, ParenTypeId, ArraySize, Constructor, Init,
+                        ConsArgs, NumConsArgs, OperatorDelete, ResultType,
+                        StartLoc, Init ? ConstructorRParen : SourceLocation()));
+}
+
+/// CheckAllocatedType - Checks that a type is suitable as the allocated type
+/// in a new-expression.
+/// dimension off and stores the size expression in ArraySize.
+bool Sema::CheckAllocatedType(QualType AllocType, SourceLocation Loc,
+                              SourceRange R) {
+  // C++ 5.3.4p1: "[The] type shall be a complete object type, but not an
+  //   abstract class type or array thereof.
+  if (AllocType->isFunctionType())
+    return Diag(Loc, diag::err_bad_new_type)
+      << AllocType << 0 << R;
+  else if (AllocType->isReferenceType())
+    return Diag(Loc, diag::err_bad_new_type)
+      << AllocType << 1 << R;
+  else if (!AllocType->isDependentType() &&
+           RequireCompleteType(Loc, AllocType,
+                               PDiag(diag::err_new_incomplete_type)
+                                 << R))
+    return true;
+  else if (RequireNonAbstractType(Loc, AllocType,
+                                  diag::err_allocation_of_abstract_type))
+    return true;
+
+  return false;
+}
+
+/// FindAllocationFunctions - Finds the overloads of operator new and delete
+/// that are appropriate for the allocation.
+bool Sema::FindAllocationFunctions(SourceLocation StartLoc, SourceRange Range,
+                                   bool UseGlobal, QualType AllocType,
+                                   bool IsArray, Expr **PlaceArgs,
+                                   unsigned NumPlaceArgs,
+                                   FunctionDecl *&OperatorNew,
+                                   FunctionDecl *&OperatorDelete) {
+  // --- Choosing an allocation function ---
+  // C++ 5.3.4p8 - 14 & 18
+  // 1) If UseGlobal is true, only look in the global scope. Else, also look
+  //   in the scope of the allocated class.
+  // 2) If an array size is given, look for operator new[], else look for
+  //   operator new.
+  // 3) The first argument is always size_t. Append the arguments from the
+  //   placement form.
+  // FIXME: Also find the appropriate delete operator.
+
+  llvm::SmallVector<Expr*, 8> AllocArgs(1 + NumPlaceArgs);
+  // We don't care about the actual value of this argument.
+  // FIXME: Should the Sema create the expression and embed it in the syntax
+  // tree? Or should the consumer just recalculate the value?
+  IntegerLiteral Size(llvm::APInt::getNullValue(
+                      Context.Target.getPointerWidth(0)),
+                      Context.getSizeType(),
+                      SourceLocation());
+  AllocArgs[0] = &Size;
+  std::copy(PlaceArgs, PlaceArgs + NumPlaceArgs, AllocArgs.begin() + 1);
+
+  DeclarationName NewName = Context.DeclarationNames.getCXXOperatorName(
+                                        IsArray ? OO_Array_New : OO_New);
+  if (AllocType->isRecordType() && !UseGlobal) {
+    CXXRecordDecl *Record
+      = cast<CXXRecordDecl>(AllocType->getAs<RecordType>()->getDecl());
+    // FIXME: We fail to find inherited overloads.
+    if (FindAllocationOverload(StartLoc, Range, NewName, &AllocArgs[0],
+                          AllocArgs.size(), Record, /*AllowMissing=*/true,
+                          OperatorNew))
+      return true;
+  }
+  if (!OperatorNew) {
+    // Didn't find a member overload. Look for a global one.
+    DeclareGlobalNewDelete();
+    DeclContext *TUDecl = Context.getTranslationUnitDecl();
+    if (FindAllocationOverload(StartLoc, Range, NewName, &AllocArgs[0],
+                          AllocArgs.size(), TUDecl, /*AllowMissing=*/false,
+                          OperatorNew))
+      return true;
+  }
+
+  // FindAllocationOverload can change the passed in arguments, so we need to
+  // copy them back.
+  if (NumPlaceArgs > 0)
+    std::copy(&AllocArgs[1], AllocArgs.end(), PlaceArgs);
+
+  return false;
+}
+
+/// FindAllocationOverload - Find an fitting overload for the allocation
+/// function in the specified scope.
+bool Sema::FindAllocationOverload(SourceLocation StartLoc, SourceRange Range,
+                                  DeclarationName Name, Expr** Args,
+                                  unsigned NumArgs, DeclContext *Ctx,
+                                  bool AllowMissing, FunctionDecl *&Operator) {
+  LookupResult R(*this, Name, StartLoc, LookupOrdinaryName);
+  LookupQualifiedName(R, Ctx);
+  if (R.empty()) {
+    if (AllowMissing)
+      return false;
+    return Diag(StartLoc, diag::err_ovl_no_viable_function_in_call)
+      << Name << Range;
+  }
+
+  // FIXME: handle ambiguity
+
+  OverloadCandidateSet Candidates(StartLoc);
+  for (LookupResult::iterator Alloc = R.begin(), AllocEnd = R.end(); 
+       Alloc != AllocEnd; ++Alloc) {
+    // Even member operator new/delete are implicitly treated as
+    // static, so don't use AddMemberCandidate.
+
+    if (FunctionTemplateDecl *FnTemplate = 
+          dyn_cast<FunctionTemplateDecl>((*Alloc)->getUnderlyingDecl())) {
+      AddTemplateOverloadCandidate(FnTemplate, Alloc.getAccess(),
+                                   /*ExplicitTemplateArgs=*/0, Args, NumArgs,
+                                   Candidates,
+                                   /*SuppressUserConversions=*/false);
+      continue;
+    }
+
+    FunctionDecl *Fn = cast<FunctionDecl>((*Alloc)->getUnderlyingDecl());
+    AddOverloadCandidate(Fn, Alloc.getAccess(), Args, NumArgs, Candidates,
+                         /*SuppressUserConversions=*/false);
+  }
+
+  // Do the resolution.
+  OverloadCandidateSet::iterator Best;
+  switch(BestViableFunction(Candidates, StartLoc, Best)) {
+  case OR_Success: {
+    // Got one!
+    FunctionDecl *FnDecl = Best->Function;
+    // The first argument is size_t, and the first parameter must be size_t,
+    // too. This is checked on declaration and can be assumed. (It can't be
+    // asserted on, though, since invalid decls are left in there.)
+    // Whatch out for variadic allocator function.
+    unsigned NumArgsInFnDecl = FnDecl->getNumParams();
+    for (unsigned i = 0; (i < NumArgs && i < NumArgsInFnDecl); ++i) {
+      if (PerformCopyInitialization(Args[i],
+                                    FnDecl->getParamDecl(i)->getType(),
+                                    AA_Passing))
+        return true;
+    }
+    Operator = FnDecl;
+    return false;
+  }
+
+  case OR_No_Viable_Function:
+    Diag(StartLoc, diag::err_ovl_no_viable_function_in_call)
+      << Name << Range;
+    PrintOverloadCandidates(Candidates, OCD_AllCandidates, Args, NumArgs);
+    return true;
+
+  case OR_Ambiguous:
+    Diag(StartLoc, diag::err_ovl_ambiguous_call)
+      << Name << Range;
+    PrintOverloadCandidates(Candidates, OCD_ViableCandidates, Args, NumArgs);
+    return true;
+
+  case OR_Deleted:
+    Diag(StartLoc, diag::err_ovl_deleted_call)
+      << Best->Function->isDeleted()
+      << Name << Range;
+    PrintOverloadCandidates(Candidates, OCD_AllCandidates, Args, NumArgs);
+    return true;
+  }
+  assert(false && "Unreachable, bad result from BestViableFunction");
+  return true;
+}
+
+
+/// DeclareGlobalNewDelete - Declare the global forms of operator new and
+/// delete. These are:
+/// @code
+///   void* operator new(std::size_t) throw(std::bad_alloc);
+///   void* operator new[](std::size_t) throw(std::bad_alloc);
+///   void operator delete(void *) throw();
+///   void operator delete[](void *) throw();
+/// @endcode
+/// Note that the placement and nothrow forms of new are *not* implicitly
+/// declared. Their use requires including \<new\>.
+void Sema::DeclareGlobalNewDelete() {
+  if (GlobalNewDeleteDeclared)
+    return;
+  
+  // C++ [basic.std.dynamic]p2:
+  //   [...] The following allocation and deallocation functions (18.4) are 
+  //   implicitly declared in global scope in each translation unit of a 
+  //   program
+  //   
+  //     void* operator new(std::size_t) throw(std::bad_alloc);
+  //     void* operator new[](std::size_t) throw(std::bad_alloc); 
+  //     void  operator delete(void*) throw(); 
+  //     void  operator delete[](void*) throw();
+  //
+  //   These implicit declarations introduce only the function names operator 
+  //   new, operator new[], operator delete, operator delete[].
+  //
+  // Here, we need to refer to std::bad_alloc, so we will implicitly declare
+  // "std" or "bad_alloc" as necessary to form the exception specification.
+  // However, we do not make these implicit declarations visible to name
+  // lookup.
+  if (!StdNamespace) {
+    // The "std" namespace has not yet been defined, so build one implicitly.
+    StdNamespace = NamespaceDecl::Create(Context, 
+                                         Context.getTranslationUnitDecl(),
+                                         SourceLocation(),
+                                         &PP.getIdentifierTable().get("std"));
+    StdNamespace->setImplicit(true);
+  }
+  
+  if (!StdBadAlloc) {
+    // The "std::bad_alloc" class has not yet been declared, so build it
+    // implicitly.
+    StdBadAlloc = CXXRecordDecl::Create(Context, TagDecl::TK_class, 
+                                        StdNamespace, 
+                                        SourceLocation(), 
+                                      &PP.getIdentifierTable().get("bad_alloc"), 
+                                        SourceLocation(), 0);
+    StdBadAlloc->setImplicit(true);
+  }
+  
+  GlobalNewDeleteDeclared = true;
+
+  QualType VoidPtr = Context.getPointerType(Context.VoidTy);
+  QualType SizeT = Context.getSizeType();
+  bool AssumeSaneOperatorNew = getLangOptions().AssumeSaneOperatorNew;
+
+  DeclareGlobalAllocationFunction(
+      Context.DeclarationNames.getCXXOperatorName(OO_New),
+      VoidPtr, SizeT, AssumeSaneOperatorNew);
+  DeclareGlobalAllocationFunction(
+      Context.DeclarationNames.getCXXOperatorName(OO_Array_New),
+      VoidPtr, SizeT, AssumeSaneOperatorNew);
+  DeclareGlobalAllocationFunction(
+      Context.DeclarationNames.getCXXOperatorName(OO_Delete),
+      Context.VoidTy, VoidPtr);
+  DeclareGlobalAllocationFunction(
+      Context.DeclarationNames.getCXXOperatorName(OO_Array_Delete),
+      Context.VoidTy, VoidPtr);
+}
+
+/// DeclareGlobalAllocationFunction - Declares a single implicit global
+/// allocation function if it doesn't already exist.
+void Sema::DeclareGlobalAllocationFunction(DeclarationName Name,
+                                           QualType Return, QualType Argument,
+                                           bool AddMallocAttr) {
+  DeclContext *GlobalCtx = Context.getTranslationUnitDecl();
+
+  // Check if this function is already declared.
+  {
+    DeclContext::lookup_iterator Alloc, AllocEnd;
+    for (llvm::tie(Alloc, AllocEnd) = GlobalCtx->lookup(Name);
+         Alloc != AllocEnd; ++Alloc) {
+      // Only look at non-template functions, as it is the predefined,
+      // non-templated allocation function we are trying to declare here.
+      if (FunctionDecl *Func = dyn_cast<FunctionDecl>(*Alloc)) {
+        QualType InitialParamType =
+          Context.getCanonicalType(
+            Func->getParamDecl(0)->getType().getUnqualifiedType());
+        // FIXME: Do we need to check for default arguments here?
+        if (Func->getNumParams() == 1 && InitialParamType == Argument)
+          return;
+      }
+    }
+  }
+
+  QualType BadAllocType;
+  bool HasBadAllocExceptionSpec 
+    = (Name.getCXXOverloadedOperator() == OO_New ||
+       Name.getCXXOverloadedOperator() == OO_Array_New);
+  if (HasBadAllocExceptionSpec) {
+    assert(StdBadAlloc && "Must have std::bad_alloc declared");
+    BadAllocType = Context.getTypeDeclType(StdBadAlloc);
+  }
+  
+  QualType FnType = Context.getFunctionType(Return, &Argument, 1, false, 0,
+                                            true, false,
+                                            HasBadAllocExceptionSpec? 1 : 0,
+                                            &BadAllocType);
+  FunctionDecl *Alloc =
+    FunctionDecl::Create(Context, GlobalCtx, SourceLocation(), Name,
+                         FnType, /*TInfo=*/0, FunctionDecl::None, false, true);
+  Alloc->setImplicit();
+  
+  if (AddMallocAttr)
+    Alloc->addAttr(::new (Context) MallocAttr());
+  
+  ParmVarDecl *Param = ParmVarDecl::Create(Context, Alloc, SourceLocation(),
+                                           0, Argument, /*TInfo=*/0,
+                                           VarDecl::None, 0);
+  Alloc->setParams(Context, &Param, 1);
+
+  // FIXME: Also add this declaration to the IdentifierResolver, but
+  // make sure it is at the end of the chain to coincide with the
+  // global scope.
+  ((DeclContext *)TUScope->getEntity())->addDecl(Alloc);
+}
+
+bool Sema::FindDeallocationFunction(SourceLocation StartLoc, CXXRecordDecl *RD,
+                                    DeclarationName Name,
+                                    FunctionDecl* &Operator) {
+  LookupResult Found(*this, Name, StartLoc, LookupOrdinaryName);
+  // Try to find operator delete/operator delete[] in class scope.
+  LookupQualifiedName(Found, RD);
+  
+  if (Found.isAmbiguous())
+    return true;
+
+  for (LookupResult::iterator F = Found.begin(), FEnd = Found.end();
+       F != FEnd; ++F) {
+    if (CXXMethodDecl *Delete = dyn_cast<CXXMethodDecl>(*F))
+      if (Delete->isUsualDeallocationFunction()) {
+        Operator = Delete;
+        return false;
+      }
+  }
+
+  // We did find operator delete/operator delete[] declarations, but
+  // none of them were suitable.
+  if (!Found.empty()) {
+    Diag(StartLoc, diag::err_no_suitable_delete_member_function_found)
+      << Name << RD;
+        
+    for (LookupResult::iterator F = Found.begin(), FEnd = Found.end();
+         F != FEnd; ++F) {
+      Diag((*F)->getLocation(), 
+           diag::note_delete_member_function_declared_here)
+        << Name;
+    }
+
+    return true;
+  }
+
+  // Look for a global declaration.
+  DeclareGlobalNewDelete();
+  DeclContext *TUDecl = Context.getTranslationUnitDecl();
+  
+  CXXNullPtrLiteralExpr Null(Context.VoidPtrTy, SourceLocation());
+  Expr* DeallocArgs[1];
+  DeallocArgs[0] = &Null;
+  if (FindAllocationOverload(StartLoc, SourceRange(), Name,
+                             DeallocArgs, 1, TUDecl, /*AllowMissing=*/false,
+                             Operator))
+    return true;
+
+  assert(Operator && "Did not find a deallocation function!");
+  return false;
+}
+
+/// ActOnCXXDelete - Parsed a C++ 'delete' expression (C++ 5.3.5), as in:
+/// @code ::delete ptr; @endcode
+/// or
+/// @code delete [] ptr; @endcode
+Action::OwningExprResult
+Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal,
+                     bool ArrayForm, ExprArg Operand) {
+  // C++ [expr.delete]p1:
+  //   The operand shall have a pointer type, or a class type having a single
+  //   conversion function to a pointer type. The result has type void.
+  //
+  // DR599 amends "pointer type" to "pointer to object type" in both cases.
+
+  FunctionDecl *OperatorDelete = 0;
+
+  Expr *Ex = (Expr *)Operand.get();
+  if (!Ex->isTypeDependent()) {
+    QualType Type = Ex->getType();
+
+    if (const RecordType *Record = Type->getAs<RecordType>()) {
+      llvm::SmallVector<CXXConversionDecl *, 4> ObjectPtrConversions;
+      CXXRecordDecl *RD = cast<CXXRecordDecl>(Record->getDecl());
+      const UnresolvedSetImpl *Conversions = RD->getVisibleConversionFunctions();
+      
+      for (UnresolvedSetImpl::iterator I = Conversions->begin(),
+             E = Conversions->end(); I != E; ++I) {
+        // Skip over templated conversion functions; they aren't considered.
+        if (isa<FunctionTemplateDecl>(*I))
+          continue;
+        
+        CXXConversionDecl *Conv = cast<CXXConversionDecl>(*I);
+        
+        QualType ConvType = Conv->getConversionType().getNonReferenceType();
+        if (const PointerType *ConvPtrType = ConvType->getAs<PointerType>())
+          if (ConvPtrType->getPointeeType()->isObjectType())
+            ObjectPtrConversions.push_back(Conv);
+      }
+      if (ObjectPtrConversions.size() == 1) {
+        // We have a single conversion to a pointer-to-object type. Perform
+        // that conversion.
+        Operand.release();
+        if (!PerformImplicitConversion(Ex, 
+                            ObjectPtrConversions.front()->getConversionType(), 
+                                      AA_Converting)) {
+          Operand = Owned(Ex);
+          Type = Ex->getType();
+        }
+      }
+      else if (ObjectPtrConversions.size() > 1) {
+        Diag(StartLoc, diag::err_ambiguous_delete_operand)
+              << Type << Ex->getSourceRange();
+        for (unsigned i= 0; i < ObjectPtrConversions.size(); i++) {
+          CXXConversionDecl *Conv = ObjectPtrConversions[i];
+          NoteOverloadCandidate(Conv);
+        }
+        return ExprError();
+      }
+    }
+
+    if (!Type->isPointerType())
+      return ExprError(Diag(StartLoc, diag::err_delete_operand)
+        << Type << Ex->getSourceRange());
+
+    QualType Pointee = Type->getAs<PointerType>()->getPointeeType();
+    if (Pointee->isFunctionType() || Pointee->isVoidType())
+      return ExprError(Diag(StartLoc, diag::err_delete_operand)
+        << Type << Ex->getSourceRange());
+    else if (!Pointee->isDependentType() &&
+             RequireCompleteType(StartLoc, Pointee,
+                                 PDiag(diag::warn_delete_incomplete)
+                                   << Ex->getSourceRange()))
+      return ExprError();
+
+    // C++ [expr.delete]p2:
+    //   [Note: a pointer to a const type can be the operand of a 
+    //   delete-expression; it is not necessary to cast away the constness 
+    //   (5.2.11) of the pointer expression before it is used as the operand 
+    //   of the delete-expression. ]
+    ImpCastExprToType(Ex, Context.getPointerType(Context.VoidTy), 
+                      CastExpr::CK_NoOp);
+    
+    // Update the operand.
+    Operand.take();
+    Operand = ExprArg(*this, Ex);
+    
+    DeclarationName DeleteName = Context.DeclarationNames.getCXXOperatorName(
+                                      ArrayForm ? OO_Array_Delete : OO_Delete);
+
+    if (const RecordType *RT = Pointee->getAs<RecordType>()) {
+      CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
+
+      if (!UseGlobal && 
+          FindDeallocationFunction(StartLoc, RD, DeleteName, OperatorDelete))
+        return ExprError();
+      
+      if (!RD->hasTrivialDestructor())
+        if (const CXXDestructorDecl *Dtor = RD->getDestructor(Context))
+          MarkDeclarationReferenced(StartLoc,
+                                    const_cast<CXXDestructorDecl*>(Dtor));
+    }
+    
+    if (!OperatorDelete) {
+      // Look for a global declaration.
+      DeclareGlobalNewDelete();
+      DeclContext *TUDecl = Context.getTranslationUnitDecl();
+      if (FindAllocationOverload(StartLoc, SourceRange(), DeleteName,
+                                 &Ex, 1, TUDecl, /*AllowMissing=*/false,
+                                 OperatorDelete))
+        return ExprError();
+    }
+
+    // FIXME: Check access and ambiguity of operator delete and destructor.
+  }
+
+  Operand.release();
+  return Owned(new (Context) CXXDeleteExpr(Context.VoidTy, UseGlobal, ArrayForm,
+                                           OperatorDelete, Ex, StartLoc));
+}
+
+/// \brief Check the use of the given variable as a C++ condition in an if,
+/// while, do-while, or switch statement.
+Action::OwningExprResult Sema::CheckConditionVariable(VarDecl *ConditionVar) {
+  QualType T = ConditionVar->getType();
+  
+  // C++ [stmt.select]p2:
+  //   The declarator shall not specify a function or an array.
+  if (T->isFunctionType())
+    return ExprError(Diag(ConditionVar->getLocation(), 
+                          diag::err_invalid_use_of_function_type)
+                       << ConditionVar->getSourceRange());
+  else if (T->isArrayType())
+    return ExprError(Diag(ConditionVar->getLocation(), 
+                          diag::err_invalid_use_of_array_type)
+                     << ConditionVar->getSourceRange());
+
+  return Owned(DeclRefExpr::Create(Context, 0, SourceRange(), ConditionVar,
+                                   ConditionVar->getLocation(), 
+                                ConditionVar->getType().getNonReferenceType()));
+}
+
+/// CheckCXXBooleanCondition - Returns true if a conversion to bool is invalid.
+bool Sema::CheckCXXBooleanCondition(Expr *&CondExpr) {
+  // C++ 6.4p4:
+  // The value of a condition that is an initialized declaration in a statement
+  // other than a switch statement is the value of the declared variable
+  // implicitly converted to type bool. If that conversion is ill-formed, the
+  // program is ill-formed.
+  // The value of a condition that is an expression is the value of the
+  // expression, implicitly converted to bool.
+  //
+  return PerformContextuallyConvertToBool(CondExpr);
+}
+
+/// Helper function to determine whether this is the (deprecated) C++
+/// conversion from a string literal to a pointer to non-const char or
+/// non-const wchar_t (for narrow and wide string literals,
+/// respectively).
+bool
+Sema::IsStringLiteralToNonConstPointerConversion(Expr *From, QualType ToType) {
+  // Look inside the implicit cast, if it exists.
+  if (ImplicitCastExpr *Cast = dyn_cast<ImplicitCastExpr>(From))
+    From = Cast->getSubExpr();
+
+  // A string literal (2.13.4) that is not a wide string literal can
+  // be converted to an rvalue of type "pointer to char"; a wide
+  // string literal can be converted to an rvalue of type "pointer
+  // to wchar_t" (C++ 4.2p2).
+  if (StringLiteral *StrLit = dyn_cast<StringLiteral>(From))
+    if (const PointerType *ToPtrType = ToType->getAs<PointerType>())
+      if (const BuiltinType *ToPointeeType
+          = ToPtrType->getPointeeType()->getAs<BuiltinType>()) {
+        // This conversion is considered only when there is an
+        // explicit appropriate pointer target type (C++ 4.2p2).
+        if (!ToPtrType->getPointeeType().hasQualifiers() &&
+            ((StrLit->isWide() && ToPointeeType->isWideCharType()) ||
+             (!StrLit->isWide() &&
+              (ToPointeeType->getKind() == BuiltinType::Char_U ||
+               ToPointeeType->getKind() == BuiltinType::Char_S))))
+          return true;
+      }
+
+  return false;
+}
+
+/// PerformImplicitConversion - Perform an implicit conversion of the
+/// expression From to the type ToType. Returns true if there was an
+/// error, false otherwise. The expression From is replaced with the
+/// converted expression. Flavor is the kind of conversion we're
+/// performing, used in the error message. If @p AllowExplicit,
+/// explicit user-defined conversions are permitted. @p Elidable should be true
+/// when called for copies which may be elided (C++ 12.8p15). C++0x overload
+/// resolution works differently in that case.
+bool
+Sema::PerformImplicitConversion(Expr *&From, QualType ToType,
+                                AssignmentAction Action, bool AllowExplicit,
+                                bool Elidable) {
+  ImplicitConversionSequence ICS;
+  return PerformImplicitConversion(From, ToType, Action, AllowExplicit, 
+                                   Elidable, ICS);
+}
+
+bool
+Sema::PerformImplicitConversion(Expr *&From, QualType ToType,
+                                AssignmentAction Action, bool AllowExplicit,
+                                bool Elidable,
+                                ImplicitConversionSequence& ICS) {
+  ICS.setBad();
+  ICS.Bad.init(BadConversionSequence::no_conversion, From, ToType);
+  if (Elidable && getLangOptions().CPlusPlus0x) {
+    ICS = TryImplicitConversion(From, ToType,
+                                /*SuppressUserConversions=*/false,
+                                AllowExplicit,
+                                /*ForceRValue=*/true,
+                                /*InOverloadResolution=*/false);
+  }
+  if (ICS.isBad()) {
+    ICS = TryImplicitConversion(From, ToType,
+                                /*SuppressUserConversions=*/false,
+                                AllowExplicit,
+                                /*ForceRValue=*/false,
+                                /*InOverloadResolution=*/false);
+  }
+  return PerformImplicitConversion(From, ToType, ICS, Action);
+}
+
+/// PerformImplicitConversion - Perform an implicit conversion of the
+/// expression From to the type ToType using the pre-computed implicit
+/// conversion sequence ICS. Returns true if there was an error, false
+/// otherwise. The expression From is replaced with the converted
+/// expression. Action is the kind of conversion we're performing,
+/// used in the error message.
+bool
+Sema::PerformImplicitConversion(Expr *&From, QualType ToType,
+                                const ImplicitConversionSequence &ICS,
+                                AssignmentAction Action, bool IgnoreBaseAccess) {
+  switch (ICS.getKind()) {
+  case ImplicitConversionSequence::StandardConversion:
+    if (PerformImplicitConversion(From, ToType, ICS.Standard, Action,
+                                  IgnoreBaseAccess))
+      return true;
+    break;
+
+  case ImplicitConversionSequence::UserDefinedConversion: {
+    
+      FunctionDecl *FD = ICS.UserDefined.ConversionFunction;
+      CastExpr::CastKind CastKind = CastExpr::CK_Unknown;
+      QualType BeforeToType;
+      if (const CXXConversionDecl *Conv = dyn_cast<CXXConversionDecl>(FD)) {
+        CastKind = CastExpr::CK_UserDefinedConversion;
+        
+        // If the user-defined conversion is specified by a conversion function,
+        // the initial standard conversion sequence converts the source type to
+        // the implicit object parameter of the conversion function.
+        BeforeToType = Context.getTagDeclType(Conv->getParent());
+      } else if (const CXXConstructorDecl *Ctor = 
+                  dyn_cast<CXXConstructorDecl>(FD)) {
+        CastKind = CastExpr::CK_ConstructorConversion;
+        // Do no conversion if dealing with ... for the first conversion.
+        if (!ICS.UserDefined.EllipsisConversion) {
+          // If the user-defined conversion is specified by a constructor, the 
+          // initial standard conversion sequence converts the source type to the
+          // type required by the argument of the constructor
+          BeforeToType = Ctor->getParamDecl(0)->getType().getNonReferenceType();
+        }
+      }    
+      else
+        assert(0 && "Unknown conversion function kind!");
+      // Whatch out for elipsis conversion.
+      if (!ICS.UserDefined.EllipsisConversion) {
+        if (PerformImplicitConversion(From, BeforeToType, 
+                                      ICS.UserDefined.Before, AA_Converting,
+                                      IgnoreBaseAccess))
+          return true;
+      }
+    
+      OwningExprResult CastArg 
+        = BuildCXXCastArgument(From->getLocStart(),
+                               ToType.getNonReferenceType(),
+                               CastKind, cast<CXXMethodDecl>(FD), 
+                               Owned(From));
+
+      if (CastArg.isInvalid())
+        return true;
+
+      From = CastArg.takeAs<Expr>();
+
+      return PerformImplicitConversion(From, ToType, ICS.UserDefined.After,
+                                       AA_Converting, IgnoreBaseAccess);
+  }
+
+  case ImplicitConversionSequence::AmbiguousConversion:
+    DiagnoseAmbiguousConversion(ICS, From->getExprLoc(),
+                          PDiag(diag::err_typecheck_ambiguous_condition)
+                            << From->getSourceRange());
+     return true;
+      
+  case ImplicitConversionSequence::EllipsisConversion:
+    assert(false && "Cannot perform an ellipsis conversion");
+    return false;
+
+  case ImplicitConversionSequence::BadConversion:
+    return true;
+  }
+
+  // Everything went well.
+  return false;
+}
+
+/// PerformImplicitConversion - Perform an implicit conversion of the
+/// expression From to the type ToType by following the standard
+/// conversion sequence SCS. Returns true if there was an error, false
+/// otherwise. The expression From is replaced with the converted
+/// expression. Flavor is the context in which we're performing this
+/// conversion, for use in error messages.
+bool
+Sema::PerformImplicitConversion(Expr *&From, QualType ToType,
+                                const StandardConversionSequence& SCS,
+                                AssignmentAction Action, bool IgnoreBaseAccess) {
+  // Overall FIXME: we are recomputing too many types here and doing far too
+  // much extra work. What this means is that we need to keep track of more
+  // information that is computed when we try the implicit conversion initially,
+  // so that we don't need to recompute anything here.
+  QualType FromType = From->getType();
+
+  if (SCS.CopyConstructor) {
+    // FIXME: When can ToType be a reference type?
+    assert(!ToType->isReferenceType());
+    if (SCS.Second == ICK_Derived_To_Base) {
+      ASTOwningVector<&ActionBase::DeleteExpr> ConstructorArgs(*this);
+      if (CompleteConstructorCall(cast<CXXConstructorDecl>(SCS.CopyConstructor),
+                                  MultiExprArg(*this, (void **)&From, 1),
+                                  /*FIXME:ConstructLoc*/SourceLocation(), 
+                                  ConstructorArgs))
+        return true;
+      OwningExprResult FromResult =
+        BuildCXXConstructExpr(/*FIXME:ConstructLoc*/SourceLocation(),
+                              ToType, SCS.CopyConstructor,
+                              move_arg(ConstructorArgs));
+      if (FromResult.isInvalid())
+        return true;
+      From = FromResult.takeAs<Expr>();
+      return false;
+    }
+    OwningExprResult FromResult =
+      BuildCXXConstructExpr(/*FIXME:ConstructLoc*/SourceLocation(),
+                            ToType, SCS.CopyConstructor,
+                            MultiExprArg(*this, (void**)&From, 1));
+
+    if (FromResult.isInvalid())
+      return true;
+
+    From = FromResult.takeAs<Expr>();
+    return false;
+  }
+
+  // Perform the first implicit conversion.
+  switch (SCS.First) {
+  case ICK_Identity:
+  case ICK_Lvalue_To_Rvalue:
+    // Nothing to do.
+    break;
+
+  case ICK_Array_To_Pointer:
+    FromType = Context.getArrayDecayedType(FromType);
+    ImpCastExprToType(From, FromType, CastExpr::CK_ArrayToPointerDecay);
+    break;
+
+  case ICK_Function_To_Pointer:
+    if (Context.getCanonicalType(FromType) == Context.OverloadTy) {
+      FunctionDecl *Fn = ResolveAddressOfOverloadedFunction(From, ToType, true);
+      if (!Fn)
+        return true;
+
+      if (DiagnoseUseOfDecl(Fn, From->getSourceRange().getBegin()))
+        return true;
+
+      From = FixOverloadedFunctionReference(From, Fn);
+      FromType = From->getType();
+        
+      // If there's already an address-of operator in the expression, we have
+      // the right type already, and the code below would just introduce an
+      // invalid additional pointer level.
+      if (FromType->isPointerType() || FromType->isMemberFunctionPointerType())
+        break;
+    }
+    FromType = Context.getPointerType(FromType);
+    ImpCastExprToType(From, FromType, CastExpr::CK_FunctionToPointerDecay);
+    break;
+
+  default:
+    assert(false && "Improper first standard conversion");
+    break;
+  }
+
+  // Perform the second implicit conversion
+  switch (SCS.Second) {
+  case ICK_Identity:
+    // If both sides are functions (or pointers/references to them), there could
+    // be incompatible exception declarations.
+    if (CheckExceptionSpecCompatibility(From, ToType))
+      return true;
+    // Nothing else to do.
+    break;
+
+  case ICK_NoReturn_Adjustment:
+    // If both sides are functions (or pointers/references to them), there could
+    // be incompatible exception declarations.
+    if (CheckExceptionSpecCompatibility(From, ToType))
+      return true;      
+      
+    ImpCastExprToType(From, Context.getNoReturnType(From->getType(), false),
+                      CastExpr::CK_NoOp);
+    break;
+      
+  case ICK_Integral_Promotion:
+  case ICK_Integral_Conversion:
+    ImpCastExprToType(From, ToType, CastExpr::CK_IntegralCast);
+    break;
+
+  case ICK_Floating_Promotion:
+  case ICK_Floating_Conversion:
+    ImpCastExprToType(From, ToType, CastExpr::CK_FloatingCast);
+    break;
+
+  case ICK_Complex_Promotion:
+  case ICK_Complex_Conversion:
+    ImpCastExprToType(From, ToType, CastExpr::CK_Unknown);
+    break;
+
+  case ICK_Floating_Integral:
+    if (ToType->isFloatingType())
+      ImpCastExprToType(From, ToType, CastExpr::CK_IntegralToFloating);
+    else
+      ImpCastExprToType(From, ToType, CastExpr::CK_FloatingToIntegral);
+    break;
+
+  case ICK_Complex_Real:
+    ImpCastExprToType(From, ToType, CastExpr::CK_Unknown);
+    break;
+
+  case ICK_Compatible_Conversion:
+    ImpCastExprToType(From, ToType, CastExpr::CK_NoOp);
+    break;
+
+  case ICK_Pointer_Conversion: {
+    if (SCS.IncompatibleObjC) {
+      // Diagnose incompatible Objective-C conversions
+      Diag(From->getSourceRange().getBegin(),
+           diag::ext_typecheck_convert_incompatible_pointer)
+        << From->getType() << ToType << Action
+        << From->getSourceRange();
+    }
+
+    
+    CastExpr::CastKind Kind = CastExpr::CK_Unknown;
+    if (CheckPointerConversion(From, ToType, Kind, IgnoreBaseAccess))
+      return true;
+    ImpCastExprToType(From, ToType, Kind);
+    break;
+  }
+  
+  case ICK_Pointer_Member: {
+    CastExpr::CastKind Kind = CastExpr::CK_Unknown;
+    if (CheckMemberPointerConversion(From, ToType, Kind, IgnoreBaseAccess))
+      return true;
+    if (CheckExceptionSpecCompatibility(From, ToType))
+      return true;
+    ImpCastExprToType(From, ToType, Kind);
+    break;
+  }
+  case ICK_Boolean_Conversion: {
+    CastExpr::CastKind Kind = CastExpr::CK_Unknown;
+    if (FromType->isMemberPointerType())
+      Kind = CastExpr::CK_MemberPointerToBoolean;
+    
+    ImpCastExprToType(From, Context.BoolTy, Kind);
+    break;
+  }
+
+  case ICK_Derived_To_Base:
+    if (CheckDerivedToBaseConversion(From->getType(), 
+                                     ToType.getNonReferenceType(),
+                                     From->getLocStart(),
+                                     From->getSourceRange(),
+                                     IgnoreBaseAccess))
+      return true;
+    ImpCastExprToType(From, ToType.getNonReferenceType(), 
+                      CastExpr::CK_DerivedToBase);
+    break;
+      
+  default:
+    assert(false && "Improper second standard conversion");
+    break;
+  }
+
+  switch (SCS.Third) {
+  case ICK_Identity:
+    // Nothing to do.
+    break;
+
+  case ICK_Qualification:
+    // FIXME: Not sure about lvalue vs rvalue here in the presence of rvalue
+    // references.
+    ImpCastExprToType(From, ToType.getNonReferenceType(),
+                      CastExpr::CK_NoOp,
+                      ToType->isLValueReferenceType());
+    break;
+      
+  default:
+    assert(false && "Improper second standard conversion");
+    break;
+  }
+
+  return false;
+}
+
+Sema::OwningExprResult Sema::ActOnUnaryTypeTrait(UnaryTypeTrait OTT,
+                                                 SourceLocation KWLoc,
+                                                 SourceLocation LParen,
+                                                 TypeTy *Ty,
+                                                 SourceLocation RParen) {
+  QualType T = GetTypeFromParser(Ty);
+
+  // According to http://gcc.gnu.org/onlinedocs/gcc/Type-Traits.html
+  // all traits except __is_class, __is_enum and __is_union require a the type
+  // to be complete.
+  if (OTT != UTT_IsClass && OTT != UTT_IsEnum && OTT != UTT_IsUnion) {
+    if (RequireCompleteType(KWLoc, T,
+                            diag::err_incomplete_type_used_in_type_trait_expr))
+      return ExprError();
+  }
+
+  // There is no point in eagerly computing the value. The traits are designed
+  // to be used from type trait templates, so Ty will be a template parameter
+  // 99% of the time.
+  return Owned(new (Context) UnaryTypeTraitExpr(KWLoc, OTT, T,
+                                                RParen, Context.BoolTy));
+}
+
+QualType Sema::CheckPointerToMemberOperands(
+  Expr *&lex, Expr *&rex, SourceLocation Loc, bool isIndirect) {
+  const char *OpSpelling = isIndirect ? "->*" : ".*";
+  // C++ 5.5p2
+  //   The binary operator .* [p3: ->*] binds its second operand, which shall
+  //   be of type "pointer to member of T" (where T is a completely-defined
+  //   class type) [...]
+  QualType RType = rex->getType();
+  const MemberPointerType *MemPtr = RType->getAs<MemberPointerType>();
+  if (!MemPtr) {
+    Diag(Loc, diag::err_bad_memptr_rhs)
+      << OpSpelling << RType << rex->getSourceRange();
+    return QualType();
+  }
+
+  QualType Class(MemPtr->getClass(), 0);
+
+  // C++ 5.5p2
+  //   [...] to its first operand, which shall be of class T or of a class of
+  //   which T is an unambiguous and accessible base class. [p3: a pointer to
+  //   such a class]
+  QualType LType = lex->getType();
+  if (isIndirect) {
+    if (const PointerType *Ptr = LType->getAs<PointerType>())
+      LType = Ptr->getPointeeType().getNonReferenceType();
+    else {
+      Diag(Loc, diag::err_bad_memptr_lhs)
+        << OpSpelling << 1 << LType
+        << CodeModificationHint::CreateReplacement(SourceRange(Loc), ".*");
+      return QualType();
+    }
+  }
+
+  if (!Context.hasSameUnqualifiedType(Class, LType)) {
+    CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/false,
+                       /*DetectVirtual=*/false);
+    // FIXME: Would it be useful to print full ambiguity paths, or is that
+    // overkill?
+    if (!IsDerivedFrom(LType, Class, Paths) ||
+        Paths.isAmbiguous(Context.getCanonicalType(Class))) {
+      Diag(Loc, diag::err_bad_memptr_lhs) << OpSpelling
+        << (int)isIndirect << lex->getType();
+      return QualType();
+    }
+    // Cast LHS to type of use.
+    QualType UseType = isIndirect ? Context.getPointerType(Class) : Class;
+    bool isLValue = !isIndirect && lex->isLvalue(Context) == Expr::LV_Valid;
+    ImpCastExprToType(lex, UseType, CastExpr::CK_DerivedToBase, isLValue);
+  }
+
+  if (isa<CXXZeroInitValueExpr>(rex->IgnoreParens())) {
+    // Diagnose use of pointer-to-member type which when used as
+    // the functional cast in a pointer-to-member expression.
+    Diag(Loc, diag::err_pointer_to_member_type) << isIndirect;
+     return QualType();
+  }
+  // C++ 5.5p2
+  //   The result is an object or a function of the type specified by the
+  //   second operand.
+  // The cv qualifiers are the union of those in the pointer and the left side,
+  // in accordance with 5.5p5 and 5.2.5.
+  // FIXME: This returns a dereferenced member function pointer as a normal
+  // function type. However, the only operation valid on such functions is
+  // calling them. There's also a GCC extension to get a function pointer to the
+  // thing, which is another complication, because this type - unlike the type
+  // that is the result of this expression - takes the class as the first
+  // argument.
+  // We probably need a "MemberFunctionClosureType" or something like that.
+  QualType Result = MemPtr->getPointeeType();
+  Result = Context.getCVRQualifiedType(Result, LType.getCVRQualifiers());
+  return Result;
+}
+
+/// \brief Get the target type of a standard or user-defined conversion.
+static QualType TargetType(const ImplicitConversionSequence &ICS) {
+  switch (ICS.getKind()) {
+  case ImplicitConversionSequence::StandardConversion:
+    return ICS.Standard.getToType(2);
+  case ImplicitConversionSequence::UserDefinedConversion:
+    return ICS.UserDefined.After.getToType(2);
+  case ImplicitConversionSequence::AmbiguousConversion:
+    return ICS.Ambiguous.getToType();
+  case ImplicitConversionSequence::EllipsisConversion:
+  case ImplicitConversionSequence::BadConversion:
+    llvm_unreachable("function not valid for ellipsis or bad conversions");
+  }
+  return QualType(); // silence warnings
+}
+
+/// \brief Try to convert a type to another according to C++0x 5.16p3.
+///
+/// This is part of the parameter validation for the ? operator. If either
+/// value operand is a class type, the two operands are attempted to be
+/// converted to each other. This function does the conversion in one direction.
+/// It emits a diagnostic and returns true only if it finds an ambiguous
+/// conversion.
+static bool TryClassUnification(Sema &Self, Expr *From, Expr *To,
+                                SourceLocation QuestionLoc,
+                                ImplicitConversionSequence &ICS) {
+  // C++0x 5.16p3
+  //   The process for determining whether an operand expression E1 of type T1
+  //   can be converted to match an operand expression E2 of type T2 is defined
+  //   as follows:
+  //   -- If E2 is an lvalue:
+  if (To->isLvalue(Self.Context) == Expr::LV_Valid) {
+    //   E1 can be converted to match E2 if E1 can be implicitly converted to
+    //   type "lvalue reference to T2", subject to the constraint that in the
+    //   conversion the reference must bind directly to E1.
+    if (!Self.CheckReferenceInit(From,
+                            Self.Context.getLValueReferenceType(To->getType()),
+                                 To->getLocStart(),
+                                 /*SuppressUserConversions=*/false,
+                                 /*AllowExplicit=*/false,
+                                 /*ForceRValue=*/false,
+                                 &ICS))
+    {
+      assert((ICS.isStandard() || ICS.isUserDefined()) &&
+             "expected a definite conversion");
+      bool DirectBinding =
+        ICS.isStandard() ? ICS.Standard.DirectBinding
+                         : ICS.UserDefined.After.DirectBinding;
+      if (DirectBinding)
+        return false;
+    }
+  }
+  ICS.setBad();
+  //   -- If E2 is an rvalue, or if the conversion above cannot be done:
+  //      -- if E1 and E2 have class type, and the underlying class types are
+  //         the same or one is a base class of the other:
+  QualType FTy = From->getType();
+  QualType TTy = To->getType();
+  const RecordType *FRec = FTy->getAs<RecordType>();
+  const RecordType *TRec = TTy->getAs<RecordType>();
+  bool FDerivedFromT = FRec && TRec && Self.IsDerivedFrom(FTy, TTy);
+  if (FRec && TRec && (FRec == TRec ||
+        FDerivedFromT || Self.IsDerivedFrom(TTy, FTy))) {
+    //         E1 can be converted to match E2 if the class of T2 is the
+    //         same type as, or a base class of, the class of T1, and
+    //         [cv2 > cv1].
+    if ((FRec == TRec || FDerivedFromT) && TTy.isAtLeastAsQualifiedAs(FTy)) {
+      // Could still fail if there's no copy constructor.
+      // FIXME: Is this a hard error then, or just a conversion failure? The
+      // standard doesn't say.
+      ICS = Self.TryCopyInitialization(From, TTy,
+                                       /*SuppressUserConversions=*/false,
+                                       /*ForceRValue=*/false,
+                                       /*InOverloadResolution=*/false);
+    }
+  } else {
+    //     -- Otherwise: E1 can be converted to match E2 if E1 can be
+    //        implicitly converted to the type that expression E2 would have
+    //        if E2 were converted to an rvalue.
+    // First find the decayed type.
+    if (TTy->isFunctionType())
+      TTy = Self.Context.getPointerType(TTy);
+    else if (TTy->isArrayType())
+      TTy = Self.Context.getArrayDecayedType(TTy);
+
+    // Now try the implicit conversion.
+    // FIXME: This doesn't detect ambiguities.
+    ICS = Self.TryImplicitConversion(From, TTy,
+                                     /*SuppressUserConversions=*/false,
+                                     /*AllowExplicit=*/false,
+                                     /*ForceRValue=*/false,
+                                     /*InOverloadResolution=*/false);
+  }
+  return false;
+}
+
+/// \brief Try to find a common type for two according to C++0x 5.16p5.
+///
+/// This is part of the parameter validation for the ? operator. If either
+/// value operand is a class type, overload resolution is used to find a
+/// conversion to a common type.
+static bool FindConditionalOverload(Sema &Self, Expr *&LHS, Expr *&RHS,
+                                    SourceLocation Loc) {
+  Expr *Args[2] = { LHS, RHS };
+  OverloadCandidateSet CandidateSet(Loc);
+  Self.AddBuiltinOperatorCandidates(OO_Conditional, Loc, Args, 2, CandidateSet);
+
+  OverloadCandidateSet::iterator Best;
+  switch (Self.BestViableFunction(CandidateSet, Loc, Best)) {
+    case OR_Success:
+      // We found a match. Perform the conversions on the arguments and move on.
+      if (Self.PerformImplicitConversion(LHS, Best->BuiltinTypes.ParamTypes[0],
+                                         Best->Conversions[0], Sema::AA_Converting) ||
+          Self.PerformImplicitConversion(RHS, Best->BuiltinTypes.ParamTypes[1],
+                                         Best->Conversions[1], Sema::AA_Converting))
+        break;
+      return false;
+
+    case OR_No_Viable_Function:
+      Self.Diag(Loc, diag::err_typecheck_cond_incompatible_operands)
+        << LHS->getType() << RHS->getType()
+        << LHS->getSourceRange() << RHS->getSourceRange();
+      return true;
+
+    case OR_Ambiguous:
+      Self.Diag(Loc, diag::err_conditional_ambiguous_ovl)
+        << LHS->getType() << RHS->getType()
+        << LHS->getSourceRange() << RHS->getSourceRange();
+      // FIXME: Print the possible common types by printing the return types of
+      // the viable candidates.
+      break;
+
+    case OR_Deleted:
+      assert(false && "Conditional operator has only built-in overloads");
+      break;
+  }
+  return true;
+}
+
+/// \brief Perform an "extended" implicit conversion as returned by
+/// TryClassUnification.
+///
+/// TryClassUnification generates ICSs that include reference bindings.
+/// PerformImplicitConversion is not suitable for this; it chokes if the
+/// second part of a standard conversion is ICK_DerivedToBase. This function
+/// handles the reference binding specially.
+static bool ConvertForConditional(Sema &Self, Expr *&E,
+                                  const ImplicitConversionSequence &ICS) {
+  if (ICS.isStandard() && ICS.Standard.ReferenceBinding) {
+    assert(ICS.Standard.DirectBinding &&
+           "TryClassUnification should never generate indirect ref bindings");
+    // FIXME: CheckReferenceInit should be able to reuse the ICS instead of
+    // redoing all the work.
+    return Self.CheckReferenceInit(E, Self.Context.getLValueReferenceType(
+                                        TargetType(ICS)),
+                                   /*FIXME:*/E->getLocStart(),
+                                   /*SuppressUserConversions=*/false,
+                                   /*AllowExplicit=*/false,
+                                   /*ForceRValue=*/false);
+  }
+  if (ICS.isUserDefined() && ICS.UserDefined.After.ReferenceBinding) {
+    assert(ICS.UserDefined.After.DirectBinding &&
+           "TryClassUnification should never generate indirect ref bindings");
+    return Self.CheckReferenceInit(E, Self.Context.getLValueReferenceType(
+                                        TargetType(ICS)),
+                                   /*FIXME:*/E->getLocStart(),
+                                   /*SuppressUserConversions=*/false,
+                                   /*AllowExplicit=*/false,
+                                   /*ForceRValue=*/false);
+  }
+  if (Self.PerformImplicitConversion(E, TargetType(ICS), ICS, Sema::AA_Converting))
+    return true;
+  return false;
+}
+
+/// \brief Check the operands of ?: under C++ semantics.
+///
+/// See C++ [expr.cond]. Note that LHS is never null, even for the GNU x ?: y
+/// extension. In this case, LHS == Cond. (But they're not aliases.)
+QualType Sema::CXXCheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS,
+                                           SourceLocation QuestionLoc) {
+  // FIXME: Handle C99's complex types, vector types, block pointers and Obj-C++
+  // interface pointers.
+
+  // C++0x 5.16p1
+  //   The first expression is contextually converted to bool.
+  if (!Cond->isTypeDependent()) {
+    if (CheckCXXBooleanCondition(Cond))
+      return QualType();
+  }
+
+  // Either of the arguments dependent?
+  if (LHS->isTypeDependent() || RHS->isTypeDependent())
+    return Context.DependentTy;
+
+  CheckSignCompare(LHS, RHS, QuestionLoc, diag::warn_mixed_sign_conditional);
+
+  // C++0x 5.16p2
+  //   If either the second or the third operand has type (cv) void, ...
+  QualType LTy = LHS->getType();
+  QualType RTy = RHS->getType();
+  bool LVoid = LTy->isVoidType();
+  bool RVoid = RTy->isVoidType();
+  if (LVoid || RVoid) {
+    //   ... then the [l2r] conversions are performed on the second and third
+    //   operands ...
+    DefaultFunctionArrayLvalueConversion(LHS);
+    DefaultFunctionArrayLvalueConversion(RHS);
+    LTy = LHS->getType();
+    RTy = RHS->getType();
+
+    //   ... and one of the following shall hold:
+    //   -- The second or the third operand (but not both) is a throw-
+    //      expression; the result is of the type of the other and is an rvalue.
+    bool LThrow = isa<CXXThrowExpr>(LHS);
+    bool RThrow = isa<CXXThrowExpr>(RHS);
+    if (LThrow && !RThrow)
+      return RTy;
+    if (RThrow && !LThrow)
+      return LTy;
+
+    //   -- Both the second and third operands have type void; the result is of
+    //      type void and is an rvalue.
+    if (LVoid && RVoid)
+      return Context.VoidTy;
+
+    // Neither holds, error.
+    Diag(QuestionLoc, diag::err_conditional_void_nonvoid)
+      << (LVoid ? RTy : LTy) << (LVoid ? 0 : 1)
+      << LHS->getSourceRange() << RHS->getSourceRange();
+    return QualType();
+  }
+
+  // Neither is void.
+
+  // C++0x 5.16p3
+  //   Otherwise, if the second and third operand have different types, and
+  //   either has (cv) class type, and attempt is made to convert each of those
+  //   operands to the other.
+  if (Context.getCanonicalType(LTy) != Context.getCanonicalType(RTy) &&
+      (LTy->isRecordType() || RTy->isRecordType())) {
+    ImplicitConversionSequence ICSLeftToRight, ICSRightToLeft;
+    // These return true if a single direction is already ambiguous.
+    if (TryClassUnification(*this, LHS, RHS, QuestionLoc, ICSLeftToRight))
+      return QualType();
+    if (TryClassUnification(*this, RHS, LHS, QuestionLoc, ICSRightToLeft))
+      return QualType();
+
+    bool HaveL2R = !ICSLeftToRight.isBad();
+    bool HaveR2L = !ICSRightToLeft.isBad();
+    //   If both can be converted, [...] the program is ill-formed.
+    if (HaveL2R && HaveR2L) {
+      Diag(QuestionLoc, diag::err_conditional_ambiguous)
+        << LTy << RTy << LHS->getSourceRange() << RHS->getSourceRange();
+      return QualType();
+    }
+
+    //   If exactly one conversion is possible, that conversion is applied to
+    //   the chosen operand and the converted operands are used in place of the
+    //   original operands for the remainder of this section.
+    if (HaveL2R) {
+      if (ConvertForConditional(*this, LHS, ICSLeftToRight))
+        return QualType();
+      LTy = LHS->getType();
+    } else if (HaveR2L) {
+      if (ConvertForConditional(*this, RHS, ICSRightToLeft))
+        return QualType();
+      RTy = RHS->getType();
+    }
+  }
+
+  // C++0x 5.16p4
+  //   If the second and third operands are lvalues and have the same type,
+  //   the result is of that type [...]
+  bool Same = Context.getCanonicalType(LTy) == Context.getCanonicalType(RTy);
+  if (Same && LHS->isLvalue(Context) == Expr::LV_Valid &&
+      RHS->isLvalue(Context) == Expr::LV_Valid)
+    return LTy;
+
+  // C++0x 5.16p5
+  //   Otherwise, the result is an rvalue. If the second and third operands
+  //   do not have the same type, and either has (cv) class type, ...
+  if (!Same && (LTy->isRecordType() || RTy->isRecordType())) {
+    //   ... overload resolution is used to determine the conversions (if any)
+    //   to be applied to the operands. If the overload resolution fails, the
+    //   program is ill-formed.
+    if (FindConditionalOverload(*this, LHS, RHS, QuestionLoc))
+      return QualType();
+  }
+
+  // C++0x 5.16p6
+  //   LValue-to-rvalue, array-to-pointer, and function-to-pointer standard
+  //   conversions are performed on the second and third operands.
+  DefaultFunctionArrayLvalueConversion(LHS);
+  DefaultFunctionArrayLvalueConversion(RHS);
+  LTy = LHS->getType();
+  RTy = RHS->getType();
+
+  //   After those conversions, one of the following shall hold:
+  //   -- The second and third operands have the same type; the result
+  //      is of that type.
+  if (Context.getCanonicalType(LTy) == Context.getCanonicalType(RTy))
+    return LTy;
+
+  //   -- The second and third operands have arithmetic or enumeration type;
+  //      the usual arithmetic conversions are performed to bring them to a
+  //      common type, and the result is of that type.
+  if (LTy->isArithmeticType() && RTy->isArithmeticType()) {
+    UsualArithmeticConversions(LHS, RHS);
+    return LHS->getType();
+  }
+
+  //   -- The second and third operands have pointer type, or one has pointer
+  //      type and the other is a null pointer constant; pointer conversions
+  //      and qualification conversions are performed to bring them to their
+  //      composite pointer type. The result is of the composite pointer type.
+  //   -- The second and third operands have pointer to member type, or one has
+  //      pointer to member type and the other is a null pointer constant;
+  //      pointer to member conversions and qualification conversions are
+  //      performed to bring them to a common type, whose cv-qualification
+  //      shall match the cv-qualification of either the second or the third
+  //      operand. The result is of the common type.
+  QualType Composite = FindCompositePointerType(LHS, RHS);
+  if (!Composite.isNull())
+    return Composite;
+  
+  // Similarly, attempt to find composite type of twp objective-c pointers.
+  Composite = FindCompositeObjCPointerType(LHS, RHS, QuestionLoc);
+  if (!Composite.isNull())
+    return Composite;
+
+  Diag(QuestionLoc, diag::err_typecheck_cond_incompatible_operands)
+    << LHS->getType() << RHS->getType()
+    << LHS->getSourceRange() << RHS->getSourceRange();
+  return QualType();
+}
+
+/// \brief Find a merged pointer type and convert the two expressions to it.
+///
+/// This finds the composite pointer type (or member pointer type) for @p E1
+/// and @p E2 according to C++0x 5.9p2. It converts both expressions to this
+/// type and returns it.
+/// It does not emit diagnostics.
+QualType Sema::FindCompositePointerType(Expr *&E1, Expr *&E2) {
+  assert(getLangOptions().CPlusPlus && "This function assumes C++");
+  QualType T1 = E1->getType(), T2 = E2->getType();
+
+  if (!T1->isAnyPointerType() && !T1->isMemberPointerType() &&
+      !T2->isAnyPointerType() && !T2->isMemberPointerType())
+   return QualType();
+
+  // C++0x 5.9p2
+  //   Pointer conversions and qualification conversions are performed on
+  //   pointer operands to bring them to their composite pointer type. If
+  //   one operand is a null pointer constant, the composite pointer type is
+  //   the type of the other operand.
+  if (E1->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull)) {
+    if (T2->isMemberPointerType())
+      ImpCastExprToType(E1, T2, CastExpr::CK_NullToMemberPointer);
+    else
+      ImpCastExprToType(E1, T2, CastExpr::CK_IntegralToPointer);
+    return T2;
+  }
+  if (E2->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull)) {
+    if (T1->isMemberPointerType())
+      ImpCastExprToType(E2, T1, CastExpr::CK_NullToMemberPointer);
+    else
+      ImpCastExprToType(E2, T1, CastExpr::CK_IntegralToPointer);
+    return T1;
+  }
+
+  // Now both have to be pointers or member pointers.
+  if ((!T1->isPointerType() && !T1->isMemberPointerType()) ||
+      (!T2->isPointerType() && !T2->isMemberPointerType()))
+    return QualType();
+
+  //   Otherwise, of one of the operands has type "pointer to cv1 void," then
+  //   the other has type "pointer to cv2 T" and the composite pointer type is
+  //   "pointer to cv12 void," where cv12 is the union of cv1 and cv2.
+  //   Otherwise, the composite pointer type is a pointer type similar to the
+  //   type of one of the operands, with a cv-qualification signature that is
+  //   the union of the cv-qualification signatures of the operand types.
+  // In practice, the first part here is redundant; it's subsumed by the second.
+  // What we do here is, we build the two possible composite types, and try the
+  // conversions in both directions. If only one works, or if the two composite
+  // types are the same, we have succeeded.
+  // FIXME: extended qualifiers?
+  typedef llvm::SmallVector<unsigned, 4> QualifierVector;
+  QualifierVector QualifierUnion;
+  typedef llvm::SmallVector<std::pair<const Type *, const Type *>, 4>
+      ContainingClassVector;
+  ContainingClassVector MemberOfClass;
+  QualType Composite1 = Context.getCanonicalType(T1),
+           Composite2 = Context.getCanonicalType(T2);
+  do {
+    const PointerType *Ptr1, *Ptr2;
+    if ((Ptr1 = Composite1->getAs<PointerType>()) &&
+        (Ptr2 = Composite2->getAs<PointerType>())) {
+      Composite1 = Ptr1->getPointeeType();
+      Composite2 = Ptr2->getPointeeType();
+      QualifierUnion.push_back(
+                 Composite1.getCVRQualifiers() | Composite2.getCVRQualifiers());
+      MemberOfClass.push_back(std::make_pair((const Type *)0, (const Type *)0));
+      continue;
+    }
+
+    const MemberPointerType *MemPtr1, *MemPtr2;
+    if ((MemPtr1 = Composite1->getAs<MemberPointerType>()) &&
+        (MemPtr2 = Composite2->getAs<MemberPointerType>())) {
+      Composite1 = MemPtr1->getPointeeType();
+      Composite2 = MemPtr2->getPointeeType();
+      QualifierUnion.push_back(
+                 Composite1.getCVRQualifiers() | Composite2.getCVRQualifiers());
+      MemberOfClass.push_back(std::make_pair(MemPtr1->getClass(),
+                                             MemPtr2->getClass()));
+      continue;
+    }
+
+    // FIXME: block pointer types?
+
+    // Cannot unwrap any more types.
+    break;
+  } while (true);
+
+  // Rewrap the composites as pointers or member pointers with the union CVRs.
+  ContainingClassVector::reverse_iterator MOC
+    = MemberOfClass.rbegin();
+  for (QualifierVector::reverse_iterator
+         I = QualifierUnion.rbegin(),
+         E = QualifierUnion.rend();
+       I != E; (void)++I, ++MOC) {
+    Qualifiers Quals = Qualifiers::fromCVRMask(*I);
+    if (MOC->first && MOC->second) {
+      // Rebuild member pointer type
+      Composite1 = Context.getMemberPointerType(
+                                    Context.getQualifiedType(Composite1, Quals),
+                                    MOC->first);
+      Composite2 = Context.getMemberPointerType(
+                                    Context.getQualifiedType(Composite2, Quals),
+                                    MOC->second);
+    } else {
+      // Rebuild pointer type
+      Composite1
+        = Context.getPointerType(Context.getQualifiedType(Composite1, Quals));
+      Composite2
+        = Context.getPointerType(Context.getQualifiedType(Composite2, Quals));
+    }
+  }
+
+  ImplicitConversionSequence E1ToC1 =
+    TryImplicitConversion(E1, Composite1,
+                          /*SuppressUserConversions=*/false,
+                          /*AllowExplicit=*/false,
+                          /*ForceRValue=*/false,
+                          /*InOverloadResolution=*/false);
+  ImplicitConversionSequence E2ToC1 =
+    TryImplicitConversion(E2, Composite1,
+                          /*SuppressUserConversions=*/false,
+                          /*AllowExplicit=*/false,
+                          /*ForceRValue=*/false,
+                          /*InOverloadResolution=*/false);
+
+  ImplicitConversionSequence E1ToC2, E2ToC2;
+  E1ToC2.setBad();
+  E2ToC2.setBad();  
+  if (Context.getCanonicalType(Composite1) !=
+      Context.getCanonicalType(Composite2)) {
+    E1ToC2 = TryImplicitConversion(E1, Composite2,
+                                   /*SuppressUserConversions=*/false,
+                                   /*AllowExplicit=*/false,
+                                   /*ForceRValue=*/false,
+                                   /*InOverloadResolution=*/false);
+    E2ToC2 = TryImplicitConversion(E2, Composite2,
+                                   /*SuppressUserConversions=*/false,
+                                   /*AllowExplicit=*/false,
+                                   /*ForceRValue=*/false,
+                                   /*InOverloadResolution=*/false);
+  }
+
+  bool ToC1Viable = !E1ToC1.isBad() && !E2ToC1.isBad();
+  bool ToC2Viable = !E1ToC2.isBad() && !E2ToC2.isBad();
+  if (ToC1Viable && !ToC2Viable) {
+    if (!PerformImplicitConversion(E1, Composite1, E1ToC1, Sema::AA_Converting) &&
+        !PerformImplicitConversion(E2, Composite1, E2ToC1, Sema::AA_Converting))
+      return Composite1;
+  }
+  if (ToC2Viable && !ToC1Viable) {
+    if (!PerformImplicitConversion(E1, Composite2, E1ToC2, Sema::AA_Converting) &&
+        !PerformImplicitConversion(E2, Composite2, E2ToC2, Sema::AA_Converting))
+      return Composite2;
+  }
+  return QualType();
+}
+
+Sema::OwningExprResult Sema::MaybeBindToTemporary(Expr *E) {
+  if (!Context.getLangOptions().CPlusPlus)
+    return Owned(E);
+
+  assert(!isa<CXXBindTemporaryExpr>(E) && "Double-bound temporary?");
+
+  const RecordType *RT = E->getType()->getAs<RecordType>();
+  if (!RT)
+    return Owned(E);
+
+  // If this is the result of a call expression, our source might
+  // actually be a reference, in which case we shouldn't bind.
+  if (CallExpr *CE = dyn_cast<CallExpr>(E)) {
+    QualType Ty = CE->getCallee()->getType();
+    if (const PointerType *PT = Ty->getAs<PointerType>())
+      Ty = PT->getPointeeType();
+    
+    const FunctionType *FTy = Ty->getAs<FunctionType>();
+    if (FTy->getResultType()->isReferenceType())
+      return Owned(E);
+  }
+
+  // That should be enough to guarantee that this type is complete.
+  // If it has a trivial destructor, we can avoid the extra copy.
+  CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
+  if (RD->hasTrivialDestructor())
+    return Owned(E);
+
+  CXXTemporary *Temp = CXXTemporary::Create(Context,
+                                            RD->getDestructor(Context));
+  ExprTemporaries.push_back(Temp);
+  if (CXXDestructorDecl *Destructor =
+        const_cast<CXXDestructorDecl*>(RD->getDestructor(Context)))
+    MarkDeclarationReferenced(E->getExprLoc(), Destructor);
+  // FIXME: Add the temporary to the temporaries vector.
+  return Owned(CXXBindTemporaryExpr::Create(Context, Temp, E));
+}
+
+Expr *Sema::MaybeCreateCXXExprWithTemporaries(Expr *SubExpr) {
+  assert(SubExpr && "sub expression can't be null!");
+
+  unsigned FirstTemporary = ExprEvalContexts.back().NumTemporaries;
+  assert(ExprTemporaries.size() >= FirstTemporary);
+  if (ExprTemporaries.size() == FirstTemporary)
+    return SubExpr;
+
+  Expr *E = CXXExprWithTemporaries::Create(Context, SubExpr,
+                                           &ExprTemporaries[FirstTemporary],
+                                       ExprTemporaries.size() - FirstTemporary);
+  ExprTemporaries.erase(ExprTemporaries.begin() + FirstTemporary,
+                        ExprTemporaries.end());
+
+  return E;
+}
+
+Sema::OwningExprResult 
+Sema::MaybeCreateCXXExprWithTemporaries(OwningExprResult SubExpr) {
+  if (SubExpr.isInvalid())
+    return ExprError();
+  
+  return Owned(MaybeCreateCXXExprWithTemporaries(SubExpr.takeAs<Expr>()));
+}
+
+FullExpr Sema::CreateFullExpr(Expr *SubExpr) {
+  unsigned FirstTemporary = ExprEvalContexts.back().NumTemporaries;
+  assert(ExprTemporaries.size() >= FirstTemporary);
+  
+  unsigned NumTemporaries = ExprTemporaries.size() - FirstTemporary;
+  CXXTemporary **Temporaries = 
+    NumTemporaries == 0 ? 0 : &ExprTemporaries[FirstTemporary];
+  
+  FullExpr E = FullExpr::Create(Context, SubExpr, Temporaries, NumTemporaries);
+
+  ExprTemporaries.erase(ExprTemporaries.begin() + FirstTemporary,
+                        ExprTemporaries.end());
+
+  return E;
+}
+
+Sema::OwningExprResult
+Sema::ActOnStartCXXMemberReference(Scope *S, ExprArg Base, SourceLocation OpLoc,
+                                   tok::TokenKind OpKind, TypeTy *&ObjectType) {
+  // Since this might be a postfix expression, get rid of ParenListExprs.
+  Base = MaybeConvertParenListExprToParenExpr(S, move(Base));
+
+  Expr *BaseExpr = (Expr*)Base.get();
+  assert(BaseExpr && "no record expansion");
+
+  QualType BaseType = BaseExpr->getType();
+  if (BaseType->isDependentType()) {
+    // If we have a pointer to a dependent type and are using the -> operator,
+    // the object type is the type that the pointer points to. We might still
+    // have enough information about that type to do something useful.
+    if (OpKind == tok::arrow)
+      if (const PointerType *Ptr = BaseType->getAs<PointerType>())
+        BaseType = Ptr->getPointeeType();
+    
+    ObjectType = BaseType.getAsOpaquePtr();
+    return move(Base);
+  }
+
+  // C++ [over.match.oper]p8:
+  //   [...] When operator->returns, the operator-> is applied  to the value
+  //   returned, with the original second operand.
+  if (OpKind == tok::arrow) {
+    // The set of types we've considered so far.
+    llvm::SmallPtrSet<CanQualType,8> CTypes;
+    llvm::SmallVector<SourceLocation, 8> Locations;
+    CTypes.insert(Context.getCanonicalType(BaseType));
+    
+    while (BaseType->isRecordType()) {
+      Base = BuildOverloadedArrowExpr(S, move(Base), OpLoc);
+      BaseExpr = (Expr*)Base.get();
+      if (BaseExpr == NULL)
+        return ExprError();
+      if (CXXOperatorCallExpr *OpCall = dyn_cast<CXXOperatorCallExpr>(BaseExpr))
+        Locations.push_back(OpCall->getDirectCallee()->getLocation());
+      BaseType = BaseExpr->getType();
+      CanQualType CBaseType = Context.getCanonicalType(BaseType);
+      if (!CTypes.insert(CBaseType)) {
+        Diag(OpLoc, diag::err_operator_arrow_circular);
+        for (unsigned i = 0; i < Locations.size(); i++)
+          Diag(Locations[i], diag::note_declared_at);
+        return ExprError();
+      }
+    }
+
+    if (BaseType->isPointerType())
+      BaseType = BaseType->getPointeeType();
+  }
+
+  // We could end up with various non-record types here, such as extended
+  // vector types or Objective-C interfaces. Just return early and let
+  // ActOnMemberReferenceExpr do the work.
+  if (!BaseType->isRecordType()) {
+    // C++ [basic.lookup.classref]p2:
+    //   [...] If the type of the object expression is of pointer to scalar
+    //   type, the unqualified-id is looked up in the context of the complete
+    //   postfix-expression.
+    ObjectType = 0;
+    return move(Base);
+  }
+
+  // The object type must be complete (or dependent).
+  if (!BaseType->isDependentType() &&
+      RequireCompleteType(OpLoc, BaseType, 
+                          PDiag(diag::err_incomplete_member_access)))
+    return ExprError();
+  
+  // C++ [basic.lookup.classref]p2:
+  //   If the id-expression in a class member access (5.2.5) is an
+  //   unqualified-id, and the type of the object expression is of a class
+  //   type C (or of pointer to a class type C), the unqualified-id is looked
+  //   up in the scope of class C. [...]
+  ObjectType = BaseType.getAsOpaquePtr();
+  
+  return move(Base);
+}
+
+CXXMemberCallExpr *Sema::BuildCXXMemberCallExpr(Expr *Exp, 
+                                                CXXMethodDecl *Method) {
+  if (PerformObjectArgumentInitialization(Exp, Method))
+    assert(0 && "Calling BuildCXXMemberCallExpr with invalid call?");
+
+  MemberExpr *ME = 
+      new (Context) MemberExpr(Exp, /*IsArrow=*/false, Method, 
+                               SourceLocation(), Method->getType());
+  QualType ResultType = Method->getResultType().getNonReferenceType();
+  MarkDeclarationReferenced(Exp->getLocStart(), Method);
+  CXXMemberCallExpr *CE =
+    new (Context) CXXMemberCallExpr(Context, ME, 0, 0, ResultType,
+                                    Exp->getLocEnd());
+  return CE;
+}
+
+Sema::OwningExprResult Sema::BuildCXXCastArgument(SourceLocation CastLoc,
+                                                  QualType Ty,
+                                                  CastExpr::CastKind Kind,
+                                                  CXXMethodDecl *Method,
+                                                  ExprArg Arg) {
+  Expr *From = Arg.takeAs<Expr>();
+
+  switch (Kind) {
+  default: assert(0 && "Unhandled cast kind!");
+  case CastExpr::CK_ConstructorConversion: {
+    ASTOwningVector<&ActionBase::DeleteExpr> ConstructorArgs(*this);
+    
+    if (CompleteConstructorCall(cast<CXXConstructorDecl>(Method),
+                                MultiExprArg(*this, (void **)&From, 1),
+                                CastLoc, ConstructorArgs))
+      return ExprError();
+    
+    OwningExprResult Result = 
+      BuildCXXConstructExpr(CastLoc, Ty, cast<CXXConstructorDecl>(Method), 
+                            move_arg(ConstructorArgs));
+    if (Result.isInvalid())
+      return ExprError();
+    
+    return MaybeBindToTemporary(Result.takeAs<Expr>());
+  }
+
+  case CastExpr::CK_UserDefinedConversion: {
+    assert(!From->getType()->isPointerType() && "Arg can't have pointer type!");
+
+    // Create an implicit call expr that calls it.
+    CXXMemberCallExpr *CE = BuildCXXMemberCallExpr(From, Method);
+    return MaybeBindToTemporary(CE);
+  }
+  }
+}    
+
+Sema::OwningExprResult Sema::ActOnFinishFullExpr(ExprArg Arg) {
+  Expr *FullExpr = Arg.takeAs<Expr>();
+  if (FullExpr)
+    FullExpr = MaybeCreateCXXExprWithTemporaries(FullExpr);
+
+  return Owned(FullExpr);
+}
diff --git a/lib/Sema/SemaExprObjC.cpp b/lib/Sema/SemaExprObjC.cpp
new file mode 100644
index 0000000..85956c3
--- /dev/null
+++ b/lib/Sema/SemaExprObjC.cpp
@@ -0,0 +1,671 @@
+//===--- SemaExprObjC.cpp - Semantic Analysis for ObjC Expressions --------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+//  This file implements semantic analysis for Objective-C expressions.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Sema.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/AST/ExprObjC.h"
+#include "llvm/ADT/SmallString.h"
+#include "clang/Lex/Preprocessor.h"
+
+using namespace clang;
+
+Sema::ExprResult Sema::ParseObjCStringLiteral(SourceLocation *AtLocs,
+                                              ExprTy **strings,
+                                              unsigned NumStrings) {
+  StringLiteral **Strings = reinterpret_cast<StringLiteral**>(strings);
+
+  // Most ObjC strings are formed out of a single piece.  However, we *can*
+  // have strings formed out of multiple @ strings with multiple pptokens in
+  // each one, e.g. @"foo" "bar" @"baz" "qux"   which need to be turned into one
+  // StringLiteral for ObjCStringLiteral to hold onto.
+  StringLiteral *S = Strings[0];
+
+  // If we have a multi-part string, merge it all together.
+  if (NumStrings != 1) {
+    // Concatenate objc strings.
+    llvm::SmallString<128> StrBuf;
+    llvm::SmallVector<SourceLocation, 8> StrLocs;
+
+    for (unsigned i = 0; i != NumStrings; ++i) {
+      S = Strings[i];
+
+      // ObjC strings can't be wide.
+      if (S->isWide()) {
+        Diag(S->getLocStart(), diag::err_cfstring_literal_not_string_constant)
+          << S->getSourceRange();
+        return true;
+      }
+
+      // Get the string data.
+      StrBuf.append(S->getStrData(), S->getStrData()+S->getByteLength());
+
+      // Get the locations of the string tokens.
+      StrLocs.append(S->tokloc_begin(), S->tokloc_end());
+
+      // Free the temporary string.
+      S->Destroy(Context);
+    }
+
+    // Create the aggregate string with the appropriate content and location
+    // information.
+    S = StringLiteral::Create(Context, &StrBuf[0], StrBuf.size(), false,
+                              Context.getPointerType(Context.CharTy),
+                              &StrLocs[0], StrLocs.size());
+  }
+
+  // Verify that this composite string is acceptable for ObjC strings.
+  if (CheckObjCString(S))
+    return true;
+
+  // Initialize the constant string interface lazily. This assumes
+  // the NSString interface is seen in this translation unit. Note: We
+  // don't use NSConstantString, since the runtime team considers this
+  // interface private (even though it appears in the header files).
+  QualType Ty = Context.getObjCConstantStringInterface();
+  if (!Ty.isNull()) {
+    Ty = Context.getObjCObjectPointerType(Ty);
+  } else {
+    IdentifierInfo *NSIdent = &Context.Idents.get("NSString");
+    NamedDecl *IF = LookupSingleName(TUScope, NSIdent, LookupOrdinaryName);
+    if (ObjCInterfaceDecl *StrIF = dyn_cast_or_null<ObjCInterfaceDecl>(IF)) {
+      Context.setObjCConstantStringInterface(StrIF);
+      Ty = Context.getObjCConstantStringInterface();
+      Ty = Context.getObjCObjectPointerType(Ty);
+    } else {
+      // If there is no NSString interface defined then treat constant
+      // strings as untyped objects and let the runtime figure it out later.
+      Ty = Context.getObjCIdType();
+    }
+  }
+
+  return new (Context) ObjCStringLiteral(S, Ty, AtLocs[0]);
+}
+
+Expr *Sema::BuildObjCEncodeExpression(SourceLocation AtLoc,
+                                      QualType EncodedType,
+                                      SourceLocation RParenLoc) {
+  QualType StrTy;
+  if (EncodedType->isDependentType())
+    StrTy = Context.DependentTy;
+  else {
+    std::string Str;
+    Context.getObjCEncodingForType(EncodedType, Str);
+
+    // The type of @encode is the same as the type of the corresponding string,
+    // which is an array type.
+    StrTy = Context.CharTy;
+    // A C++ string literal has a const-qualified element type (C++ 2.13.4p1).
+    if (getLangOptions().CPlusPlus)
+      StrTy.addConst();
+    StrTy = Context.getConstantArrayType(StrTy, llvm::APInt(32, Str.size()+1),
+                                         ArrayType::Normal, 0);
+  }
+
+  return new (Context) ObjCEncodeExpr(StrTy, EncodedType, AtLoc, RParenLoc);
+}
+
+Sema::ExprResult Sema::ParseObjCEncodeExpression(SourceLocation AtLoc,
+                                                 SourceLocation EncodeLoc,
+                                                 SourceLocation LParenLoc,
+                                                 TypeTy *ty,
+                                                 SourceLocation RParenLoc) {
+  // FIXME: Preserve type source info ?
+  QualType EncodedType = GetTypeFromParser(ty);
+
+  return BuildObjCEncodeExpression(AtLoc, EncodedType, RParenLoc);
+}
+
+Sema::ExprResult Sema::ParseObjCSelectorExpression(Selector Sel,
+                                                   SourceLocation AtLoc,
+                                                   SourceLocation SelLoc,
+                                                   SourceLocation LParenLoc,
+                                                   SourceLocation RParenLoc) {
+  ObjCMethodDecl *Method = LookupInstanceMethodInGlobalPool(Sel,
+                             SourceRange(LParenLoc, RParenLoc), false);
+  if (!Method)
+    Method = LookupFactoryMethodInGlobalPool(Sel,
+                                          SourceRange(LParenLoc, RParenLoc));
+  if (!Method)
+    Diag(SelLoc, diag::warn_undeclared_selector) << Sel;
+
+  QualType Ty = Context.getObjCSelType();
+  return new (Context) ObjCSelectorExpr(Ty, Sel, AtLoc, RParenLoc);
+}
+
+Sema::ExprResult Sema::ParseObjCProtocolExpression(IdentifierInfo *ProtocolId,
+                                                   SourceLocation AtLoc,
+                                                   SourceLocation ProtoLoc,
+                                                   SourceLocation LParenLoc,
+                                                   SourceLocation RParenLoc) {
+  ObjCProtocolDecl* PDecl = LookupProtocol(ProtocolId);
+  if (!PDecl) {
+    Diag(ProtoLoc, diag::err_undeclared_protocol) << ProtocolId;
+    return true;
+  }
+
+  QualType Ty = Context.getObjCProtoType();
+  if (Ty.isNull())
+    return true;
+  Ty = Context.getObjCObjectPointerType(Ty);
+  return new (Context) ObjCProtocolExpr(Ty, PDecl, AtLoc, RParenLoc);
+}
+
+bool Sema::CheckMessageArgumentTypes(Expr **Args, unsigned NumArgs,
+                                     Selector Sel, ObjCMethodDecl *Method,
+                                     bool isClassMessage,
+                                     SourceLocation lbrac, SourceLocation rbrac,
+                                     QualType &ReturnType) {
+  if (!Method) {
+    // Apply default argument promotion as for (C99 6.5.2.2p6).
+    for (unsigned i = 0; i != NumArgs; i++)
+      DefaultArgumentPromotion(Args[i]);
+
+    unsigned DiagID = isClassMessage ? diag::warn_class_method_not_found :
+                                       diag::warn_inst_method_not_found;
+    Diag(lbrac, DiagID)
+      << Sel << isClassMessage << SourceRange(lbrac, rbrac);
+    ReturnType = Context.getObjCIdType();
+    return false;
+  }
+
+  ReturnType = Method->getResultType();
+
+  unsigned NumNamedArgs = Sel.getNumArgs();
+  assert(NumArgs >= NumNamedArgs && "Too few arguments for selector!");
+
+  bool IsError = false;
+  for (unsigned i = 0; i < NumNamedArgs; i++) {
+    Expr *argExpr = Args[i];
+    assert(argExpr && "CheckMessageArgumentTypes(): missing expression");
+
+    QualType lhsType = Method->param_begin()[i]->getType();
+    QualType rhsType = argExpr->getType();
+
+    // If necessary, apply function/array conversion. C99 6.7.5.3p[7,8].
+    if (lhsType->isArrayType())
+      lhsType = Context.getArrayDecayedType(lhsType);
+    else if (lhsType->isFunctionType())
+      lhsType = Context.getPointerType(lhsType);
+
+    AssignConvertType Result =
+      CheckSingleAssignmentConstraints(lhsType, argExpr);
+    if (Args[i] != argExpr) // The expression was converted.
+      Args[i] = argExpr; // Make sure we store the converted expression.
+
+    IsError |=
+      DiagnoseAssignmentResult(Result, argExpr->getLocStart(), lhsType, rhsType,
+                               argExpr, AA_Sending);
+  }
+
+  // Promote additional arguments to variadic methods.
+  if (Method->isVariadic()) {
+    for (unsigned i = NumNamedArgs; i < NumArgs; ++i)
+      IsError |= DefaultVariadicArgumentPromotion(Args[i], VariadicMethod);
+  } else {
+    // Check for extra arguments to non-variadic methods.
+    if (NumArgs != NumNamedArgs) {
+      Diag(Args[NumNamedArgs]->getLocStart(),
+           diag::err_typecheck_call_too_many_args)
+        << 2 /*method*/ << Method->getSourceRange()
+        << SourceRange(Args[NumNamedArgs]->getLocStart(),
+                       Args[NumArgs-1]->getLocEnd());
+    }
+  }
+
+  return IsError;
+}
+
+bool Sema::isSelfExpr(Expr *RExpr) {
+  if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(RExpr))
+    if (DRE->getDecl()->getIdentifier() == &Context.Idents.get("self"))
+      return true;
+  return false;
+}
+
+// Helper method for ActOnClassMethod/ActOnInstanceMethod.
+// Will search "local" class/category implementations for a method decl.
+// If failed, then we search in class's root for an instance method.
+// Returns 0 if no method is found.
+ObjCMethodDecl *Sema::LookupPrivateClassMethod(Selector Sel,
+                                          ObjCInterfaceDecl *ClassDecl) {
+  ObjCMethodDecl *Method = 0;
+  // lookup in class and all superclasses
+  while (ClassDecl && !Method) {
+    if (ObjCImplementationDecl *ImpDecl = ClassDecl->getImplementation())
+      Method = ImpDecl->getClassMethod(Sel);
+
+    // Look through local category implementations associated with the class.
+    if (!Method)
+      Method = ClassDecl->getCategoryClassMethod(Sel);
+
+    // Before we give up, check if the selector is an instance method.
+    // But only in the root. This matches gcc's behaviour and what the
+    // runtime expects.
+    if (!Method && !ClassDecl->getSuperClass()) {
+      Method = ClassDecl->lookupInstanceMethod(Sel);
+      // Look through local category implementations associated
+      // with the root class.
+      if (!Method)
+        Method = LookupPrivateInstanceMethod(Sel, ClassDecl);
+    }
+
+    ClassDecl = ClassDecl->getSuperClass();
+  }
+  return Method;
+}
+
+ObjCMethodDecl *Sema::LookupPrivateInstanceMethod(Selector Sel,
+                                              ObjCInterfaceDecl *ClassDecl) {
+  ObjCMethodDecl *Method = 0;
+  while (ClassDecl && !Method) {
+    // If we have implementations in scope, check "private" methods.
+    if (ObjCImplementationDecl *ImpDecl = ClassDecl->getImplementation())
+      Method = ImpDecl->getInstanceMethod(Sel);
+
+    // Look through local category implementations associated with the class.
+    if (!Method)
+      Method = ClassDecl->getCategoryInstanceMethod(Sel);
+    ClassDecl = ClassDecl->getSuperClass();
+  }
+  return Method;
+}
+
+Action::OwningExprResult Sema::ActOnClassPropertyRefExpr(
+  IdentifierInfo &receiverName,
+  IdentifierInfo &propertyName,
+  SourceLocation &receiverNameLoc,
+  SourceLocation &propertyNameLoc) {
+
+  IdentifierInfo *receiverNamePtr = &receiverName;
+  ObjCInterfaceDecl *IFace = getObjCInterfaceDecl(receiverNamePtr);
+
+  // Search for a declared property first.
+
+  Selector Sel = PP.getSelectorTable().getNullarySelector(&propertyName);
+  ObjCMethodDecl *Getter = IFace->lookupClassMethod(Sel);
+
+  // If this reference is in an @implementation, check for 'private' methods.
+  if (!Getter)
+    if (ObjCMethodDecl *CurMeth = getCurMethodDecl())
+      if (ObjCInterfaceDecl *ClassDecl = CurMeth->getClassInterface())
+        if (ObjCImplementationDecl *ImpDecl = ClassDecl->getImplementation())
+          Getter = ImpDecl->getClassMethod(Sel);
+
+  if (Getter) {
+    // FIXME: refactor/share with ActOnMemberReference().
+    // Check if we can reference this property.
+    if (DiagnoseUseOfDecl(Getter, propertyNameLoc))
+      return ExprError();
+  }
+
+  // Look for the matching setter, in case it is needed.
+  Selector SetterSel =
+    SelectorTable::constructSetterName(PP.getIdentifierTable(),
+                                       PP.getSelectorTable(), &propertyName);
+
+  ObjCMethodDecl *Setter = IFace->lookupClassMethod(SetterSel);
+  if (!Setter) {
+    // If this reference is in an @implementation, also check for 'private'
+    // methods.
+    if (ObjCMethodDecl *CurMeth = getCurMethodDecl())
+      if (ObjCInterfaceDecl *ClassDecl = CurMeth->getClassInterface())
+        if (ObjCImplementationDecl *ImpDecl = ClassDecl->getImplementation())
+          Setter = ImpDecl->getClassMethod(SetterSel);
+  }
+  // Look through local category implementations associated with the class.
+  if (!Setter)
+    Setter = IFace->getCategoryClassMethod(SetterSel);
+
+  if (Setter && DiagnoseUseOfDecl(Setter, propertyNameLoc))
+    return ExprError();
+
+  if (Getter || Setter) {
+    QualType PType;
+
+    if (Getter)
+      PType = Getter->getResultType();
+    else {
+      for (ObjCMethodDecl::param_iterator PI = Setter->param_begin(),
+           E = Setter->param_end(); PI != E; ++PI)
+        PType = (*PI)->getType();
+    }
+    return Owned(new (Context) ObjCImplicitSetterGetterRefExpr(
+                                  Getter, PType, Setter,
+                                  propertyNameLoc, IFace, receiverNameLoc));
+  }
+  return ExprError(Diag(propertyNameLoc, diag::err_property_not_found)
+                     << &propertyName << Context.getObjCInterfaceType(IFace));
+}
+
+
+// ActOnClassMessage - used for both unary and keyword messages.
+// ArgExprs is optional - if it is present, the number of expressions
+// is obtained from Sel.getNumArgs().
+Sema::ExprResult Sema::ActOnClassMessage(
+  Scope *S,
+  IdentifierInfo *receiverName, Selector Sel,
+  SourceLocation lbrac, SourceLocation receiverLoc,
+  SourceLocation selectorLoc, SourceLocation rbrac,
+  ExprTy **Args, unsigned NumArgs) {
+  assert(receiverName && "missing receiver class name");
+
+  Expr **ArgExprs = reinterpret_cast<Expr **>(Args);
+  ObjCInterfaceDecl* ClassDecl = 0;
+  bool isSuper = false;
+
+  if (receiverName->isStr("super")) {
+    if (getCurMethodDecl()) {
+      isSuper = true;
+      ObjCInterfaceDecl *OID = getCurMethodDecl()->getClassInterface();
+      if (!OID)
+        return Diag(lbrac, diag::error_no_super_class_message)
+                      << getCurMethodDecl()->getDeclName();
+      ClassDecl = OID->getSuperClass();
+      if (!ClassDecl)
+        return Diag(lbrac, diag::error_no_super_class) << OID->getDeclName();
+      if (getCurMethodDecl()->isInstanceMethod()) {
+        QualType superTy = Context.getObjCInterfaceType(ClassDecl);
+        superTy = Context.getObjCObjectPointerType(superTy);
+        ExprResult ReceiverExpr = new (Context) ObjCSuperExpr(SourceLocation(),
+                                                              superTy);
+        // We are really in an instance method, redirect.
+        return ActOnInstanceMessage(ReceiverExpr.get(), Sel, lbrac,
+                                    selectorLoc, rbrac, Args, NumArgs);
+      }
+      // We are sending a message to 'super' within a class method. Do nothing,
+      // the receiver will pass through as 'super' (how convenient:-).
+    } else {
+      // 'super' has been used outside a method context. If a variable named
+      // 'super' has been declared, redirect. If not, produce a diagnostic.
+      NamedDecl *SuperDecl
+        = LookupSingleName(S, receiverName, LookupOrdinaryName);
+      ValueDecl *VD = dyn_cast_or_null<ValueDecl>(SuperDecl);
+      if (VD) {
+        ExprResult ReceiverExpr = new (Context) DeclRefExpr(VD, VD->getType(),
+                                                            receiverLoc);
+        // We are really in an instance method, redirect.
+        return ActOnInstanceMessage(ReceiverExpr.get(), Sel, lbrac,
+                                    selectorLoc, rbrac, Args, NumArgs);
+      }
+      else if (TypedefDecl *OCTD = dyn_cast_or_null<TypedefDecl>(SuperDecl)) {
+        const ObjCInterfaceType *OCIT;
+        OCIT = OCTD->getUnderlyingType()->getAs<ObjCInterfaceType>();
+        if (!OCIT) {
+          Diag(receiverLoc, diag::err_invalid_receiver_to_message);
+          return true;
+        }
+        ClassDecl = OCIT->getDecl();
+      }
+      else      
+        return Diag(receiverLoc, diag::err_undeclared_var_use) << receiverName;
+    }
+  } else
+    ClassDecl = getObjCInterfaceDecl(receiverName, receiverLoc);
+
+  // The following code allows for the following GCC-ism:
+  //
+  //  typedef XCElementDisplayRect XCElementGraphicsRect;
+  //
+  //  @implementation XCRASlice
+  //  - whatever { // Note that XCElementGraphicsRect is a typedef name.
+  //    _sGraphicsDelegate =[[XCElementGraphicsRect alloc] init];
+  //  }
+  //
+  // If necessary, the following lookup could move to getObjCInterfaceDecl().
+  if (!ClassDecl) {
+    NamedDecl *IDecl
+      = LookupSingleName(TUScope, receiverName, LookupOrdinaryName);
+    if (TypedefDecl *OCTD = dyn_cast_or_null<TypedefDecl>(IDecl)) {
+      const ObjCInterfaceType *OCIT;
+      OCIT = OCTD->getUnderlyingType()->getAs<ObjCInterfaceType>();
+      if (!OCIT) {
+        Diag(receiverLoc, diag::err_invalid_receiver_to_message);
+        return true;
+      }
+      ClassDecl = OCIT->getDecl();
+    }
+  }
+  assert(ClassDecl && "missing interface declaration");
+  ObjCMethodDecl *Method = 0;
+  QualType returnType;
+  if (ClassDecl->isForwardDecl()) {
+    // A forward class used in messaging is tread as a 'Class'
+    Diag(lbrac, diag::warn_receiver_forward_class) << ClassDecl->getDeclName();
+    Method = LookupFactoryMethodInGlobalPool(Sel, SourceRange(lbrac,rbrac));
+    if (Method)
+      Diag(Method->getLocation(), diag::note_method_sent_forward_class)
+        << Method->getDeclName();
+  }
+  if (!Method)
+    Method = ClassDecl->lookupClassMethod(Sel);
+
+  // If we have an implementation in scope, check "private" methods.
+  if (!Method)
+    Method = LookupPrivateClassMethod(Sel, ClassDecl);
+
+  if (Method && DiagnoseUseOfDecl(Method, receiverLoc))
+    return true;
+
+  if (CheckMessageArgumentTypes(ArgExprs, NumArgs, Sel, Method, true,
+                                lbrac, rbrac, returnType))
+    return true;
+
+  returnType = returnType.getNonReferenceType();
+
+  // If we have the ObjCInterfaceDecl* for the class that is receiving the
+  // message, use that to construct the ObjCMessageExpr.  Otherwise pass on the
+  // IdentifierInfo* for the class.
+  // FIXME: need to do a better job handling 'super' usage within a class.  For
+  // now, we simply pass the "super" identifier through (which isn't consistent
+  // with instance methods.
+  if (isSuper)
+    return new (Context) ObjCMessageExpr(receiverName, Sel, returnType, Method,
+                                         lbrac, rbrac, ArgExprs, NumArgs);
+  else
+    return new (Context) ObjCMessageExpr(ClassDecl, Sel, returnType, Method,
+                                         lbrac, rbrac, ArgExprs, NumArgs);
+}
+
+// ActOnInstanceMessage - used for both unary and keyword messages.
+// ArgExprs is optional - if it is present, the number of expressions
+// is obtained from Sel.getNumArgs().
+Sema::ExprResult Sema::ActOnInstanceMessage(ExprTy *receiver, Selector Sel,
+                                            SourceLocation lbrac,
+                                            SourceLocation receiverLoc,
+                                            SourceLocation rbrac,
+                                            ExprTy **Args, unsigned NumArgs) {
+  assert(receiver && "missing receiver expression");
+
+  Expr **ArgExprs = reinterpret_cast<Expr **>(Args);
+  Expr *RExpr = static_cast<Expr *>(receiver);
+
+  // If necessary, apply function/array conversion to the receiver.
+  // C99 6.7.5.3p[7,8].
+  DefaultFunctionArrayLvalueConversion(RExpr);
+
+  QualType returnType;
+  QualType ReceiverCType =
+    Context.getCanonicalType(RExpr->getType()).getUnqualifiedType();
+
+  // Handle messages to 'super'.
+  if (isa<ObjCSuperExpr>(RExpr)) {
+    ObjCMethodDecl *Method = 0;
+    if (ObjCMethodDecl *CurMeth = getCurMethodDecl()) {
+      // If we have an interface in scope, check 'super' methods.
+      if (ObjCInterfaceDecl *ClassDecl = CurMeth->getClassInterface())
+        if (ObjCInterfaceDecl *SuperDecl = ClassDecl->getSuperClass()) {
+          Method = SuperDecl->lookupInstanceMethod(Sel);
+
+          if (!Method)
+            // If we have implementations in scope, check "private" methods.
+            Method = LookupPrivateInstanceMethod(Sel, SuperDecl);
+        }
+    }
+
+    if (Method && DiagnoseUseOfDecl(Method, receiverLoc))
+      return true;
+
+    if (CheckMessageArgumentTypes(ArgExprs, NumArgs, Sel, Method, false,
+                                  lbrac, rbrac, returnType))
+      return true;
+
+    returnType = returnType.getNonReferenceType();
+    return new (Context) ObjCMessageExpr(RExpr, Sel, returnType, Method, lbrac,
+                                         rbrac, ArgExprs, NumArgs);
+  }
+
+  // Handle messages to id.
+  if (ReceiverCType->isObjCIdType() || ReceiverCType->isBlockPointerType() ||
+      Context.isObjCNSObjectType(RExpr->getType())) {
+    ObjCMethodDecl *Method = LookupInstanceMethodInGlobalPool(
+                               Sel, SourceRange(lbrac,rbrac));
+    if (!Method)
+      Method = LookupFactoryMethodInGlobalPool(Sel, SourceRange(lbrac, rbrac));
+    if (CheckMessageArgumentTypes(ArgExprs, NumArgs, Sel, Method, false,
+                                  lbrac, rbrac, returnType))
+      return true;
+    returnType = returnType.getNonReferenceType();
+    return new (Context) ObjCMessageExpr(RExpr, Sel, returnType, Method, lbrac,
+                                         rbrac, ArgExprs, NumArgs);
+  }
+
+  // Handle messages to Class.
+  if (ReceiverCType->isObjCClassType() ||
+      ReceiverCType->isObjCQualifiedClassType()) {
+    ObjCMethodDecl *Method = 0;
+
+    if (ObjCMethodDecl *CurMeth = getCurMethodDecl()) {
+      if (ObjCInterfaceDecl *ClassDecl = CurMeth->getClassInterface()) {
+        // First check the public methods in the class interface.
+        Method = ClassDecl->lookupClassMethod(Sel);
+
+        if (!Method)
+          Method = LookupPrivateClassMethod(Sel, ClassDecl);
+
+        // FIXME: if we still haven't found a method, we need to look in
+        // protocols (if we have qualifiers).
+      }
+      if (Method && DiagnoseUseOfDecl(Method, receiverLoc))
+        return true;
+    }
+    if (!Method) {
+      // If not messaging 'self', look for any factory method named 'Sel'.
+      if (!isSelfExpr(RExpr)) {
+        Method = LookupFactoryMethodInGlobalPool(Sel, SourceRange(lbrac,rbrac));
+        if (!Method) {
+          // If no class (factory) method was found, check if an _instance_
+          // method of the same name exists in the root class only.
+          Method = LookupInstanceMethodInGlobalPool(
+                                   Sel, SourceRange(lbrac,rbrac));
+          if (Method)
+              if (const ObjCInterfaceDecl *ID =
+                dyn_cast<ObjCInterfaceDecl>(Method->getDeclContext())) {
+              if (ID->getSuperClass())
+                Diag(lbrac, diag::warn_root_inst_method_not_found)
+                  << Sel << SourceRange(lbrac, rbrac);
+            }
+        }
+      }
+    }
+    if (CheckMessageArgumentTypes(ArgExprs, NumArgs, Sel, Method, false,
+                                  lbrac, rbrac, returnType))
+      return true;
+    returnType = returnType.getNonReferenceType();
+    return new (Context) ObjCMessageExpr(RExpr, Sel, returnType, Method, lbrac,
+                                         rbrac, ArgExprs, NumArgs);
+  }
+
+  ObjCMethodDecl *Method = 0;
+  ObjCInterfaceDecl* ClassDecl = 0;
+
+  // We allow sending a message to a qualified ID ("id<foo>"), which is ok as
+  // long as one of the protocols implements the selector (if not, warn).
+  if (const ObjCObjectPointerType *QIdTy =
+        ReceiverCType->getAsObjCQualifiedIdType()) {
+    // Search protocols for instance methods.
+    for (ObjCObjectPointerType::qual_iterator I = QIdTy->qual_begin(),
+         E = QIdTy->qual_end(); I != E; ++I) {
+      ObjCProtocolDecl *PDecl = *I;
+      if (PDecl && (Method = PDecl->lookupInstanceMethod(Sel)))
+        break;
+      // Since we aren't supporting "Class<foo>", look for a class method.
+      if (PDecl && (Method = PDecl->lookupClassMethod(Sel)))
+        break;
+    }
+  } else if (const ObjCObjectPointerType *OCIType =
+                ReceiverCType->getAsObjCInterfacePointerType()) {
+    // We allow sending a message to a pointer to an interface (an object).
+
+    ClassDecl = OCIType->getInterfaceDecl();
+    // FIXME: consider using LookupInstanceMethodInGlobalPool, since it will be
+    // faster than the following method (which can do *many* linear searches).
+    // The idea is to add class info to InstanceMethodPool.
+    Method = ClassDecl->lookupInstanceMethod(Sel);
+
+    if (!Method) {
+      // Search protocol qualifiers.
+      for (ObjCObjectPointerType::qual_iterator QI = OCIType->qual_begin(),
+           E = OCIType->qual_end(); QI != E; ++QI) {
+        if ((Method = (*QI)->lookupInstanceMethod(Sel)))
+          break;
+      }
+    }
+    if (!Method) {
+      // If we have implementations in scope, check "private" methods.
+      Method = LookupPrivateInstanceMethod(Sel, ClassDecl);
+
+      if (!Method && !isSelfExpr(RExpr)) {
+        // If we still haven't found a method, look in the global pool. This
+        // behavior isn't very desirable, however we need it for GCC
+        // compatibility. FIXME: should we deviate??
+        if (OCIType->qual_empty()) {
+          Method = LookupInstanceMethodInGlobalPool(
+                               Sel, SourceRange(lbrac,rbrac));
+          if (Method && !OCIType->getInterfaceDecl()->isForwardDecl())
+            Diag(lbrac, diag::warn_maynot_respond)
+              << OCIType->getInterfaceDecl()->getIdentifier()->getName() << Sel;
+        }
+      }
+    }
+    if (Method && DiagnoseUseOfDecl(Method, receiverLoc))
+      return true;
+  } else if (!Context.getObjCIdType().isNull() &&
+             (ReceiverCType->isPointerType() ||
+              (ReceiverCType->isIntegerType() &&
+               ReceiverCType->isScalarType()))) {
+    // Implicitly convert integers and pointers to 'id' but emit a warning.
+    Diag(lbrac, diag::warn_bad_receiver_type)
+      << RExpr->getType() << RExpr->getSourceRange();
+    if (ReceiverCType->isPointerType())
+      ImpCastExprToType(RExpr, Context.getObjCIdType(), CastExpr::CK_BitCast);
+    else
+      ImpCastExprToType(RExpr, Context.getObjCIdType(),
+                        CastExpr::CK_IntegralToPointer);
+  } else {
+    // Reject other random receiver types (e.g. structs).
+    Diag(lbrac, diag::err_bad_receiver_type)
+      << RExpr->getType() << RExpr->getSourceRange();
+    return true;
+  }
+
+  if (Method)
+    DiagnoseSentinelCalls(Method, receiverLoc, ArgExprs, NumArgs);
+  if (CheckMessageArgumentTypes(ArgExprs, NumArgs, Sel, Method, false,
+                                lbrac, rbrac, returnType))
+    return true;
+  returnType = returnType.getNonReferenceType();
+  return new (Context) ObjCMessageExpr(RExpr, Sel, returnType, Method, lbrac,
+                                       rbrac, ArgExprs, NumArgs);
+}
+
diff --git a/lib/Sema/SemaInit.cpp b/lib/Sema/SemaInit.cpp
new file mode 100644
index 0000000..d47b8ca
--- /dev/null
+++ b/lib/Sema/SemaInit.cpp
@@ -0,0 +1,3982 @@
+//===--- SemaInit.cpp - Semantic Analysis for Initializers ----------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements semantic analysis for initializers. The main entry
+// point is Sema::CheckInitList(), but all of the work is performed
+// within the InitListChecker class.
+//
+// This file also implements Sema::CheckInitializerTypes.
+//
+//===----------------------------------------------------------------------===//
+
+#include "SemaInit.h"
+#include "Lookup.h"
+#include "Sema.h"
+#include "clang/Parse/Designator.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/ExprCXX.h"
+#include "clang/AST/ExprObjC.h"
+#include "clang/AST/TypeLoc.h"
+#include "llvm/Support/ErrorHandling.h"
+#include <map>
+using namespace clang;
+
+//===----------------------------------------------------------------------===//
+// Sema Initialization Checking
+//===----------------------------------------------------------------------===//
+
+static Expr *IsStringInit(Expr *Init, QualType DeclType, ASTContext &Context) {
+  const ArrayType *AT = Context.getAsArrayType(DeclType);
+  if (!AT) return 0;
+
+  if (!isa<ConstantArrayType>(AT) && !isa<IncompleteArrayType>(AT))
+    return 0;
+
+  // See if this is a string literal or @encode.
+  Init = Init->IgnoreParens();
+
+  // Handle @encode, which is a narrow string.
+  if (isa<ObjCEncodeExpr>(Init) && AT->getElementType()->isCharType())
+    return Init;
+
+  // Otherwise we can only handle string literals.
+  StringLiteral *SL = dyn_cast<StringLiteral>(Init);
+  if (SL == 0) return 0;
+
+  QualType ElemTy = Context.getCanonicalType(AT->getElementType());
+  // char array can be initialized with a narrow string.
+  // Only allow char x[] = "foo";  not char x[] = L"foo";
+  if (!SL->isWide())
+    return ElemTy->isCharType() ? Init : 0;
+
+  // wchar_t array can be initialized with a wide string: C99 6.7.8p15 (with
+  // correction from DR343): "An array with element type compatible with a
+  // qualified or unqualified version of wchar_t may be initialized by a wide
+  // string literal, optionally enclosed in braces."
+  if (Context.typesAreCompatible(Context.getWCharType(),
+                                 ElemTy.getUnqualifiedType()))
+    return Init;
+
+  return 0;
+}
+
+static void CheckStringInit(Expr *Str, QualType &DeclT, Sema &S) {
+  // Get the length of the string as parsed.
+  uint64_t StrLength =
+    cast<ConstantArrayType>(Str->getType())->getSize().getZExtValue();
+
+
+  const ArrayType *AT = S.Context.getAsArrayType(DeclT);
+  if (const IncompleteArrayType *IAT = dyn_cast<IncompleteArrayType>(AT)) {
+    // C99 6.7.8p14. We have an array of character type with unknown size
+    // being initialized to a string literal.
+    llvm::APSInt ConstVal(32);
+    ConstVal = StrLength;
+    // Return a new array type (C99 6.7.8p22).
+    DeclT = S.Context.getConstantArrayType(IAT->getElementType(),
+                                           ConstVal,
+                                           ArrayType::Normal, 0);
+    return;
+  }
+
+  const ConstantArrayType *CAT = cast<ConstantArrayType>(AT);
+
+  // C99 6.7.8p14. We have an array of character type with known size.  However,
+  // the size may be smaller or larger than the string we are initializing.
+  // FIXME: Avoid truncation for 64-bit length strings.
+  if (StrLength-1 > CAT->getSize().getZExtValue())
+    S.Diag(Str->getSourceRange().getBegin(),
+           diag::warn_initializer_string_for_char_array_too_long)
+      << Str->getSourceRange();
+
+  // Set the type to the actual size that we are initializing.  If we have
+  // something like:
+  //   char x[1] = "foo";
+  // then this will set the string literal's type to char[1].
+  Str->setType(DeclT);
+}
+
+//===----------------------------------------------------------------------===//
+// Semantic checking for initializer lists.
+//===----------------------------------------------------------------------===//
+
+/// @brief Semantic checking for initializer lists.
+///
+/// The InitListChecker class contains a set of routines that each
+/// handle the initialization of a certain kind of entity, e.g.,
+/// arrays, vectors, struct/union types, scalars, etc. The
+/// InitListChecker itself performs a recursive walk of the subobject
+/// structure of the type to be initialized, while stepping through
+/// the initializer list one element at a time. The IList and Index
+/// parameters to each of the Check* routines contain the active
+/// (syntactic) initializer list and the index into that initializer
+/// list that represents the current initializer. Each routine is
+/// responsible for moving that Index forward as it consumes elements.
+///
+/// Each Check* routine also has a StructuredList/StructuredIndex
+/// arguments, which contains the current the "structured" (semantic)
+/// initializer list and the index into that initializer list where we
+/// are copying initializers as we map them over to the semantic
+/// list. Once we have completed our recursive walk of the subobject
+/// structure, we will have constructed a full semantic initializer
+/// list.
+///
+/// C99 designators cause changes in the initializer list traversal,
+/// because they make the initialization "jump" into a specific
+/// subobject and then continue the initialization from that
+/// point. CheckDesignatedInitializer() recursively steps into the
+/// designated subobject and manages backing out the recursion to
+/// initialize the subobjects after the one designated.
+namespace {
+class InitListChecker {
+  Sema &SemaRef;
+  bool hadError;
+  std::map<InitListExpr *, InitListExpr *> SyntacticToSemantic;
+  InitListExpr *FullyStructuredList;
+
+  void CheckImplicitInitList(const InitializedEntity &Entity,
+                             InitListExpr *ParentIList, QualType T,
+                             unsigned &Index, InitListExpr *StructuredList,
+                             unsigned &StructuredIndex,
+                             bool TopLevelObject = false);
+  void CheckExplicitInitList(const InitializedEntity &Entity,
+                             InitListExpr *IList, QualType &T,
+                             unsigned &Index, InitListExpr *StructuredList,
+                             unsigned &StructuredIndex,
+                             bool TopLevelObject = false);
+  void CheckListElementTypes(const InitializedEntity &Entity,
+                             InitListExpr *IList, QualType &DeclType,
+                             bool SubobjectIsDesignatorContext,
+                             unsigned &Index,
+                             InitListExpr *StructuredList,
+                             unsigned &StructuredIndex,
+                             bool TopLevelObject = false);
+  void CheckSubElementType(const InitializedEntity &Entity,
+                           InitListExpr *IList, QualType ElemType,
+                           unsigned &Index,
+                           InitListExpr *StructuredList,
+                           unsigned &StructuredIndex);
+  void CheckScalarType(const InitializedEntity &Entity,
+                       InitListExpr *IList, QualType DeclType,
+                       unsigned &Index,
+                       InitListExpr *StructuredList,
+                       unsigned &StructuredIndex);
+  void CheckReferenceType(const InitializedEntity &Entity,
+                          InitListExpr *IList, QualType DeclType,
+                          unsigned &Index,
+                          InitListExpr *StructuredList,
+                          unsigned &StructuredIndex);
+  void CheckVectorType(const InitializedEntity &Entity,
+                       InitListExpr *IList, QualType DeclType, unsigned &Index,
+                       InitListExpr *StructuredList,
+                       unsigned &StructuredIndex);
+  void CheckStructUnionTypes(const InitializedEntity &Entity,
+                             InitListExpr *IList, QualType DeclType,
+                             RecordDecl::field_iterator Field,
+                             bool SubobjectIsDesignatorContext, unsigned &Index,
+                             InitListExpr *StructuredList,
+                             unsigned &StructuredIndex,
+                             bool TopLevelObject = false);
+  void CheckArrayType(const InitializedEntity &Entity,
+                      InitListExpr *IList, QualType &DeclType,
+                      llvm::APSInt elementIndex,
+                      bool SubobjectIsDesignatorContext, unsigned &Index,
+                      InitListExpr *StructuredList,
+                      unsigned &StructuredIndex);
+  bool CheckDesignatedInitializer(const InitializedEntity &Entity,
+                                  InitListExpr *IList, DesignatedInitExpr *DIE,
+                                  unsigned DesigIdx,
+                                  QualType &CurrentObjectType,
+                                  RecordDecl::field_iterator *NextField,
+                                  llvm::APSInt *NextElementIndex,
+                                  unsigned &Index,
+                                  InitListExpr *StructuredList,
+                                  unsigned &StructuredIndex,
+                                  bool FinishSubobjectInit,
+                                  bool TopLevelObject);
+  InitListExpr *getStructuredSubobjectInit(InitListExpr *IList, unsigned Index,
+                                           QualType CurrentObjectType,
+                                           InitListExpr *StructuredList,
+                                           unsigned StructuredIndex,
+                                           SourceRange InitRange);
+  void UpdateStructuredListElement(InitListExpr *StructuredList,
+                                   unsigned &StructuredIndex,
+                                   Expr *expr);
+  int numArrayElements(QualType DeclType);
+  int numStructUnionElements(QualType DeclType);
+
+  void FillInValueInitForField(unsigned Init, FieldDecl *Field,
+                               const InitializedEntity &ParentEntity,
+                               InitListExpr *ILE, bool &RequiresSecondPass);
+  void FillInValueInitializations(const InitializedEntity &Entity,
+                                  InitListExpr *ILE, bool &RequiresSecondPass);
+public:
+  InitListChecker(Sema &S, const InitializedEntity &Entity,
+                  InitListExpr *IL, QualType &T);
+  bool HadError() { return hadError; }
+
+  // @brief Retrieves the fully-structured initializer list used for
+  // semantic analysis and code generation.
+  InitListExpr *getFullyStructuredList() const { return FullyStructuredList; }
+};
+} // end anonymous namespace
+
+void InitListChecker::FillInValueInitForField(unsigned Init, FieldDecl *Field,
+                                        const InitializedEntity &ParentEntity,
+                                              InitListExpr *ILE, 
+                                              bool &RequiresSecondPass) {
+  SourceLocation Loc = ILE->getSourceRange().getBegin();
+  unsigned NumInits = ILE->getNumInits();
+  InitializedEntity MemberEntity 
+    = InitializedEntity::InitializeMember(Field, &ParentEntity);
+  if (Init >= NumInits || !ILE->getInit(Init)) {
+    // FIXME: We probably don't need to handle references
+    // specially here, since value-initialization of references is
+    // handled in InitializationSequence.
+    if (Field->getType()->isReferenceType()) {
+      // C++ [dcl.init.aggr]p9:
+      //   If an incomplete or empty initializer-list leaves a
+      //   member of reference type uninitialized, the program is
+      //   ill-formed.
+      SemaRef.Diag(Loc, diag::err_init_reference_member_uninitialized)
+        << Field->getType()
+        << ILE->getSyntacticForm()->getSourceRange();
+      SemaRef.Diag(Field->getLocation(),
+                   diag::note_uninit_reference_member);
+      hadError = true;
+      return;
+    }
+    
+    InitializationKind Kind = InitializationKind::CreateValue(Loc, Loc, Loc,
+                                                              true);
+    InitializationSequence InitSeq(SemaRef, MemberEntity, Kind, 0, 0);
+    if (!InitSeq) {
+      InitSeq.Diagnose(SemaRef, MemberEntity, Kind, 0, 0);
+      hadError = true;
+      return;
+    }
+    
+    Sema::OwningExprResult MemberInit
+      = InitSeq.Perform(SemaRef, MemberEntity, Kind, 
+                        Sema::MultiExprArg(SemaRef, 0, 0));
+    if (MemberInit.isInvalid()) {
+      hadError = true;
+      return;
+    }
+    
+    if (hadError) {
+      // Do nothing
+    } else if (Init < NumInits) {
+      ILE->setInit(Init, MemberInit.takeAs<Expr>());
+    } else if (InitSeq.getKind()
+                 == InitializationSequence::ConstructorInitialization) {
+      // Value-initialization requires a constructor call, so
+      // extend the initializer list to include the constructor
+      // call and make a note that we'll need to take another pass
+      // through the initializer list.
+      ILE->updateInit(Init, MemberInit.takeAs<Expr>());
+      RequiresSecondPass = true;
+    }
+  } else if (InitListExpr *InnerILE
+               = dyn_cast<InitListExpr>(ILE->getInit(Init)))
+    FillInValueInitializations(MemberEntity, InnerILE, 
+                               RequiresSecondPass);  
+}
+
+/// Recursively replaces NULL values within the given initializer list
+/// with expressions that perform value-initialization of the
+/// appropriate type.
+void 
+InitListChecker::FillInValueInitializations(const InitializedEntity &Entity,
+                                            InitListExpr *ILE,
+                                            bool &RequiresSecondPass) {
+  assert((ILE->getType() != SemaRef.Context.VoidTy) &&
+         "Should not have void type");
+  SourceLocation Loc = ILE->getSourceRange().getBegin();
+  if (ILE->getSyntacticForm())
+    Loc = ILE->getSyntacticForm()->getSourceRange().getBegin();
+
+  if (const RecordType *RType = ILE->getType()->getAs<RecordType>()) {
+    if (RType->getDecl()->isUnion() &&
+        ILE->getInitializedFieldInUnion())
+      FillInValueInitForField(0, ILE->getInitializedFieldInUnion(),
+                              Entity, ILE, RequiresSecondPass);
+    else {
+      unsigned Init = 0;
+      for (RecordDecl::field_iterator
+             Field = RType->getDecl()->field_begin(),
+             FieldEnd = RType->getDecl()->field_end();
+           Field != FieldEnd; ++Field) {
+        if (Field->isUnnamedBitfield())
+          continue;
+
+        if (hadError)
+          return;
+
+        FillInValueInitForField(Init, *Field, Entity, ILE, RequiresSecondPass);
+        if (hadError)
+          return;
+
+        ++Init;
+
+        // Only look at the first initialization of a union.
+        if (RType->getDecl()->isUnion())
+          break;
+      }
+    }
+
+    return;
+  }
+
+  QualType ElementType;
+
+  InitializedEntity ElementEntity = Entity;
+  unsigned NumInits = ILE->getNumInits();
+  unsigned NumElements = NumInits;
+  if (const ArrayType *AType = SemaRef.Context.getAsArrayType(ILE->getType())) {
+    ElementType = AType->getElementType();
+    if (const ConstantArrayType *CAType = dyn_cast<ConstantArrayType>(AType))
+      NumElements = CAType->getSize().getZExtValue();
+    ElementEntity = InitializedEntity::InitializeElement(SemaRef.Context, 
+                                                         0, Entity);
+  } else if (const VectorType *VType = ILE->getType()->getAs<VectorType>()) {
+    ElementType = VType->getElementType();
+    NumElements = VType->getNumElements();
+    ElementEntity = InitializedEntity::InitializeElement(SemaRef.Context, 
+                                                         0, Entity);
+  } else
+    ElementType = ILE->getType();
+
+  
+  for (unsigned Init = 0; Init != NumElements; ++Init) {
+    if (hadError)
+      return;
+
+    if (ElementEntity.getKind() == InitializedEntity::EK_ArrayElement ||
+        ElementEntity.getKind() == InitializedEntity::EK_VectorElement)
+      ElementEntity.setElementIndex(Init);
+
+    if (Init >= NumInits || !ILE->getInit(Init)) {
+      InitializationKind Kind = InitializationKind::CreateValue(Loc, Loc, Loc,
+                                                                true);
+      InitializationSequence InitSeq(SemaRef, ElementEntity, Kind, 0, 0);
+      if (!InitSeq) {
+        InitSeq.Diagnose(SemaRef, ElementEntity, Kind, 0, 0);
+        hadError = true;
+        return;
+      }
+
+      Sema::OwningExprResult ElementInit
+        = InitSeq.Perform(SemaRef, ElementEntity, Kind, 
+                          Sema::MultiExprArg(SemaRef, 0, 0));
+      if (ElementInit.isInvalid()) {
+        hadError = true;
+        return;
+      }
+
+      if (hadError) {
+        // Do nothing
+      } else if (Init < NumInits) {
+        ILE->setInit(Init, ElementInit.takeAs<Expr>());
+      } else if (InitSeq.getKind()
+                   == InitializationSequence::ConstructorInitialization) {
+        // Value-initialization requires a constructor call, so
+        // extend the initializer list to include the constructor
+        // call and make a note that we'll need to take another pass
+        // through the initializer list.
+        ILE->updateInit(Init, ElementInit.takeAs<Expr>());
+        RequiresSecondPass = true;
+      }
+    } else if (InitListExpr *InnerILE
+                 = dyn_cast<InitListExpr>(ILE->getInit(Init)))
+      FillInValueInitializations(ElementEntity, InnerILE, RequiresSecondPass);
+  }
+}
+
+
+InitListChecker::InitListChecker(Sema &S, const InitializedEntity &Entity,
+                                 InitListExpr *IL, QualType &T)
+  : SemaRef(S) {
+  hadError = false;
+
+  unsigned newIndex = 0;
+  unsigned newStructuredIndex = 0;
+  FullyStructuredList
+    = getStructuredSubobjectInit(IL, newIndex, T, 0, 0, IL->getSourceRange());
+  CheckExplicitInitList(Entity, IL, T, newIndex, 
+                        FullyStructuredList, newStructuredIndex,
+                        /*TopLevelObject=*/true);
+
+  if (!hadError) {
+    bool RequiresSecondPass = false;
+    FillInValueInitializations(Entity, FullyStructuredList, RequiresSecondPass);
+    if (RequiresSecondPass && !hadError)
+      FillInValueInitializations(Entity, FullyStructuredList, 
+                                 RequiresSecondPass);
+  }
+}
+
+int InitListChecker::numArrayElements(QualType DeclType) {
+  // FIXME: use a proper constant
+  int maxElements = 0x7FFFFFFF;
+  if (const ConstantArrayType *CAT =
+        SemaRef.Context.getAsConstantArrayType(DeclType)) {
+    maxElements = static_cast<int>(CAT->getSize().getZExtValue());
+  }
+  return maxElements;
+}
+
+int InitListChecker::numStructUnionElements(QualType DeclType) {
+  RecordDecl *structDecl = DeclType->getAs<RecordType>()->getDecl();
+  int InitializableMembers = 0;
+  for (RecordDecl::field_iterator
+         Field = structDecl->field_begin(),
+         FieldEnd = structDecl->field_end();
+       Field != FieldEnd; ++Field) {
+    if ((*Field)->getIdentifier() || !(*Field)->isBitField())
+      ++InitializableMembers;
+  }
+  if (structDecl->isUnion())
+    return std::min(InitializableMembers, 1);
+  return InitializableMembers - structDecl->hasFlexibleArrayMember();
+}
+
+void InitListChecker::CheckImplicitInitList(const InitializedEntity &Entity,
+                                            InitListExpr *ParentIList,
+                                            QualType T, unsigned &Index,
+                                            InitListExpr *StructuredList,
+                                            unsigned &StructuredIndex,
+                                            bool TopLevelObject) {
+  int maxElements = 0;
+
+  if (T->isArrayType())
+    maxElements = numArrayElements(T);
+  else if (T->isStructureType() || T->isUnionType())
+    maxElements = numStructUnionElements(T);
+  else if (T->isVectorType())
+    maxElements = T->getAs<VectorType>()->getNumElements();
+  else
+    assert(0 && "CheckImplicitInitList(): Illegal type");
+
+  if (maxElements == 0) {
+    SemaRef.Diag(ParentIList->getInit(Index)->getLocStart(),
+                  diag::err_implicit_empty_initializer);
+    ++Index;
+    hadError = true;
+    return;
+  }
+
+  // Build a structured initializer list corresponding to this subobject.
+  InitListExpr *StructuredSubobjectInitList
+    = getStructuredSubobjectInit(ParentIList, Index, T, StructuredList,
+                                 StructuredIndex,
+          SourceRange(ParentIList->getInit(Index)->getSourceRange().getBegin(),
+                      ParentIList->getSourceRange().getEnd()));
+  unsigned StructuredSubobjectInitIndex = 0;
+
+  // Check the element types and build the structural subobject.
+  unsigned StartIndex = Index;
+  CheckListElementTypes(Entity, ParentIList, T, 
+                        /*SubobjectIsDesignatorContext=*/false, Index,
+                        StructuredSubobjectInitList,
+                        StructuredSubobjectInitIndex,
+                        TopLevelObject);
+  unsigned EndIndex = (Index == StartIndex? StartIndex : Index - 1);
+  StructuredSubobjectInitList->setType(T);
+
+  // Update the structured sub-object initializer so that it's ending
+  // range corresponds with the end of the last initializer it used.
+  if (EndIndex < ParentIList->getNumInits()) {
+    SourceLocation EndLoc
+      = ParentIList->getInit(EndIndex)->getSourceRange().getEnd();
+    StructuredSubobjectInitList->setRBraceLoc(EndLoc);
+  }
+}
+
+void InitListChecker::CheckExplicitInitList(const InitializedEntity &Entity,
+                                            InitListExpr *IList, QualType &T,
+                                            unsigned &Index,
+                                            InitListExpr *StructuredList,
+                                            unsigned &StructuredIndex,
+                                            bool TopLevelObject) {
+  assert(IList->isExplicit() && "Illegal Implicit InitListExpr");
+  SyntacticToSemantic[IList] = StructuredList;
+  StructuredList->setSyntacticForm(IList);
+  CheckListElementTypes(Entity, IList, T, /*SubobjectIsDesignatorContext=*/true, 
+                        Index, StructuredList, StructuredIndex, TopLevelObject);
+  IList->setType(T.getNonReferenceType());
+  StructuredList->setType(T.getNonReferenceType());
+  if (hadError)
+    return;
+
+  if (Index < IList->getNumInits()) {
+    // We have leftover initializers
+    if (StructuredIndex == 1 &&
+        IsStringInit(StructuredList->getInit(0), T, SemaRef.Context)) {
+      unsigned DK = diag::warn_excess_initializers_in_char_array_initializer;
+      if (SemaRef.getLangOptions().CPlusPlus) {
+        DK = diag::err_excess_initializers_in_char_array_initializer;
+        hadError = true;
+      }
+      // Special-case
+      SemaRef.Diag(IList->getInit(Index)->getLocStart(), DK)
+        << IList->getInit(Index)->getSourceRange();
+    } else if (!T->isIncompleteType()) {
+      // Don't complain for incomplete types, since we'll get an error
+      // elsewhere
+      QualType CurrentObjectType = StructuredList->getType();
+      int initKind =
+        CurrentObjectType->isArrayType()? 0 :
+        CurrentObjectType->isVectorType()? 1 :
+        CurrentObjectType->isScalarType()? 2 :
+        CurrentObjectType->isUnionType()? 3 :
+        4;
+
+      unsigned DK = diag::warn_excess_initializers;
+      if (SemaRef.getLangOptions().CPlusPlus) {
+        DK = diag::err_excess_initializers;
+        hadError = true;
+      }
+      if (SemaRef.getLangOptions().OpenCL && initKind == 1) {
+        DK = diag::err_excess_initializers;
+        hadError = true;
+      }
+
+      SemaRef.Diag(IList->getInit(Index)->getLocStart(), DK)
+        << initKind << IList->getInit(Index)->getSourceRange();
+    }
+  }
+
+  if (T->isScalarType() && !TopLevelObject)
+    SemaRef.Diag(IList->getLocStart(), diag::warn_braces_around_scalar_init)
+      << IList->getSourceRange()
+      << CodeModificationHint::CreateRemoval(IList->getLocStart())
+      << CodeModificationHint::CreateRemoval(IList->getLocEnd());
+}
+
+void InitListChecker::CheckListElementTypes(const InitializedEntity &Entity,
+                                            InitListExpr *IList,
+                                            QualType &DeclType,
+                                            bool SubobjectIsDesignatorContext,
+                                            unsigned &Index,
+                                            InitListExpr *StructuredList,
+                                            unsigned &StructuredIndex,
+                                            bool TopLevelObject) {
+  if (DeclType->isScalarType()) {
+    CheckScalarType(Entity, IList, DeclType, Index,
+                    StructuredList, StructuredIndex);
+  } else if (DeclType->isVectorType()) {
+    CheckVectorType(Entity, IList, DeclType, Index, 
+                    StructuredList, StructuredIndex);
+  } else if (DeclType->isAggregateType()) {
+    if (DeclType->isRecordType()) {
+      RecordDecl *RD = DeclType->getAs<RecordType>()->getDecl();
+      CheckStructUnionTypes(Entity, IList, DeclType, RD->field_begin(),
+                            SubobjectIsDesignatorContext, Index,
+                            StructuredList, StructuredIndex,
+                            TopLevelObject);
+    } else if (DeclType->isArrayType()) {
+      llvm::APSInt Zero(
+                      SemaRef.Context.getTypeSize(SemaRef.Context.getSizeType()),
+                      false);
+      CheckArrayType(Entity, IList, DeclType, Zero, 
+                     SubobjectIsDesignatorContext, Index,
+                     StructuredList, StructuredIndex);
+    } else
+      assert(0 && "Aggregate that isn't a structure or array?!");
+  } else if (DeclType->isVoidType() || DeclType->isFunctionType()) {
+    // This type is invalid, issue a diagnostic.
+    ++Index;
+    SemaRef.Diag(IList->getLocStart(), diag::err_illegal_initializer_type)
+      << DeclType;
+    hadError = true;
+  } else if (DeclType->isRecordType()) {
+    // C++ [dcl.init]p14:
+    //   [...] If the class is an aggregate (8.5.1), and the initializer
+    //   is a brace-enclosed list, see 8.5.1.
+    //
+    // Note: 8.5.1 is handled below; here, we diagnose the case where
+    // we have an initializer list and a destination type that is not
+    // an aggregate.
+    // FIXME: In C++0x, this is yet another form of initialization.
+    SemaRef.Diag(IList->getLocStart(), diag::err_init_non_aggr_init_list)
+      << DeclType << IList->getSourceRange();
+    hadError = true;
+  } else if (DeclType->isReferenceType()) {
+    CheckReferenceType(Entity, IList, DeclType, Index,
+                       StructuredList, StructuredIndex);
+  } else {
+    // In C, all types are either scalars or aggregates, but
+    // additional handling is needed here for C++ (and possibly others?).
+    assert(0 && "Unsupported initializer type");
+  }
+}
+
+void InitListChecker::CheckSubElementType(const InitializedEntity &Entity,
+                                          InitListExpr *IList,
+                                          QualType ElemType,
+                                          unsigned &Index,
+                                          InitListExpr *StructuredList,
+                                          unsigned &StructuredIndex) {
+  Expr *expr = IList->getInit(Index);
+  if (InitListExpr *SubInitList = dyn_cast<InitListExpr>(expr)) {
+    unsigned newIndex = 0;
+    unsigned newStructuredIndex = 0;
+    InitListExpr *newStructuredList
+      = getStructuredSubobjectInit(IList, Index, ElemType,
+                                   StructuredList, StructuredIndex,
+                                   SubInitList->getSourceRange());
+    CheckExplicitInitList(Entity, SubInitList, ElemType, newIndex,
+                          newStructuredList, newStructuredIndex);
+    ++StructuredIndex;
+    ++Index;
+  } else if (Expr *Str = IsStringInit(expr, ElemType, SemaRef.Context)) {
+    CheckStringInit(Str, ElemType, SemaRef);
+    UpdateStructuredListElement(StructuredList, StructuredIndex, Str);
+    ++Index;
+  } else if (ElemType->isScalarType()) {
+    CheckScalarType(Entity, IList, ElemType, Index, 
+                    StructuredList, StructuredIndex);
+  } else if (ElemType->isReferenceType()) {
+    CheckReferenceType(Entity, IList, ElemType, Index,
+                       StructuredList, StructuredIndex);
+  } else {
+    if (SemaRef.getLangOptions().CPlusPlus) {
+      // C++ [dcl.init.aggr]p12:
+      //   All implicit type conversions (clause 4) are considered when
+      //   initializing the aggregate member with an ini- tializer from
+      //   an initializer-list. If the initializer can initialize a
+      //   member, the member is initialized. [...]
+
+      // FIXME: Better EqualLoc?
+      InitializationKind Kind = 
+        InitializationKind::CreateCopy(expr->getLocStart(), SourceLocation());
+      InitializationSequence Seq(SemaRef, Entity, Kind, &expr, 1);
+      
+      if (Seq) {
+        Sema::OwningExprResult Result = 
+          Seq.Perform(SemaRef, Entity, Kind,
+                      Sema::MultiExprArg(SemaRef, (void **)&expr, 1));
+        if (Result.isInvalid())
+          hadError = true;
+        
+        UpdateStructuredListElement(StructuredList, StructuredIndex, 
+                                    Result.takeAs<Expr>());
+        ++Index;
+        return;
+      }
+
+      // Fall through for subaggregate initialization
+    } else {
+      // C99 6.7.8p13:
+      //
+      //   The initializer for a structure or union object that has
+      //   automatic storage duration shall be either an initializer
+      //   list as described below, or a single expression that has
+      //   compatible structure or union type. In the latter case, the
+      //   initial value of the object, including unnamed members, is
+      //   that of the expression.
+      if ((ElemType->isRecordType() || ElemType->isVectorType()) &&
+          SemaRef.Context.hasSameUnqualifiedType(expr->getType(), ElemType)) {
+        UpdateStructuredListElement(StructuredList, StructuredIndex, expr);
+        ++Index;
+        return;
+      }
+
+      // Fall through for subaggregate initialization
+    }
+
+    // C++ [dcl.init.aggr]p12:
+    //
+    //   [...] Otherwise, if the member is itself a non-empty
+    //   subaggregate, brace elision is assumed and the initializer is
+    //   considered for the initialization of the first member of
+    //   the subaggregate.
+    if (ElemType->isAggregateType() || ElemType->isVectorType()) {
+      CheckImplicitInitList(Entity, IList, ElemType, Index, StructuredList,
+                            StructuredIndex);
+      ++StructuredIndex;
+    } else {
+      // We cannot initialize this element, so let
+      // PerformCopyInitialization produce the appropriate diagnostic.
+      SemaRef.PerformCopyInitialization(Entity, SourceLocation(), 
+                                        SemaRef.Owned(expr));
+      IList->setInit(Index, 0);
+      hadError = true;
+      ++Index;
+      ++StructuredIndex;
+    }
+  }
+}
+
+void InitListChecker::CheckScalarType(const InitializedEntity &Entity,
+                                      InitListExpr *IList, QualType DeclType,
+                                      unsigned &Index,
+                                      InitListExpr *StructuredList,
+                                      unsigned &StructuredIndex) {
+  if (Index < IList->getNumInits()) {
+    Expr *expr = IList->getInit(Index);
+    if (isa<InitListExpr>(expr)) {
+      SemaRef.Diag(IList->getLocStart(),
+                    diag::err_many_braces_around_scalar_init)
+        << IList->getSourceRange();
+      hadError = true;
+      ++Index;
+      ++StructuredIndex;
+      return;
+    } else if (isa<DesignatedInitExpr>(expr)) {
+      SemaRef.Diag(expr->getSourceRange().getBegin(),
+                    diag::err_designator_for_scalar_init)
+        << DeclType << expr->getSourceRange();
+      hadError = true;
+      ++Index;
+      ++StructuredIndex;
+      return;
+    }
+
+    Sema::OwningExprResult Result =
+      SemaRef.PerformCopyInitialization(Entity, expr->getLocStart(),
+                                        SemaRef.Owned(expr));
+
+    Expr *ResultExpr;
+
+    if (Result.isInvalid())
+      hadError = true; // types weren't compatible.
+    else {
+      ResultExpr = Result.takeAs<Expr>();
+      
+      if (ResultExpr != expr) {
+        // The type was promoted, update initializer list.
+        IList->setInit(Index, ResultExpr);
+      }
+    }
+    if (hadError)
+      ++StructuredIndex;
+    else
+      UpdateStructuredListElement(StructuredList, StructuredIndex, ResultExpr);
+    ++Index;
+  } else {
+    SemaRef.Diag(IList->getLocStart(), diag::err_empty_scalar_initializer)
+      << IList->getSourceRange();
+    hadError = true;
+    ++Index;
+    ++StructuredIndex;
+    return;
+  }
+}
+
+void InitListChecker::CheckReferenceType(const InitializedEntity &Entity,
+                                         InitListExpr *IList, QualType DeclType,
+                                         unsigned &Index,
+                                         InitListExpr *StructuredList,
+                                         unsigned &StructuredIndex) {
+  if (Index < IList->getNumInits()) {
+    Expr *expr = IList->getInit(Index);
+    if (isa<InitListExpr>(expr)) {
+      SemaRef.Diag(IList->getLocStart(), diag::err_init_non_aggr_init_list)
+        << DeclType << IList->getSourceRange();
+      hadError = true;
+      ++Index;
+      ++StructuredIndex;
+      return;
+    }
+
+    Sema::OwningExprResult Result =
+      SemaRef.PerformCopyInitialization(Entity, expr->getLocStart(),
+                                        SemaRef.Owned(expr));
+
+    if (Result.isInvalid())
+      hadError = true;
+
+    expr = Result.takeAs<Expr>();
+    IList->setInit(Index, expr);
+
+    if (hadError)
+      ++StructuredIndex;
+    else
+      UpdateStructuredListElement(StructuredList, StructuredIndex, expr);
+    ++Index;
+  } else {
+    // FIXME: It would be wonderful if we could point at the actual member. In
+    // general, it would be useful to pass location information down the stack,
+    // so that we know the location (or decl) of the "current object" being
+    // initialized.
+    SemaRef.Diag(IList->getLocStart(),
+                  diag::err_init_reference_member_uninitialized)
+      << DeclType
+      << IList->getSourceRange();
+    hadError = true;
+    ++Index;
+    ++StructuredIndex;
+    return;
+  }
+}
+
+void InitListChecker::CheckVectorType(const InitializedEntity &Entity,
+                                      InitListExpr *IList, QualType DeclType,
+                                      unsigned &Index,
+                                      InitListExpr *StructuredList,
+                                      unsigned &StructuredIndex) {
+  if (Index < IList->getNumInits()) {
+    const VectorType *VT = DeclType->getAs<VectorType>();
+    unsigned maxElements = VT->getNumElements();
+    unsigned numEltsInit = 0;
+    QualType elementType = VT->getElementType();
+
+    if (!SemaRef.getLangOptions().OpenCL) {
+      InitializedEntity ElementEntity =
+        InitializedEntity::InitializeElement(SemaRef.Context, 0, Entity);
+
+      for (unsigned i = 0; i < maxElements; ++i, ++numEltsInit) {
+        // Don't attempt to go past the end of the init list
+        if (Index >= IList->getNumInits())
+          break;
+        
+        ElementEntity.setElementIndex(Index);
+        CheckSubElementType(ElementEntity, IList, elementType, Index,
+                            StructuredList, StructuredIndex);
+      }
+    } else {
+      InitializedEntity ElementEntity =
+        InitializedEntity::InitializeElement(SemaRef.Context, 0, Entity);
+      
+      // OpenCL initializers allows vectors to be constructed from vectors.
+      for (unsigned i = 0; i < maxElements; ++i) {
+        // Don't attempt to go past the end of the init list
+        if (Index >= IList->getNumInits())
+          break;
+        
+        ElementEntity.setElementIndex(Index);
+
+        QualType IType = IList->getInit(Index)->getType();
+        if (!IType->isVectorType()) {
+          CheckSubElementType(ElementEntity, IList, elementType, Index,
+                              StructuredList, StructuredIndex);
+          ++numEltsInit;
+        } else {
+          const VectorType *IVT = IType->getAs<VectorType>();
+          unsigned numIElts = IVT->getNumElements();
+          QualType VecType = SemaRef.Context.getExtVectorType(elementType,
+                                                              numIElts);
+          CheckSubElementType(ElementEntity, IList, VecType, Index,
+                              StructuredList, StructuredIndex);
+          numEltsInit += numIElts;
+        }
+      }
+    }
+
+    // OpenCL & AltiVec require all elements to be initialized.
+    if (numEltsInit != maxElements)
+      if (SemaRef.getLangOptions().OpenCL || SemaRef.getLangOptions().AltiVec)
+        SemaRef.Diag(IList->getSourceRange().getBegin(),
+                     diag::err_vector_incorrect_num_initializers)
+          << (numEltsInit < maxElements) << maxElements << numEltsInit;
+  }
+}
+
+void InitListChecker::CheckArrayType(const InitializedEntity &Entity,
+                                     InitListExpr *IList, QualType &DeclType,
+                                     llvm::APSInt elementIndex,
+                                     bool SubobjectIsDesignatorContext,
+                                     unsigned &Index,
+                                     InitListExpr *StructuredList,
+                                     unsigned &StructuredIndex) {
+  // Check for the special-case of initializing an array with a string.
+  if (Index < IList->getNumInits()) {
+    if (Expr *Str = IsStringInit(IList->getInit(Index), DeclType,
+                                 SemaRef.Context)) {
+      CheckStringInit(Str, DeclType, SemaRef);
+      // We place the string literal directly into the resulting
+      // initializer list. This is the only place where the structure
+      // of the structured initializer list doesn't match exactly,
+      // because doing so would involve allocating one character
+      // constant for each string.
+      UpdateStructuredListElement(StructuredList, StructuredIndex, Str);
+      StructuredList->resizeInits(SemaRef.Context, StructuredIndex);
+      ++Index;
+      return;
+    }
+  }
+  if (const VariableArrayType *VAT =
+        SemaRef.Context.getAsVariableArrayType(DeclType)) {
+    // Check for VLAs; in standard C it would be possible to check this
+    // earlier, but I don't know where clang accepts VLAs (gcc accepts
+    // them in all sorts of strange places).
+    SemaRef.Diag(VAT->getSizeExpr()->getLocStart(),
+                  diag::err_variable_object_no_init)
+      << VAT->getSizeExpr()->getSourceRange();
+    hadError = true;
+    ++Index;
+    ++StructuredIndex;
+    return;
+  }
+
+  // We might know the maximum number of elements in advance.
+  llvm::APSInt maxElements(elementIndex.getBitWidth(),
+                           elementIndex.isUnsigned());
+  bool maxElementsKnown = false;
+  if (const ConstantArrayType *CAT =
+        SemaRef.Context.getAsConstantArrayType(DeclType)) {
+    maxElements = CAT->getSize();
+    elementIndex.extOrTrunc(maxElements.getBitWidth());
+    elementIndex.setIsUnsigned(maxElements.isUnsigned());
+    maxElementsKnown = true;
+  }
+
+  QualType elementType = SemaRef.Context.getAsArrayType(DeclType)
+                             ->getElementType();
+  while (Index < IList->getNumInits()) {
+    Expr *Init = IList->getInit(Index);
+    if (DesignatedInitExpr *DIE = dyn_cast<DesignatedInitExpr>(Init)) {
+      // If we're not the subobject that matches up with the '{' for
+      // the designator, we shouldn't be handling the
+      // designator. Return immediately.
+      if (!SubobjectIsDesignatorContext)
+        return;
+
+      // Handle this designated initializer. elementIndex will be
+      // updated to be the next array element we'll initialize.
+      if (CheckDesignatedInitializer(Entity, IList, DIE, 0,
+                                     DeclType, 0, &elementIndex, Index,
+                                     StructuredList, StructuredIndex, true,
+                                     false)) {
+        hadError = true;
+        continue;
+      }
+
+      if (elementIndex.getBitWidth() > maxElements.getBitWidth())
+        maxElements.extend(elementIndex.getBitWidth());
+      else if (elementIndex.getBitWidth() < maxElements.getBitWidth())
+        elementIndex.extend(maxElements.getBitWidth());
+      elementIndex.setIsUnsigned(maxElements.isUnsigned());
+
+      // If the array is of incomplete type, keep track of the number of
+      // elements in the initializer.
+      if (!maxElementsKnown && elementIndex > maxElements)
+        maxElements = elementIndex;
+
+      continue;
+    }
+
+    // If we know the maximum number of elements, and we've already
+    // hit it, stop consuming elements in the initializer list.
+    if (maxElementsKnown && elementIndex == maxElements)
+      break;
+
+    InitializedEntity ElementEntity =
+      InitializedEntity::InitializeElement(SemaRef.Context, StructuredIndex, 
+                                           Entity);
+    // Check this element.
+    CheckSubElementType(ElementEntity, IList, elementType, Index,
+                        StructuredList, StructuredIndex);
+    ++elementIndex;
+
+    // If the array is of incomplete type, keep track of the number of
+    // elements in the initializer.
+    if (!maxElementsKnown && elementIndex > maxElements)
+      maxElements = elementIndex;
+  }
+  if (!hadError && DeclType->isIncompleteArrayType()) {
+    // If this is an incomplete array type, the actual type needs to
+    // be calculated here.
+    llvm::APSInt Zero(maxElements.getBitWidth(), maxElements.isUnsigned());
+    if (maxElements == Zero) {
+      // Sizing an array implicitly to zero is not allowed by ISO C,
+      // but is supported by GNU.
+      SemaRef.Diag(IList->getLocStart(),
+                    diag::ext_typecheck_zero_array_size);
+    }
+
+    DeclType = SemaRef.Context.getConstantArrayType(elementType, maxElements,
+                                                     ArrayType::Normal, 0);
+  }
+}
+
+void InitListChecker::CheckStructUnionTypes(const InitializedEntity &Entity,
+                                            InitListExpr *IList,
+                                            QualType DeclType,
+                                            RecordDecl::field_iterator Field,
+                                            bool SubobjectIsDesignatorContext,
+                                            unsigned &Index,
+                                            InitListExpr *StructuredList,
+                                            unsigned &StructuredIndex,
+                                            bool TopLevelObject) {
+  RecordDecl* structDecl = DeclType->getAs<RecordType>()->getDecl();
+
+  // If the record is invalid, some of it's members are invalid. To avoid
+  // confusion, we forgo checking the intializer for the entire record.
+  if (structDecl->isInvalidDecl()) {
+    hadError = true;
+    return;
+  }
+
+  if (DeclType->isUnionType() && IList->getNumInits() == 0) {
+    // Value-initialize the first named member of the union.
+    RecordDecl *RD = DeclType->getAs<RecordType>()->getDecl();
+    for (RecordDecl::field_iterator FieldEnd = RD->field_end();
+         Field != FieldEnd; ++Field) {
+      if (Field->getDeclName()) {
+        StructuredList->setInitializedFieldInUnion(*Field);
+        break;
+      }
+    }
+    return;
+  }
+
+  // If structDecl is a forward declaration, this loop won't do
+  // anything except look at designated initializers; That's okay,
+  // because an error should get printed out elsewhere. It might be
+  // worthwhile to skip over the rest of the initializer, though.
+  RecordDecl *RD = DeclType->getAs<RecordType>()->getDecl();
+  RecordDecl::field_iterator FieldEnd = RD->field_end();
+  bool InitializedSomething = false;
+  while (Index < IList->getNumInits()) {
+    Expr *Init = IList->getInit(Index);
+
+    if (DesignatedInitExpr *DIE = dyn_cast<DesignatedInitExpr>(Init)) {
+      // If we're not the subobject that matches up with the '{' for
+      // the designator, we shouldn't be handling the
+      // designator. Return immediately.
+      if (!SubobjectIsDesignatorContext)
+        return;
+
+      // Handle this designated initializer. Field will be updated to
+      // the next field that we'll be initializing.
+      if (CheckDesignatedInitializer(Entity, IList, DIE, 0,
+                                     DeclType, &Field, 0, Index,
+                                     StructuredList, StructuredIndex,
+                                     true, TopLevelObject))
+        hadError = true;
+
+      InitializedSomething = true;
+      continue;
+    }
+
+    if (Field == FieldEnd) {
+      // We've run out of fields. We're done.
+      break;
+    }
+
+    // We've already initialized a member of a union. We're done.
+    if (InitializedSomething && DeclType->isUnionType())
+      break;
+
+    // If we've hit the flexible array member at the end, we're done.
+    if (Field->getType()->isIncompleteArrayType())
+      break;
+
+    if (Field->isUnnamedBitfield()) {
+      // Don't initialize unnamed bitfields, e.g. "int : 20;"
+      ++Field;
+      continue;
+    }
+
+    InitializedEntity MemberEntity =
+      InitializedEntity::InitializeMember(*Field, &Entity);
+    CheckSubElementType(MemberEntity, IList, Field->getType(), Index,
+                        StructuredList, StructuredIndex);
+    InitializedSomething = true;
+
+    if (DeclType->isUnionType()) {
+      // Initialize the first field within the union.
+      StructuredList->setInitializedFieldInUnion(*Field);
+    }
+
+    ++Field;
+  }
+
+  if (Field == FieldEnd || !Field->getType()->isIncompleteArrayType() ||
+      Index >= IList->getNumInits())
+    return;
+
+  // Handle GNU flexible array initializers.
+  if (!TopLevelObject &&
+      (!isa<InitListExpr>(IList->getInit(Index)) ||
+       cast<InitListExpr>(IList->getInit(Index))->getNumInits() > 0)) {
+    SemaRef.Diag(IList->getInit(Index)->getSourceRange().getBegin(),
+                  diag::err_flexible_array_init_nonempty)
+      << IList->getInit(Index)->getSourceRange().getBegin();
+    SemaRef.Diag(Field->getLocation(), diag::note_flexible_array_member)
+      << *Field;
+    hadError = true;
+    ++Index;
+    return;
+  } else {
+    SemaRef.Diag(IList->getInit(Index)->getSourceRange().getBegin(),
+                 diag::ext_flexible_array_init)
+      << IList->getInit(Index)->getSourceRange().getBegin();
+    SemaRef.Diag(Field->getLocation(), diag::note_flexible_array_member)
+      << *Field;
+  }
+
+  InitializedEntity MemberEntity =
+    InitializedEntity::InitializeMember(*Field, &Entity);
+    
+  if (isa<InitListExpr>(IList->getInit(Index)))
+    CheckSubElementType(MemberEntity, IList, Field->getType(), Index, 
+                        StructuredList, StructuredIndex);
+  else
+    CheckImplicitInitList(MemberEntity, IList, Field->getType(), Index, 
+                          StructuredList, StructuredIndex);
+}
+
+/// \brief Expand a field designator that refers to a member of an
+/// anonymous struct or union into a series of field designators that
+/// refers to the field within the appropriate subobject.
+///
+/// Field/FieldIndex will be updated to point to the (new)
+/// currently-designated field.
+static void ExpandAnonymousFieldDesignator(Sema &SemaRef,
+                                           DesignatedInitExpr *DIE,
+                                           unsigned DesigIdx,
+                                           FieldDecl *Field,
+                                        RecordDecl::field_iterator &FieldIter,
+                                           unsigned &FieldIndex) {
+  typedef DesignatedInitExpr::Designator Designator;
+
+  // Build the path from the current object to the member of the
+  // anonymous struct/union (backwards).
+  llvm::SmallVector<FieldDecl *, 4> Path;
+  SemaRef.BuildAnonymousStructUnionMemberPath(Field, Path);
+
+  // Build the replacement designators.
+  llvm::SmallVector<Designator, 4> Replacements;
+  for (llvm::SmallVector<FieldDecl *, 4>::reverse_iterator
+         FI = Path.rbegin(), FIEnd = Path.rend();
+       FI != FIEnd; ++FI) {
+    if (FI + 1 == FIEnd)
+      Replacements.push_back(Designator((IdentifierInfo *)0,
+                                    DIE->getDesignator(DesigIdx)->getDotLoc(),
+                                DIE->getDesignator(DesigIdx)->getFieldLoc()));
+    else
+      Replacements.push_back(Designator((IdentifierInfo *)0, SourceLocation(),
+                                        SourceLocation()));
+    Replacements.back().setField(*FI);
+  }
+
+  // Expand the current designator into the set of replacement
+  // designators, so we have a full subobject path down to where the
+  // member of the anonymous struct/union is actually stored.
+  DIE->ExpandDesignator(SemaRef.Context, DesigIdx, &Replacements[0],
+                        &Replacements[0] + Replacements.size());
+
+  // Update FieldIter/FieldIndex;
+  RecordDecl *Record = cast<RecordDecl>(Path.back()->getDeclContext());
+  FieldIter = Record->field_begin();
+  FieldIndex = 0;
+  for (RecordDecl::field_iterator FEnd = Record->field_end();
+       FieldIter != FEnd; ++FieldIter) {
+    if (FieldIter->isUnnamedBitfield())
+        continue;
+
+    if (*FieldIter == Path.back())
+      return;
+
+    ++FieldIndex;
+  }
+
+  assert(false && "Unable to find anonymous struct/union field");
+}
+
+/// @brief Check the well-formedness of a C99 designated initializer.
+///
+/// Determines whether the designated initializer @p DIE, which
+/// resides at the given @p Index within the initializer list @p
+/// IList, is well-formed for a current object of type @p DeclType
+/// (C99 6.7.8). The actual subobject that this designator refers to
+/// within the current subobject is returned in either
+/// @p NextField or @p NextElementIndex (whichever is appropriate).
+///
+/// @param IList  The initializer list in which this designated
+/// initializer occurs.
+///
+/// @param DIE The designated initializer expression.
+///
+/// @param DesigIdx  The index of the current designator.
+///
+/// @param DeclType  The type of the "current object" (C99 6.7.8p17),
+/// into which the designation in @p DIE should refer.
+///
+/// @param NextField  If non-NULL and the first designator in @p DIE is
+/// a field, this will be set to the field declaration corresponding
+/// to the field named by the designator.
+///
+/// @param NextElementIndex  If non-NULL and the first designator in @p
+/// DIE is an array designator or GNU array-range designator, this
+/// will be set to the last index initialized by this designator.
+///
+/// @param Index  Index into @p IList where the designated initializer
+/// @p DIE occurs.
+///
+/// @param StructuredList  The initializer list expression that
+/// describes all of the subobject initializers in the order they'll
+/// actually be initialized.
+///
+/// @returns true if there was an error, false otherwise.
+bool
+InitListChecker::CheckDesignatedInitializer(const InitializedEntity &Entity,
+                                            InitListExpr *IList,
+                                      DesignatedInitExpr *DIE,
+                                      unsigned DesigIdx,
+                                      QualType &CurrentObjectType,
+                                      RecordDecl::field_iterator *NextField,
+                                      llvm::APSInt *NextElementIndex,
+                                      unsigned &Index,
+                                      InitListExpr *StructuredList,
+                                      unsigned &StructuredIndex,
+                                            bool FinishSubobjectInit,
+                                            bool TopLevelObject) {
+  if (DesigIdx == DIE->size()) {
+    // Check the actual initialization for the designated object type.
+    bool prevHadError = hadError;
+
+    // Temporarily remove the designator expression from the
+    // initializer list that the child calls see, so that we don't try
+    // to re-process the designator.
+    unsigned OldIndex = Index;
+    IList->setInit(OldIndex, DIE->getInit());
+
+    CheckSubElementType(Entity, IList, CurrentObjectType, Index,
+                        StructuredList, StructuredIndex);
+
+    // Restore the designated initializer expression in the syntactic
+    // form of the initializer list.
+    if (IList->getInit(OldIndex) != DIE->getInit())
+      DIE->setInit(IList->getInit(OldIndex));
+    IList->setInit(OldIndex, DIE);
+
+    return hadError && !prevHadError;
+  }
+
+  bool IsFirstDesignator = (DesigIdx == 0);
+  assert((IsFirstDesignator || StructuredList) &&
+         "Need a non-designated initializer list to start from");
+
+  DesignatedInitExpr::Designator *D = DIE->getDesignator(DesigIdx);
+  // Determine the structural initializer list that corresponds to the
+  // current subobject.
+  StructuredList = IsFirstDesignator? SyntacticToSemantic[IList]
+    : getStructuredSubobjectInit(IList, Index, CurrentObjectType,
+                                 StructuredList, StructuredIndex,
+                                 SourceRange(D->getStartLocation(),
+                                             DIE->getSourceRange().getEnd()));
+  assert(StructuredList && "Expected a structured initializer list");
+
+  if (D->isFieldDesignator()) {
+    // C99 6.7.8p7:
+    //
+    //   If a designator has the form
+    //
+    //      . identifier
+    //
+    //   then the current object (defined below) shall have
+    //   structure or union type and the identifier shall be the
+    //   name of a member of that type.
+    const RecordType *RT = CurrentObjectType->getAs<RecordType>();
+    if (!RT) {
+      SourceLocation Loc = D->getDotLoc();
+      if (Loc.isInvalid())
+        Loc = D->getFieldLoc();
+      SemaRef.Diag(Loc, diag::err_field_designator_non_aggr)
+        << SemaRef.getLangOptions().CPlusPlus << CurrentObjectType;
+      ++Index;
+      return true;
+    }
+
+    // Note: we perform a linear search of the fields here, despite
+    // the fact that we have a faster lookup method, because we always
+    // need to compute the field's index.
+    FieldDecl *KnownField = D->getField();
+    IdentifierInfo *FieldName = D->getFieldName();
+    unsigned FieldIndex = 0;
+    RecordDecl::field_iterator
+      Field = RT->getDecl()->field_begin(),
+      FieldEnd = RT->getDecl()->field_end();
+    for (; Field != FieldEnd; ++Field) {
+      if (Field->isUnnamedBitfield())
+        continue;
+
+      if (KnownField == *Field || Field->getIdentifier() == FieldName)
+        break;
+
+      ++FieldIndex;
+    }
+
+    if (Field == FieldEnd) {
+      // There was no normal field in the struct with the designated
+      // name. Perform another lookup for this name, which may find
+      // something that we can't designate (e.g., a member function),
+      // may find nothing, or may find a member of an anonymous
+      // struct/union.
+      DeclContext::lookup_result Lookup = RT->getDecl()->lookup(FieldName);
+      FieldDecl *ReplacementField = 0;
+      if (Lookup.first == Lookup.second) {
+        // Name lookup didn't find anything. Determine whether this
+        // was a typo for another field name.
+        LookupResult R(SemaRef, FieldName, D->getFieldLoc(), 
+                       Sema::LookupMemberName);
+        if (SemaRef.CorrectTypo(R, /*Scope=*/0, /*SS=*/0, RT->getDecl()) &&
+            (ReplacementField = R.getAsSingle<FieldDecl>()) &&
+            ReplacementField->getDeclContext()->getLookupContext()
+                                                      ->Equals(RT->getDecl())) {
+          SemaRef.Diag(D->getFieldLoc(), 
+                       diag::err_field_designator_unknown_suggest)
+            << FieldName << CurrentObjectType << R.getLookupName()
+            << CodeModificationHint::CreateReplacement(D->getFieldLoc(),
+                                               R.getLookupName().getAsString());
+          SemaRef.Diag(ReplacementField->getLocation(), 
+                       diag::note_previous_decl)
+            << ReplacementField->getDeclName();
+        } else {
+          SemaRef.Diag(D->getFieldLoc(), diag::err_field_designator_unknown)
+            << FieldName << CurrentObjectType;
+          ++Index;
+          return true;
+        }
+      } else if (!KnownField) {
+        // Determine whether we found a field at all.
+        ReplacementField = dyn_cast<FieldDecl>(*Lookup.first);
+      }
+
+      if (!ReplacementField) {
+        // Name lookup found something, but it wasn't a field.
+        SemaRef.Diag(D->getFieldLoc(), diag::err_field_designator_nonfield)
+          << FieldName;
+        SemaRef.Diag((*Lookup.first)->getLocation(),
+                      diag::note_field_designator_found);
+        ++Index;
+        return true;
+      }
+
+      if (!KnownField && 
+          cast<RecordDecl>((ReplacementField)->getDeclContext())
+                                                 ->isAnonymousStructOrUnion()) {
+        // Handle an field designator that refers to a member of an
+        // anonymous struct or union.
+        ExpandAnonymousFieldDesignator(SemaRef, DIE, DesigIdx,
+                                       ReplacementField,
+                                       Field, FieldIndex);
+        D = DIE->getDesignator(DesigIdx);
+      } else if (!KnownField) {
+        // The replacement field comes from typo correction; find it
+        // in the list of fields.
+        FieldIndex = 0;
+        Field = RT->getDecl()->field_begin();
+        for (; Field != FieldEnd; ++Field) {
+          if (Field->isUnnamedBitfield())
+            continue;
+
+          if (ReplacementField == *Field || 
+              Field->getIdentifier() == ReplacementField->getIdentifier())
+            break;
+
+          ++FieldIndex;
+        }
+      }
+    } else if (!KnownField &&
+               cast<RecordDecl>((*Field)->getDeclContext())
+                 ->isAnonymousStructOrUnion()) {
+      ExpandAnonymousFieldDesignator(SemaRef, DIE, DesigIdx, *Field,
+                                     Field, FieldIndex);
+      D = DIE->getDesignator(DesigIdx);
+    }
+
+    // All of the fields of a union are located at the same place in
+    // the initializer list.
+    if (RT->getDecl()->isUnion()) {
+      FieldIndex = 0;
+      StructuredList->setInitializedFieldInUnion(*Field);
+    }
+
+    // Update the designator with the field declaration.
+    D->setField(*Field);
+
+    // Make sure that our non-designated initializer list has space
+    // for a subobject corresponding to this field.
+    if (FieldIndex >= StructuredList->getNumInits())
+      StructuredList->resizeInits(SemaRef.Context, FieldIndex + 1);
+
+    // This designator names a flexible array member.
+    if (Field->getType()->isIncompleteArrayType()) {
+      bool Invalid = false;
+      if ((DesigIdx + 1) != DIE->size()) {
+        // We can't designate an object within the flexible array
+        // member (because GCC doesn't allow it).
+        DesignatedInitExpr::Designator *NextD
+          = DIE->getDesignator(DesigIdx + 1);
+        SemaRef.Diag(NextD->getStartLocation(),
+                      diag::err_designator_into_flexible_array_member)
+          << SourceRange(NextD->getStartLocation(),
+                         DIE->getSourceRange().getEnd());
+        SemaRef.Diag(Field->getLocation(), diag::note_flexible_array_member)
+          << *Field;
+        Invalid = true;
+      }
+
+      if (!hadError && !isa<InitListExpr>(DIE->getInit())) {
+        // The initializer is not an initializer list.
+        SemaRef.Diag(DIE->getInit()->getSourceRange().getBegin(),
+                      diag::err_flexible_array_init_needs_braces)
+          << DIE->getInit()->getSourceRange();
+        SemaRef.Diag(Field->getLocation(), diag::note_flexible_array_member)
+          << *Field;
+        Invalid = true;
+      }
+
+      // Handle GNU flexible array initializers.
+      if (!Invalid && !TopLevelObject &&
+          cast<InitListExpr>(DIE->getInit())->getNumInits() > 0) {
+        SemaRef.Diag(DIE->getSourceRange().getBegin(),
+                      diag::err_flexible_array_init_nonempty)
+          << DIE->getSourceRange().getBegin();
+        SemaRef.Diag(Field->getLocation(), diag::note_flexible_array_member)
+          << *Field;
+        Invalid = true;
+      }
+
+      if (Invalid) {
+        ++Index;
+        return true;
+      }
+
+      // Initialize the array.
+      bool prevHadError = hadError;
+      unsigned newStructuredIndex = FieldIndex;
+      unsigned OldIndex = Index;
+      IList->setInit(Index, DIE->getInit());
+
+      InitializedEntity MemberEntity =
+        InitializedEntity::InitializeMember(*Field, &Entity);
+      CheckSubElementType(MemberEntity, IList, Field->getType(), Index,
+                          StructuredList, newStructuredIndex);
+
+      IList->setInit(OldIndex, DIE);
+      if (hadError && !prevHadError) {
+        ++Field;
+        ++FieldIndex;
+        if (NextField)
+          *NextField = Field;
+        StructuredIndex = FieldIndex;
+        return true;
+      }
+    } else {
+      // Recurse to check later designated subobjects.
+      QualType FieldType = (*Field)->getType();
+      unsigned newStructuredIndex = FieldIndex;
+      
+      InitializedEntity MemberEntity =
+        InitializedEntity::InitializeMember(*Field, &Entity);
+      if (CheckDesignatedInitializer(MemberEntity, IList, DIE, DesigIdx + 1, 
+                                     FieldType, 0, 0, Index, 
+                                     StructuredList, newStructuredIndex,
+                                     true, false))
+        return true;
+    }
+
+    // Find the position of the next field to be initialized in this
+    // subobject.
+    ++Field;
+    ++FieldIndex;
+
+    // If this the first designator, our caller will continue checking
+    // the rest of this struct/class/union subobject.
+    if (IsFirstDesignator) {
+      if (NextField)
+        *NextField = Field;
+      StructuredIndex = FieldIndex;
+      return false;
+    }
+
+    if (!FinishSubobjectInit)
+      return false;
+
+    // We've already initialized something in the union; we're done.
+    if (RT->getDecl()->isUnion())
+      return hadError;
+
+    // Check the remaining fields within this class/struct/union subobject.
+    bool prevHadError = hadError;
+    
+    CheckStructUnionTypes(Entity, IList, CurrentObjectType, Field, false, Index,
+                          StructuredList, FieldIndex);
+    return hadError && !prevHadError;
+  }
+
+  // C99 6.7.8p6:
+  //
+  //   If a designator has the form
+  //
+  //      [ constant-expression ]
+  //
+  //   then the current object (defined below) shall have array
+  //   type and the expression shall be an integer constant
+  //   expression. If the array is of unknown size, any
+  //   nonnegative value is valid.
+  //
+  // Additionally, cope with the GNU extension that permits
+  // designators of the form
+  //
+  //      [ constant-expression ... constant-expression ]
+  const ArrayType *AT = SemaRef.Context.getAsArrayType(CurrentObjectType);
+  if (!AT) {
+    SemaRef.Diag(D->getLBracketLoc(), diag::err_array_designator_non_array)
+      << CurrentObjectType;
+    ++Index;
+    return true;
+  }
+
+  Expr *IndexExpr = 0;
+  llvm::APSInt DesignatedStartIndex, DesignatedEndIndex;
+  if (D->isArrayDesignator()) {
+    IndexExpr = DIE->getArrayIndex(*D);
+    DesignatedStartIndex = IndexExpr->EvaluateAsInt(SemaRef.Context);
+    DesignatedEndIndex = DesignatedStartIndex;
+  } else {
+    assert(D->isArrayRangeDesignator() && "Need array-range designator");
+
+
+    DesignatedStartIndex =
+      DIE->getArrayRangeStart(*D)->EvaluateAsInt(SemaRef.Context);
+    DesignatedEndIndex =
+      DIE->getArrayRangeEnd(*D)->EvaluateAsInt(SemaRef.Context);
+    IndexExpr = DIE->getArrayRangeEnd(*D);
+
+    if (DesignatedStartIndex.getZExtValue() !=DesignatedEndIndex.getZExtValue())
+      FullyStructuredList->sawArrayRangeDesignator();
+  }
+
+  if (isa<ConstantArrayType>(AT)) {
+    llvm::APSInt MaxElements(cast<ConstantArrayType>(AT)->getSize(), false);
+    DesignatedStartIndex.extOrTrunc(MaxElements.getBitWidth());
+    DesignatedStartIndex.setIsUnsigned(MaxElements.isUnsigned());
+    DesignatedEndIndex.extOrTrunc(MaxElements.getBitWidth());
+    DesignatedEndIndex.setIsUnsigned(MaxElements.isUnsigned());
+    if (DesignatedEndIndex >= MaxElements) {
+      SemaRef.Diag(IndexExpr->getSourceRange().getBegin(),
+                    diag::err_array_designator_too_large)
+        << DesignatedEndIndex.toString(10) << MaxElements.toString(10)
+        << IndexExpr->getSourceRange();
+      ++Index;
+      return true;
+    }
+  } else {
+    // Make sure the bit-widths and signedness match.
+    if (DesignatedStartIndex.getBitWidth() > DesignatedEndIndex.getBitWidth())
+      DesignatedEndIndex.extend(DesignatedStartIndex.getBitWidth());
+    else if (DesignatedStartIndex.getBitWidth() <
+             DesignatedEndIndex.getBitWidth())
+      DesignatedStartIndex.extend(DesignatedEndIndex.getBitWidth());
+    DesignatedStartIndex.setIsUnsigned(true);
+    DesignatedEndIndex.setIsUnsigned(true);
+  }
+
+  // Make sure that our non-designated initializer list has space
+  // for a subobject corresponding to this array element.
+  if (DesignatedEndIndex.getZExtValue() >= StructuredList->getNumInits())
+    StructuredList->resizeInits(SemaRef.Context,
+                                DesignatedEndIndex.getZExtValue() + 1);
+
+  // Repeatedly perform subobject initializations in the range
+  // [DesignatedStartIndex, DesignatedEndIndex].
+
+  // Move to the next designator
+  unsigned ElementIndex = DesignatedStartIndex.getZExtValue();
+  unsigned OldIndex = Index;
+  
+  InitializedEntity ElementEntity =
+    InitializedEntity::InitializeElement(SemaRef.Context, 0, Entity);
+
+  while (DesignatedStartIndex <= DesignatedEndIndex) {
+    // Recurse to check later designated subobjects.
+    QualType ElementType = AT->getElementType();
+    Index = OldIndex;
+    
+    ElementEntity.setElementIndex(ElementIndex);
+    if (CheckDesignatedInitializer(ElementEntity, IList, DIE, DesigIdx + 1, 
+                                   ElementType, 0, 0, Index, 
+                                   StructuredList, ElementIndex,
+                                   (DesignatedStartIndex == DesignatedEndIndex),
+                                   false))
+      return true;
+
+    // Move to the next index in the array that we'll be initializing.
+    ++DesignatedStartIndex;
+    ElementIndex = DesignatedStartIndex.getZExtValue();
+  }
+
+  // If this the first designator, our caller will continue checking
+  // the rest of this array subobject.
+  if (IsFirstDesignator) {
+    if (NextElementIndex)
+      *NextElementIndex = DesignatedStartIndex;
+    StructuredIndex = ElementIndex;
+    return false;
+  }
+
+  if (!FinishSubobjectInit)
+    return false;
+
+  // Check the remaining elements within this array subobject.
+  bool prevHadError = hadError;
+  CheckArrayType(Entity, IList, CurrentObjectType, DesignatedStartIndex, 
+                 /*SubobjectIsDesignatorContext=*/false, Index,
+                 StructuredList, ElementIndex);
+  return hadError && !prevHadError;
+}
+
+// Get the structured initializer list for a subobject of type
+// @p CurrentObjectType.
+InitListExpr *
+InitListChecker::getStructuredSubobjectInit(InitListExpr *IList, unsigned Index,
+                                            QualType CurrentObjectType,
+                                            InitListExpr *StructuredList,
+                                            unsigned StructuredIndex,
+                                            SourceRange InitRange) {
+  Expr *ExistingInit = 0;
+  if (!StructuredList)
+    ExistingInit = SyntacticToSemantic[IList];
+  else if (StructuredIndex < StructuredList->getNumInits())
+    ExistingInit = StructuredList->getInit(StructuredIndex);
+
+  if (InitListExpr *Result = dyn_cast_or_null<InitListExpr>(ExistingInit))
+    return Result;
+
+  if (ExistingInit) {
+    // We are creating an initializer list that initializes the
+    // subobjects of the current object, but there was already an
+    // initialization that completely initialized the current
+    // subobject, e.g., by a compound literal:
+    //
+    // struct X { int a, b; };
+    // struct X xs[] = { [0] = (struct X) { 1, 2 }, [0].b = 3 };
+    //
+    // Here, xs[0].a == 0 and xs[0].b == 3, since the second,
+    // designated initializer re-initializes the whole
+    // subobject [0], overwriting previous initializers.
+    SemaRef.Diag(InitRange.getBegin(),
+                 diag::warn_subobject_initializer_overrides)
+      << InitRange;
+    SemaRef.Diag(ExistingInit->getSourceRange().getBegin(),
+                  diag::note_previous_initializer)
+      << /*FIXME:has side effects=*/0
+      << ExistingInit->getSourceRange();
+  }
+
+  InitListExpr *Result
+    = new (SemaRef.Context) InitListExpr(InitRange.getBegin(), 0, 0,
+                                         InitRange.getEnd());
+
+  Result->setType(CurrentObjectType.getNonReferenceType());
+
+  // Pre-allocate storage for the structured initializer list.
+  unsigned NumElements = 0;
+  unsigned NumInits = 0;
+  if (!StructuredList)
+    NumInits = IList->getNumInits();
+  else if (Index < IList->getNumInits()) {
+    if (InitListExpr *SubList = dyn_cast<InitListExpr>(IList->getInit(Index)))
+      NumInits = SubList->getNumInits();
+  }
+
+  if (const ArrayType *AType
+      = SemaRef.Context.getAsArrayType(CurrentObjectType)) {
+    if (const ConstantArrayType *CAType = dyn_cast<ConstantArrayType>(AType)) {
+      NumElements = CAType->getSize().getZExtValue();
+      // Simple heuristic so that we don't allocate a very large
+      // initializer with many empty entries at the end.
+      if (NumInits && NumElements > NumInits)
+        NumElements = 0;
+    }
+  } else if (const VectorType *VType = CurrentObjectType->getAs<VectorType>())
+    NumElements = VType->getNumElements();
+  else if (const RecordType *RType = CurrentObjectType->getAs<RecordType>()) {
+    RecordDecl *RDecl = RType->getDecl();
+    if (RDecl->isUnion())
+      NumElements = 1;
+    else
+      NumElements = std::distance(RDecl->field_begin(),
+                                  RDecl->field_end());
+  }
+
+  if (NumElements < NumInits)
+    NumElements = IList->getNumInits();
+
+  Result->reserveInits(NumElements);
+
+  // Link this new initializer list into the structured initializer
+  // lists.
+  if (StructuredList)
+    StructuredList->updateInit(StructuredIndex, Result);
+  else {
+    Result->setSyntacticForm(IList);
+    SyntacticToSemantic[IList] = Result;
+  }
+
+  return Result;
+}
+
+/// Update the initializer at index @p StructuredIndex within the
+/// structured initializer list to the value @p expr.
+void InitListChecker::UpdateStructuredListElement(InitListExpr *StructuredList,
+                                                  unsigned &StructuredIndex,
+                                                  Expr *expr) {
+  // No structured initializer list to update
+  if (!StructuredList)
+    return;
+
+  if (Expr *PrevInit = StructuredList->updateInit(StructuredIndex, expr)) {
+    // This initializer overwrites a previous initializer. Warn.
+    SemaRef.Diag(expr->getSourceRange().getBegin(),
+                  diag::warn_initializer_overrides)
+      << expr->getSourceRange();
+    SemaRef.Diag(PrevInit->getSourceRange().getBegin(),
+                  diag::note_previous_initializer)
+      << /*FIXME:has side effects=*/0
+      << PrevInit->getSourceRange();
+  }
+
+  ++StructuredIndex;
+}
+
+/// Check that the given Index expression is a valid array designator
+/// value. This is essentailly just a wrapper around
+/// VerifyIntegerConstantExpression that also checks for negative values
+/// and produces a reasonable diagnostic if there is a
+/// failure. Returns true if there was an error, false otherwise.  If
+/// everything went okay, Value will receive the value of the constant
+/// expression.
+static bool
+CheckArrayDesignatorExpr(Sema &S, Expr *Index, llvm::APSInt &Value) {
+  SourceLocation Loc = Index->getSourceRange().getBegin();
+
+  // Make sure this is an integer constant expression.
+  if (S.VerifyIntegerConstantExpression(Index, &Value))
+    return true;
+
+  if (Value.isSigned() && Value.isNegative())
+    return S.Diag(Loc, diag::err_array_designator_negative)
+      << Value.toString(10) << Index->getSourceRange();
+
+  Value.setIsUnsigned(true);
+  return false;
+}
+
+Sema::OwningExprResult Sema::ActOnDesignatedInitializer(Designation &Desig,
+                                                        SourceLocation Loc,
+                                                        bool GNUSyntax,
+                                                        OwningExprResult Init) {
+  typedef DesignatedInitExpr::Designator ASTDesignator;
+
+  bool Invalid = false;
+  llvm::SmallVector<ASTDesignator, 32> Designators;
+  llvm::SmallVector<Expr *, 32> InitExpressions;
+
+  // Build designators and check array designator expressions.
+  for (unsigned Idx = 0; Idx < Desig.getNumDesignators(); ++Idx) {
+    const Designator &D = Desig.getDesignator(Idx);
+    switch (D.getKind()) {
+    case Designator::FieldDesignator:
+      Designators.push_back(ASTDesignator(D.getField(), D.getDotLoc(),
+                                          D.getFieldLoc()));
+      break;
+
+    case Designator::ArrayDesignator: {
+      Expr *Index = static_cast<Expr *>(D.getArrayIndex());
+      llvm::APSInt IndexValue;
+      if (!Index->isTypeDependent() &&
+          !Index->isValueDependent() &&
+          CheckArrayDesignatorExpr(*this, Index, IndexValue))
+        Invalid = true;
+      else {
+        Designators.push_back(ASTDesignator(InitExpressions.size(),
+                                            D.getLBracketLoc(),
+                                            D.getRBracketLoc()));
+        InitExpressions.push_back(Index);
+      }
+      break;
+    }
+
+    case Designator::ArrayRangeDesignator: {
+      Expr *StartIndex = static_cast<Expr *>(D.getArrayRangeStart());
+      Expr *EndIndex = static_cast<Expr *>(D.getArrayRangeEnd());
+      llvm::APSInt StartValue;
+      llvm::APSInt EndValue;
+      bool StartDependent = StartIndex->isTypeDependent() ||
+                            StartIndex->isValueDependent();
+      bool EndDependent = EndIndex->isTypeDependent() ||
+                          EndIndex->isValueDependent();
+      if ((!StartDependent &&
+           CheckArrayDesignatorExpr(*this, StartIndex, StartValue)) ||
+          (!EndDependent &&
+           CheckArrayDesignatorExpr(*this, EndIndex, EndValue)))
+        Invalid = true;
+      else {
+        // Make sure we're comparing values with the same bit width.
+        if (StartDependent || EndDependent) {
+          // Nothing to compute.
+        } else if (StartValue.getBitWidth() > EndValue.getBitWidth())
+          EndValue.extend(StartValue.getBitWidth());
+        else if (StartValue.getBitWidth() < EndValue.getBitWidth())
+          StartValue.extend(EndValue.getBitWidth());
+
+        if (!StartDependent && !EndDependent && EndValue < StartValue) {
+          Diag(D.getEllipsisLoc(), diag::err_array_designator_empty_range)
+            << StartValue.toString(10) << EndValue.toString(10)
+            << StartIndex->getSourceRange() << EndIndex->getSourceRange();
+          Invalid = true;
+        } else {
+          Designators.push_back(ASTDesignator(InitExpressions.size(),
+                                              D.getLBracketLoc(),
+                                              D.getEllipsisLoc(),
+                                              D.getRBracketLoc()));
+          InitExpressions.push_back(StartIndex);
+          InitExpressions.push_back(EndIndex);
+        }
+      }
+      break;
+    }
+    }
+  }
+
+  if (Invalid || Init.isInvalid())
+    return ExprError();
+
+  // Clear out the expressions within the designation.
+  Desig.ClearExprs(*this);
+
+  DesignatedInitExpr *DIE
+    = DesignatedInitExpr::Create(Context,
+                                 Designators.data(), Designators.size(),
+                                 InitExpressions.data(), InitExpressions.size(),
+                                 Loc, GNUSyntax, Init.takeAs<Expr>());
+  return Owned(DIE);
+}
+
+bool Sema::CheckInitList(const InitializedEntity &Entity,
+                         InitListExpr *&InitList, QualType &DeclType) {
+  InitListChecker CheckInitList(*this, Entity, InitList, DeclType);
+  if (!CheckInitList.HadError())
+    InitList = CheckInitList.getFullyStructuredList();
+
+  return CheckInitList.HadError();
+}
+
+//===----------------------------------------------------------------------===//
+// Initialization entity
+//===----------------------------------------------------------------------===//
+
+InitializedEntity::InitializedEntity(ASTContext &Context, unsigned Index, 
+                                     const InitializedEntity &Parent)
+  : Parent(&Parent), Index(Index) 
+{
+  if (const ArrayType *AT = Context.getAsArrayType(Parent.getType())) {
+    Kind = EK_ArrayElement;
+    Type = AT->getElementType();
+  } else {
+    Kind = EK_VectorElement;
+    Type = Parent.getType()->getAs<VectorType>()->getElementType();
+  }
+}
+
+InitializedEntity InitializedEntity::InitializeBase(ASTContext &Context, 
+                                                    CXXBaseSpecifier *Base)
+{
+  InitializedEntity Result;
+  Result.Kind = EK_Base;
+  Result.Base = Base;
+  Result.Type = Base->getType();
+  return Result;
+}
+
+DeclarationName InitializedEntity::getName() const {
+  switch (getKind()) {
+  case EK_Parameter:
+    if (!VariableOrMember)
+      return DeclarationName();
+    // Fall through
+
+  case EK_Variable:
+  case EK_Member:
+    return VariableOrMember->getDeclName();
+
+  case EK_Result:
+  case EK_Exception:
+  case EK_New:
+  case EK_Temporary:
+  case EK_Base:
+  case EK_ArrayElement:
+  case EK_VectorElement:
+    return DeclarationName();
+  }
+  
+  // Silence GCC warning
+  return DeclarationName();
+}
+
+DeclaratorDecl *InitializedEntity::getDecl() const {
+  switch (getKind()) {
+  case EK_Variable:
+  case EK_Parameter:
+  case EK_Member:
+    return VariableOrMember;
+
+  case EK_Result:
+  case EK_Exception:
+  case EK_New:
+  case EK_Temporary:
+  case EK_Base:
+  case EK_ArrayElement:
+  case EK_VectorElement:
+    return 0;
+  }
+  
+  // Silence GCC warning
+  return 0;
+}
+
+//===----------------------------------------------------------------------===//
+// Initialization sequence
+//===----------------------------------------------------------------------===//
+
+void InitializationSequence::Step::Destroy() {
+  switch (Kind) {
+  case SK_ResolveAddressOfOverloadedFunction:
+  case SK_CastDerivedToBaseRValue:
+  case SK_CastDerivedToBaseLValue:
+  case SK_BindReference:
+  case SK_BindReferenceToTemporary:
+  case SK_UserConversion:
+  case SK_QualificationConversionRValue:
+  case SK_QualificationConversionLValue:
+  case SK_ListInitialization:
+  case SK_ConstructorInitialization:
+  case SK_ZeroInitialization:
+  case SK_CAssignment:
+  case SK_StringInit:
+    break;
+    
+  case SK_ConversionSequence:
+    delete ICS;
+  }
+}
+
+void InitializationSequence::AddAddressOverloadResolutionStep(
+                                                      FunctionDecl *Function) {
+  Step S;
+  S.Kind = SK_ResolveAddressOfOverloadedFunction;
+  S.Type = Function->getType();
+  // Access is currently ignored for these.
+  S.Function = DeclAccessPair::make(Function, AccessSpecifier(0));
+  Steps.push_back(S);
+}
+
+void InitializationSequence::AddDerivedToBaseCastStep(QualType BaseType, 
+                                                      bool IsLValue) {
+  Step S;
+  S.Kind = IsLValue? SK_CastDerivedToBaseLValue : SK_CastDerivedToBaseRValue;
+  S.Type = BaseType;
+  Steps.push_back(S);
+}
+
+void InitializationSequence::AddReferenceBindingStep(QualType T, 
+                                                     bool BindingTemporary) {
+  Step S;
+  S.Kind = BindingTemporary? SK_BindReferenceToTemporary : SK_BindReference;
+  S.Type = T;
+  Steps.push_back(S);
+}
+
+void InitializationSequence::AddUserConversionStep(FunctionDecl *Function,
+                                                   AccessSpecifier Access,
+                                                   QualType T) {
+  Step S;
+  S.Kind = SK_UserConversion;
+  S.Type = T;
+  S.Function = DeclAccessPair::make(Function, Access);
+  Steps.push_back(S);
+}
+
+void InitializationSequence::AddQualificationConversionStep(QualType Ty,
+                                                            bool IsLValue) {
+  Step S;
+  S.Kind = IsLValue? SK_QualificationConversionLValue 
+                   : SK_QualificationConversionRValue;
+  S.Type = Ty;
+  Steps.push_back(S);
+}
+
+void InitializationSequence::AddConversionSequenceStep(
+                                       const ImplicitConversionSequence &ICS,
+                                                       QualType T) {
+  Step S;
+  S.Kind = SK_ConversionSequence;
+  S.Type = T;
+  S.ICS = new ImplicitConversionSequence(ICS);
+  Steps.push_back(S);
+}
+
+void InitializationSequence::AddListInitializationStep(QualType T) {
+  Step S;
+  S.Kind = SK_ListInitialization;
+  S.Type = T;
+  Steps.push_back(S);
+}
+
+void 
+InitializationSequence::AddConstructorInitializationStep(
+                                              CXXConstructorDecl *Constructor,
+                                                       AccessSpecifier Access,
+                                                         QualType T) {
+  Step S;
+  S.Kind = SK_ConstructorInitialization;
+  S.Type = T;
+  S.Function = DeclAccessPair::make(Constructor, Access);
+  Steps.push_back(S);
+}
+
+void InitializationSequence::AddZeroInitializationStep(QualType T) {
+  Step S;
+  S.Kind = SK_ZeroInitialization;
+  S.Type = T;
+  Steps.push_back(S);
+}
+
+void InitializationSequence::AddCAssignmentStep(QualType T) {
+  Step S;
+  S.Kind = SK_CAssignment;
+  S.Type = T;
+  Steps.push_back(S);
+}
+
+void InitializationSequence::AddStringInitStep(QualType T) {
+  Step S;
+  S.Kind = SK_StringInit;
+  S.Type = T;
+  Steps.push_back(S);
+}
+
+void InitializationSequence::SetOverloadFailure(FailureKind Failure, 
+                                                OverloadingResult Result) {
+  SequenceKind = FailedSequence;
+  this->Failure = Failure;
+  this->FailedOverloadResult = Result;
+}
+
+//===----------------------------------------------------------------------===//
+// Attempt initialization
+//===----------------------------------------------------------------------===//
+
+/// \brief Attempt list initialization (C++0x [dcl.init.list]) 
+static void TryListInitialization(Sema &S, 
+                                  const InitializedEntity &Entity,
+                                  const InitializationKind &Kind,
+                                  InitListExpr *InitList,
+                                  InitializationSequence &Sequence) {
+  // FIXME: We only perform rudimentary checking of list
+  // initializations at this point, then assume that any list
+  // initialization of an array, aggregate, or scalar will be
+  // well-formed. We we actually "perform" list initialization, we'll
+  // do all of the necessary checking.  C++0x initializer lists will
+  // force us to perform more checking here.
+  Sequence.setSequenceKind(InitializationSequence::ListInitialization);
+
+  QualType DestType = Entity.getType();
+
+  // C++ [dcl.init]p13:
+  //   If T is a scalar type, then a declaration of the form 
+  //
+  //     T x = { a };
+  //
+  //   is equivalent to
+  //
+  //     T x = a;
+  if (DestType->isScalarType()) {
+    if (InitList->getNumInits() > 1 && S.getLangOptions().CPlusPlus) {
+      Sequence.SetFailed(InitializationSequence::FK_TooManyInitsForScalar);
+      return;
+    }
+
+    // Assume scalar initialization from a single value works.
+  } else if (DestType->isAggregateType()) {
+    // Assume aggregate initialization works.
+  } else if (DestType->isVectorType()) {
+    // Assume vector initialization works.
+  } else if (DestType->isReferenceType()) {
+    // FIXME: C++0x defines behavior for this.
+    Sequence.SetFailed(InitializationSequence::FK_ReferenceBindingToInitList);
+    return;
+  } else if (DestType->isRecordType()) {
+    // FIXME: C++0x defines behavior for this
+    Sequence.SetFailed(InitializationSequence::FK_InitListBadDestinationType);
+  }
+
+  // Add a general "list initialization" step.
+  Sequence.AddListInitializationStep(DestType);
+}
+
+/// \brief Try a reference initialization that involves calling a conversion
+/// function.
+///
+/// FIXME: look intos DRs 656, 896
+static OverloadingResult TryRefInitWithConversionFunction(Sema &S,
+                                             const InitializedEntity &Entity,
+                                             const InitializationKind &Kind,
+                                                          Expr *Initializer,
+                                                          bool AllowRValues,
+                                             InitializationSequence &Sequence) {
+  QualType DestType = Entity.getType();
+  QualType cv1T1 = DestType->getAs<ReferenceType>()->getPointeeType();
+  QualType T1 = cv1T1.getUnqualifiedType();
+  QualType cv2T2 = Initializer->getType();
+  QualType T2 = cv2T2.getUnqualifiedType();
+
+  bool DerivedToBase;
+  assert(!S.CompareReferenceRelationship(Initializer->getLocStart(), 
+                                         T1, T2, DerivedToBase) &&
+         "Must have incompatible references when binding via conversion");
+  (void)DerivedToBase;
+
+  // Build the candidate set directly in the initialization sequence
+  // structure, so that it will persist if we fail.
+  OverloadCandidateSet &CandidateSet = Sequence.getFailedCandidateSet();
+  CandidateSet.clear();
+
+  // Determine whether we are allowed to call explicit constructors or
+  // explicit conversion operators.
+  bool AllowExplicit = Kind.getKind() == InitializationKind::IK_Direct;
+  
+  const RecordType *T1RecordType = 0;
+  if (AllowRValues && (T1RecordType = T1->getAs<RecordType>())) {
+    // The type we're converting to is a class type. Enumerate its constructors
+    // to see if there is a suitable conversion.
+    CXXRecordDecl *T1RecordDecl = cast<CXXRecordDecl>(T1RecordType->getDecl());
+    
+    DeclarationName ConstructorName
+      = S.Context.DeclarationNames.getCXXConstructorName(
+                           S.Context.getCanonicalType(T1).getUnqualifiedType());
+    DeclContext::lookup_iterator Con, ConEnd;
+    for (llvm::tie(Con, ConEnd) = T1RecordDecl->lookup(ConstructorName);
+         Con != ConEnd; ++Con) {
+      // Find the constructor (which may be a template).
+      CXXConstructorDecl *Constructor = 0;
+      FunctionTemplateDecl *ConstructorTmpl
+        = dyn_cast<FunctionTemplateDecl>(*Con);
+      if (ConstructorTmpl)
+        Constructor = cast<CXXConstructorDecl>(
+                                         ConstructorTmpl->getTemplatedDecl());
+      else
+        Constructor = cast<CXXConstructorDecl>(*Con);
+      
+      if (!Constructor->isInvalidDecl() &&
+          Constructor->isConvertingConstructor(AllowExplicit)) {
+        if (ConstructorTmpl)
+          S.AddTemplateOverloadCandidate(ConstructorTmpl,
+                                         ConstructorTmpl->getAccess(),
+                                         /*ExplicitArgs*/ 0,
+                                         &Initializer, 1, CandidateSet);
+        else
+          S.AddOverloadCandidate(Constructor, Constructor->getAccess(),
+                                 &Initializer, 1, CandidateSet);
+      }
+    }    
+  }
+  
+  if (const RecordType *T2RecordType = T2->getAs<RecordType>()) {
+    // The type we're converting from is a class type, enumerate its conversion
+    // functions.
+    CXXRecordDecl *T2RecordDecl = cast<CXXRecordDecl>(T2RecordType->getDecl());
+
+    // Determine the type we are converting to. If we are allowed to
+    // convert to an rvalue, take the type that the destination type
+    // refers to.
+    QualType ToType = AllowRValues? cv1T1 : DestType;
+
+    const UnresolvedSetImpl *Conversions
+      = T2RecordDecl->getVisibleConversionFunctions();
+    for (UnresolvedSetImpl::const_iterator I = Conversions->begin(),
+           E = Conversions->end(); I != E; ++I) {
+      NamedDecl *D = *I;
+      CXXRecordDecl *ActingDC = cast<CXXRecordDecl>(D->getDeclContext());
+      if (isa<UsingShadowDecl>(D))
+        D = cast<UsingShadowDecl>(D)->getTargetDecl();
+      
+      FunctionTemplateDecl *ConvTemplate = dyn_cast<FunctionTemplateDecl>(D);
+      CXXConversionDecl *Conv;
+      if (ConvTemplate)
+        Conv = cast<CXXConversionDecl>(ConvTemplate->getTemplatedDecl());
+      else
+        Conv = cast<CXXConversionDecl>(*I);
+      
+      // If the conversion function doesn't return a reference type,
+      // it can't be considered for this conversion unless we're allowed to
+      // consider rvalues.
+      // FIXME: Do we need to make sure that we only consider conversion 
+      // candidates with reference-compatible results? That might be needed to 
+      // break recursion.
+      if ((AllowExplicit || !Conv->isExplicit()) &&
+          (AllowRValues || Conv->getConversionType()->isLValueReferenceType())){
+        if (ConvTemplate)
+          S.AddTemplateConversionCandidate(ConvTemplate, I.getAccess(),
+                                           ActingDC, Initializer,
+                                           ToType, CandidateSet);
+        else
+          S.AddConversionCandidate(Conv, I.getAccess(), ActingDC,
+                                   Initializer, cv1T1, CandidateSet);
+      }
+    }
+  }
+  
+  SourceLocation DeclLoc = Initializer->getLocStart();
+
+  // Perform overload resolution. If it fails, return the failed result.  
+  OverloadCandidateSet::iterator Best;
+  if (OverloadingResult Result 
+        = S.BestViableFunction(CandidateSet, DeclLoc, Best))
+    return Result;
+
+  FunctionDecl *Function = Best->Function;
+
+  // Compute the returned type of the conversion.
+  if (isa<CXXConversionDecl>(Function))
+    T2 = Function->getResultType();
+  else
+    T2 = cv1T1;
+
+  // Add the user-defined conversion step.
+  Sequence.AddUserConversionStep(Function, Best->getAccess(),
+                                 T2.getNonReferenceType());
+
+  // Determine whether we need to perform derived-to-base or 
+  // cv-qualification adjustments.
+  bool NewDerivedToBase = false;
+  Sema::ReferenceCompareResult NewRefRelationship
+    = S.CompareReferenceRelationship(DeclLoc, T1, T2.getNonReferenceType(),
+                                     NewDerivedToBase);
+  assert(NewRefRelationship != Sema::Ref_Incompatible &&
+         "Overload resolution picked a bad conversion function");
+  (void)NewRefRelationship;
+  if (NewDerivedToBase)
+    Sequence.AddDerivedToBaseCastStep(
+                                S.Context.getQualifiedType(T1,
+                                  T2.getNonReferenceType().getQualifiers()), 
+                                  /*isLValue=*/true);
+  
+  if (cv1T1.getQualifiers() != T2.getNonReferenceType().getQualifiers())
+    Sequence.AddQualificationConversionStep(cv1T1, T2->isReferenceType());
+  
+  Sequence.AddReferenceBindingStep(cv1T1, !T2->isReferenceType());
+  return OR_Success;
+}
+  
+/// \brief Attempt reference initialization (C++0x [dcl.init.list]) 
+static void TryReferenceInitialization(Sema &S, 
+                                       const InitializedEntity &Entity,
+                                       const InitializationKind &Kind,
+                                       Expr *Initializer,
+                                       InitializationSequence &Sequence) {
+  Sequence.setSequenceKind(InitializationSequence::ReferenceBinding);
+  
+  QualType DestType = Entity.getType();
+  QualType cv1T1 = DestType->getAs<ReferenceType>()->getPointeeType();
+  Qualifiers T1Quals;
+  QualType T1 = S.Context.getUnqualifiedArrayType(cv1T1, T1Quals);
+  QualType cv2T2 = Initializer->getType();
+  Qualifiers T2Quals;
+  QualType T2 = S.Context.getUnqualifiedArrayType(cv2T2, T2Quals);
+  SourceLocation DeclLoc = Initializer->getLocStart();
+  
+  // If the initializer is the address of an overloaded function, try
+  // to resolve the overloaded function. If all goes well, T2 is the
+  // type of the resulting function.
+  if (S.Context.getCanonicalType(T2) == S.Context.OverloadTy) {
+    FunctionDecl *Fn = S.ResolveAddressOfOverloadedFunction(Initializer, 
+                                                            T1,
+                                                            false);
+    if (!Fn) {
+      Sequence.SetFailed(InitializationSequence::FK_AddressOfOverloadFailed);
+      return;
+    }
+    
+    Sequence.AddAddressOverloadResolutionStep(Fn);
+    cv2T2 = Fn->getType();
+    T2 = cv2T2.getUnqualifiedType();
+  }
+  
+  // FIXME: Rvalue references
+  bool ForceRValue = false;
+  
+  // Compute some basic properties of the types and the initializer.
+  bool isLValueRef = DestType->isLValueReferenceType();
+  bool isRValueRef = !isLValueRef;
+  bool DerivedToBase = false;
+  Expr::isLvalueResult InitLvalue = ForceRValue ? Expr::LV_InvalidExpression :
+                                    Initializer->isLvalue(S.Context);
+  Sema::ReferenceCompareResult RefRelationship
+    = S.CompareReferenceRelationship(DeclLoc, cv1T1, cv2T2, DerivedToBase);
+  
+  // C++0x [dcl.init.ref]p5:
+  //   A reference to type "cv1 T1" is initialized by an expression of type 
+  //   "cv2 T2" as follows:
+  //
+  //     - If the reference is an lvalue reference and the initializer 
+  //       expression
+  OverloadingResult ConvOvlResult = OR_Success;
+  if (isLValueRef) {
+    if (InitLvalue == Expr::LV_Valid && 
+        RefRelationship >= Sema::Ref_Compatible_With_Added_Qualification) {
+      //   - is an lvalue (but is not a bit-field), and "cv1 T1" is 
+      //     reference-compatible with "cv2 T2," or
+      //
+      // Per C++ [over.best.ics]p2, we don't diagnose whether the lvalue is a 
+      // bit-field when we're determining whether the reference initialization
+      // can occur. However, we do pay attention to whether it is a bit-field
+      // to decide whether we're actually binding to a temporary created from
+      // the bit-field.
+      if (DerivedToBase)
+        Sequence.AddDerivedToBaseCastStep(
+                         S.Context.getQualifiedType(T1, T2Quals), 
+                         /*isLValue=*/true);
+      if (T1Quals != T2Quals)
+        Sequence.AddQualificationConversionStep(cv1T1, /*IsLValue=*/true);
+      bool BindingTemporary = T1Quals.hasConst() && !T1Quals.hasVolatile() &&
+        (Initializer->getBitField() || Initializer->refersToVectorElement());
+      Sequence.AddReferenceBindingStep(cv1T1, BindingTemporary);
+      return;
+    }
+    
+    //     - has a class type (i.e., T2 is a class type), where T1 is not 
+    //       reference-related to T2, and can be implicitly converted to an 
+    //       lvalue of type "cv3 T3," where "cv1 T1" is reference-compatible 
+    //       with "cv3 T3" (this conversion is selected by enumerating the 
+    //       applicable conversion functions (13.3.1.6) and choosing the best
+    //       one through overload resolution (13.3)),
+    if (RefRelationship == Sema::Ref_Incompatible && T2->isRecordType()) {
+      ConvOvlResult = TryRefInitWithConversionFunction(S, Entity, Kind, 
+                                                       Initializer,
+                                                       /*AllowRValues=*/false,
+                                                       Sequence);
+      if (ConvOvlResult == OR_Success)
+        return;
+      if (ConvOvlResult != OR_No_Viable_Function) {
+        Sequence.SetOverloadFailure(
+                      InitializationSequence::FK_ReferenceInitOverloadFailed,
+                                    ConvOvlResult);
+      }
+    }
+  }
+  
+  //     - Otherwise, the reference shall be an lvalue reference to a 
+  //       non-volatile const type (i.e., cv1 shall be const), or the reference
+  //       shall be an rvalue reference and the initializer expression shall 
+  //       be an rvalue.
+  if (!((isLValueRef && T1Quals.hasConst() && !T1Quals.hasVolatile()) ||
+        (isRValueRef && InitLvalue != Expr::LV_Valid))) {
+    if (ConvOvlResult && !Sequence.getFailedCandidateSet().empty())
+      Sequence.SetOverloadFailure(
+                        InitializationSequence::FK_ReferenceInitOverloadFailed,
+                                  ConvOvlResult);
+    else if (isLValueRef)
+      Sequence.SetFailed(InitLvalue == Expr::LV_Valid
+        ? (RefRelationship == Sema::Ref_Related
+             ? InitializationSequence::FK_ReferenceInitDropsQualifiers
+             : InitializationSequence::FK_NonConstLValueReferenceBindingToUnrelated)
+        : InitializationSequence::FK_NonConstLValueReferenceBindingToTemporary);
+    else
+      Sequence.SetFailed(
+                    InitializationSequence::FK_RValueReferenceBindingToLValue);
+    
+    return;
+  }
+  
+  //       - If T1 and T2 are class types and
+  if (T1->isRecordType() && T2->isRecordType()) {
+    //       - the initializer expression is an rvalue and "cv1 T1" is 
+    //         reference-compatible with "cv2 T2", or
+    if (InitLvalue != Expr::LV_Valid && 
+        RefRelationship >= Sema::Ref_Compatible_With_Added_Qualification) {
+      if (DerivedToBase)
+        Sequence.AddDerivedToBaseCastStep(
+                         S.Context.getQualifiedType(T1, T2Quals), 
+                         /*isLValue=*/false);
+      if (T1Quals != T2Quals)
+        Sequence.AddQualificationConversionStep(cv1T1, /*IsLValue=*/false);
+      Sequence.AddReferenceBindingStep(cv1T1, /*bindingTemporary=*/true);
+      return;
+    }
+    
+    //       - T1 is not reference-related to T2 and the initializer expression
+    //         can be implicitly converted to an rvalue of type "cv3 T3" (this
+    //         conversion is selected by enumerating the applicable conversion
+    //         functions (13.3.1.6) and choosing the best one through overload 
+    //         resolution (13.3)),
+    if (RefRelationship == Sema::Ref_Incompatible) {
+      ConvOvlResult = TryRefInitWithConversionFunction(S, Entity,
+                                                       Kind, Initializer,
+                                                       /*AllowRValues=*/true,
+                                                       Sequence);
+      if (ConvOvlResult)
+        Sequence.SetOverloadFailure(
+                      InitializationSequence::FK_ReferenceInitOverloadFailed,
+                                    ConvOvlResult);
+        
+      return;
+    }
+    
+    Sequence.SetFailed(InitializationSequence::FK_ReferenceInitDropsQualifiers);
+    return;
+  }
+  
+  //      - If the initializer expression is an rvalue, with T2 an array type,
+  //        and "cv1 T1" is reference-compatible with "cv2 T2," the reference
+  //        is bound to the object represented by the rvalue (see 3.10).
+  // FIXME: How can an array type be reference-compatible with anything?
+  // Don't we mean the element types of T1 and T2?
+  
+  //      - Otherwise, a temporary of type “cv1 T1” is created and initialized
+  //        from the initializer expression using the rules for a non-reference
+  //        copy initialization (8.5). The reference is then bound to the 
+  //        temporary. [...]
+  // Determine whether we are allowed to call explicit constructors or
+  // explicit conversion operators.
+  bool AllowExplicit = (Kind.getKind() == InitializationKind::IK_Direct);
+  ImplicitConversionSequence ICS
+    = S.TryImplicitConversion(Initializer, cv1T1,
+                              /*SuppressUserConversions=*/false, AllowExplicit, 
+                              /*ForceRValue=*/false, 
+                              /*FIXME:InOverloadResolution=*/false,
+                              /*UserCast=*/Kind.isExplicitCast());
+            
+  if (ICS.isBad()) {
+    // FIXME: Use the conversion function set stored in ICS to turn
+    // this into an overloading ambiguity diagnostic. However, we need
+    // to keep that set as an OverloadCandidateSet rather than as some
+    // other kind of set.
+    if (ConvOvlResult && !Sequence.getFailedCandidateSet().empty())
+      Sequence.SetOverloadFailure(
+                        InitializationSequence::FK_ReferenceInitOverloadFailed,
+                                  ConvOvlResult);
+    else
+      Sequence.SetFailed(InitializationSequence::FK_ReferenceInitFailed);
+    return;
+  }
+
+  //        [...] If T1 is reference-related to T2, cv1 must be the
+  //        same cv-qualification as, or greater cv-qualification
+  //        than, cv2; otherwise, the program is ill-formed.
+  unsigned T1CVRQuals = T1Quals.getCVRQualifiers();
+  unsigned T2CVRQuals = T2Quals.getCVRQualifiers();
+  if (RefRelationship == Sema::Ref_Related && 
+      (T1CVRQuals | T2CVRQuals) != T1CVRQuals) {
+    Sequence.SetFailed(InitializationSequence::FK_ReferenceInitDropsQualifiers);
+    return;
+  }
+
+  // Perform the actual conversion.
+  Sequence.AddConversionSequenceStep(ICS, cv1T1);
+  Sequence.AddReferenceBindingStep(cv1T1, /*bindingTemporary=*/true);
+  return;
+}
+
+/// \brief Attempt character array initialization from a string literal
+/// (C++ [dcl.init.string], C99 6.7.8). 
+static void TryStringLiteralInitialization(Sema &S, 
+                                           const InitializedEntity &Entity,
+                                           const InitializationKind &Kind,
+                                           Expr *Initializer,
+                                       InitializationSequence &Sequence) {
+  Sequence.setSequenceKind(InitializationSequence::StringInit);
+  Sequence.AddStringInitStep(Entity.getType());
+}
+
+/// \brief Attempt initialization by constructor (C++ [dcl.init]), which
+/// enumerates the constructors of the initialized entity and performs overload
+/// resolution to select the best.
+static void TryConstructorInitialization(Sema &S, 
+                                         const InitializedEntity &Entity,
+                                         const InitializationKind &Kind,
+                                         Expr **Args, unsigned NumArgs,
+                                         QualType DestType,
+                                         InitializationSequence &Sequence) {
+  if (Kind.getKind() == InitializationKind::IK_Copy)
+    Sequence.setSequenceKind(InitializationSequence::UserDefinedConversion);
+  else
+    Sequence.setSequenceKind(InitializationSequence::ConstructorInitialization);
+  
+  // Build the candidate set directly in the initialization sequence
+  // structure, so that it will persist if we fail.
+  OverloadCandidateSet &CandidateSet = Sequence.getFailedCandidateSet();
+  CandidateSet.clear();
+  
+  // Determine whether we are allowed to call explicit constructors or
+  // explicit conversion operators.
+  bool AllowExplicit = (Kind.getKind() == InitializationKind::IK_Direct ||
+                        Kind.getKind() == InitializationKind::IK_Value ||
+                        Kind.getKind() == InitializationKind::IK_Default);                      
+  
+  // The type we're converting to is a class type. Enumerate its constructors
+  // to see if one is suitable.
+  const RecordType *DestRecordType = DestType->getAs<RecordType>();
+  assert(DestRecordType && "Constructor initialization requires record type");  
+  CXXRecordDecl *DestRecordDecl
+    = cast<CXXRecordDecl>(DestRecordType->getDecl());
+    
+  DeclarationName ConstructorName
+    = S.Context.DeclarationNames.getCXXConstructorName(
+                     S.Context.getCanonicalType(DestType).getUnqualifiedType());
+  DeclContext::lookup_iterator Con, ConEnd;
+  for (llvm::tie(Con, ConEnd) = DestRecordDecl->lookup(ConstructorName);
+       Con != ConEnd; ++Con) {
+    // Find the constructor (which may be a template).
+    CXXConstructorDecl *Constructor = 0;
+    FunctionTemplateDecl *ConstructorTmpl
+      = dyn_cast<FunctionTemplateDecl>(*Con);
+    if (ConstructorTmpl)
+      Constructor = cast<CXXConstructorDecl>(
+                                           ConstructorTmpl->getTemplatedDecl());
+    else
+      Constructor = cast<CXXConstructorDecl>(*Con);
+    
+    if (!Constructor->isInvalidDecl() &&
+        (AllowExplicit || !Constructor->isExplicit())) {
+      if (ConstructorTmpl)
+        S.AddTemplateOverloadCandidate(ConstructorTmpl,
+                                       ConstructorTmpl->getAccess(),
+                                       /*ExplicitArgs*/ 0,
+                                       Args, NumArgs, CandidateSet);
+      else
+        S.AddOverloadCandidate(Constructor, Constructor->getAccess(),
+                               Args, NumArgs, CandidateSet);
+    }
+  }    
+    
+  SourceLocation DeclLoc = Kind.getLocation();
+  
+  // Perform overload resolution. If it fails, return the failed result.  
+  OverloadCandidateSet::iterator Best;
+  if (OverloadingResult Result 
+        = S.BestViableFunction(CandidateSet, DeclLoc, Best)) {
+    Sequence.SetOverloadFailure(
+                          InitializationSequence::FK_ConstructorOverloadFailed, 
+                                Result);
+    return;
+  }
+
+  // C++0x [dcl.init]p6:
+  //   If a program calls for the default initialization of an object
+  //   of a const-qualified type T, T shall be a class type with a
+  //   user-provided default constructor.
+  if (Kind.getKind() == InitializationKind::IK_Default &&
+      Entity.getType().isConstQualified() &&
+      cast<CXXConstructorDecl>(Best->Function)->isImplicit()) {
+    Sequence.SetFailed(InitializationSequence::FK_DefaultInitOfConst);
+    return;
+  }
+
+  // Add the constructor initialization step. Any cv-qualification conversion is
+  // subsumed by the initialization.
+  if (Kind.getKind() == InitializationKind::IK_Copy) {
+    Sequence.AddUserConversionStep(Best->Function, Best->getAccess(), DestType);
+  } else {
+    Sequence.AddConstructorInitializationStep(
+                                      cast<CXXConstructorDecl>(Best->Function), 
+                                      Best->getAccess(),
+                                      DestType);
+  }
+}
+
+/// \brief Attempt value initialization (C++ [dcl.init]p7).
+static void TryValueInitialization(Sema &S, 
+                                   const InitializedEntity &Entity,
+                                   const InitializationKind &Kind,
+                                   InitializationSequence &Sequence) {
+  // C++ [dcl.init]p5:
+  //
+  //   To value-initialize an object of type T means:
+  QualType T = Entity.getType();
+  
+  //     -- if T is an array type, then each element is value-initialized;
+  while (const ArrayType *AT = S.Context.getAsArrayType(T))
+    T = AT->getElementType();
+  
+  if (const RecordType *RT = T->getAs<RecordType>()) {
+    if (CXXRecordDecl *ClassDecl = dyn_cast<CXXRecordDecl>(RT->getDecl())) {
+      // -- if T is a class type (clause 9) with a user-declared
+      //    constructor (12.1), then the default constructor for T is
+      //    called (and the initialization is ill-formed if T has no
+      //    accessible default constructor);
+      //
+      // FIXME: we really want to refer to a single subobject of the array,
+      // but Entity doesn't have a way to capture that (yet).
+      if (ClassDecl->hasUserDeclaredConstructor())
+        return TryConstructorInitialization(S, Entity, Kind, 0, 0, T, Sequence);
+      
+      // -- if T is a (possibly cv-qualified) non-union class type
+      //    without a user-provided constructor, then the object is
+      //    zero-initialized and, if T’s implicitly-declared default
+      //    constructor is non-trivial, that constructor is called.
+      if ((ClassDecl->getTagKind() == TagDecl::TK_class ||
+           ClassDecl->getTagKind() == TagDecl::TK_struct) &&
+          !ClassDecl->hasTrivialConstructor()) {
+        Sequence.AddZeroInitializationStep(Entity.getType());
+        return TryConstructorInitialization(S, Entity, Kind, 0, 0, T, Sequence);        
+      }
+    }
+  }
+
+  Sequence.AddZeroInitializationStep(Entity.getType());
+  Sequence.setSequenceKind(InitializationSequence::ZeroInitialization);
+}
+
+/// \brief Attempt default initialization (C++ [dcl.init]p6).
+static void TryDefaultInitialization(Sema &S,
+                                     const InitializedEntity &Entity,
+                                     const InitializationKind &Kind,
+                                     InitializationSequence &Sequence) {
+  assert(Kind.getKind() == InitializationKind::IK_Default);
+  
+  // C++ [dcl.init]p6:
+  //   To default-initialize an object of type T means:
+  //     - if T is an array type, each element is default-initialized;
+  QualType DestType = Entity.getType();
+  while (const ArrayType *Array = S.Context.getAsArrayType(DestType))
+    DestType = Array->getElementType();
+         
+  //     - if T is a (possibly cv-qualified) class type (Clause 9), the default
+  //       constructor for T is called (and the initialization is ill-formed if
+  //       T has no accessible default constructor);
+  if (DestType->isRecordType() && S.getLangOptions().CPlusPlus) {
+    return TryConstructorInitialization(S, Entity, Kind, 0, 0, DestType,
+                                        Sequence);
+  }
+  
+  //     - otherwise, no initialization is performed.
+  Sequence.setSequenceKind(InitializationSequence::NoInitialization);
+  
+  //   If a program calls for the default initialization of an object of
+  //   a const-qualified type T, T shall be a class type with a user-provided 
+  //   default constructor.
+  if (DestType.isConstQualified() && S.getLangOptions().CPlusPlus)
+    Sequence.SetFailed(InitializationSequence::FK_DefaultInitOfConst);
+}
+
+/// \brief Attempt a user-defined conversion between two types (C++ [dcl.init]),
+/// which enumerates all conversion functions and performs overload resolution
+/// to select the best.
+static void TryUserDefinedConversion(Sema &S, 
+                                     const InitializedEntity &Entity,
+                                     const InitializationKind &Kind,
+                                     Expr *Initializer,
+                                     InitializationSequence &Sequence) {
+  Sequence.setSequenceKind(InitializationSequence::UserDefinedConversion);
+  
+  QualType DestType = Entity.getType();
+  assert(!DestType->isReferenceType() && "References are handled elsewhere");
+  QualType SourceType = Initializer->getType();
+  assert((DestType->isRecordType() || SourceType->isRecordType()) &&
+         "Must have a class type to perform a user-defined conversion");
+  
+  // Build the candidate set directly in the initialization sequence
+  // structure, so that it will persist if we fail.
+  OverloadCandidateSet &CandidateSet = Sequence.getFailedCandidateSet();
+  CandidateSet.clear();
+  
+  // Determine whether we are allowed to call explicit constructors or
+  // explicit conversion operators.
+  bool AllowExplicit = Kind.getKind() == InitializationKind::IK_Direct;
+  
+  if (const RecordType *DestRecordType = DestType->getAs<RecordType>()) {
+    // The type we're converting to is a class type. Enumerate its constructors
+    // to see if there is a suitable conversion.
+    CXXRecordDecl *DestRecordDecl
+      = cast<CXXRecordDecl>(DestRecordType->getDecl());
+    
+    DeclarationName ConstructorName
+      = S.Context.DeclarationNames.getCXXConstructorName(
+                     S.Context.getCanonicalType(DestType).getUnqualifiedType());
+    DeclContext::lookup_iterator Con, ConEnd;
+    for (llvm::tie(Con, ConEnd) = DestRecordDecl->lookup(ConstructorName);
+         Con != ConEnd; ++Con) {
+      // Find the constructor (which may be a template).
+      CXXConstructorDecl *Constructor = 0;
+      FunctionTemplateDecl *ConstructorTmpl
+        = dyn_cast<FunctionTemplateDecl>(*Con);
+      if (ConstructorTmpl)
+        Constructor = cast<CXXConstructorDecl>(
+                                           ConstructorTmpl->getTemplatedDecl());
+      else
+        Constructor = cast<CXXConstructorDecl>(*Con);
+      
+      if (!Constructor->isInvalidDecl() &&
+          Constructor->isConvertingConstructor(AllowExplicit)) {
+        if (ConstructorTmpl)
+          S.AddTemplateOverloadCandidate(ConstructorTmpl,
+                                         ConstructorTmpl->getAccess(),
+                                         /*ExplicitArgs*/ 0,
+                                         &Initializer, 1, CandidateSet);
+        else
+          S.AddOverloadCandidate(Constructor, Constructor->getAccess(),
+                                 &Initializer, 1, CandidateSet);
+      }
+    }    
+  }
+
+  SourceLocation DeclLoc = Initializer->getLocStart();
+
+  if (const RecordType *SourceRecordType = SourceType->getAs<RecordType>()) {
+    // The type we're converting from is a class type, enumerate its conversion
+    // functions.
+
+    // We can only enumerate the conversion functions for a complete type; if
+    // the type isn't complete, simply skip this step.
+    if (!S.RequireCompleteType(DeclLoc, SourceType, 0)) {
+      CXXRecordDecl *SourceRecordDecl
+        = cast<CXXRecordDecl>(SourceRecordType->getDecl());
+      
+      const UnresolvedSetImpl *Conversions
+        = SourceRecordDecl->getVisibleConversionFunctions();
+      for (UnresolvedSetImpl::const_iterator I = Conversions->begin(),
+           E = Conversions->end(); 
+           I != E; ++I) {
+        NamedDecl *D = *I;
+        CXXRecordDecl *ActingDC = cast<CXXRecordDecl>(D->getDeclContext());
+        if (isa<UsingShadowDecl>(D))
+          D = cast<UsingShadowDecl>(D)->getTargetDecl();
+        
+        FunctionTemplateDecl *ConvTemplate = dyn_cast<FunctionTemplateDecl>(D);
+        CXXConversionDecl *Conv;
+        if (ConvTemplate)
+          Conv = cast<CXXConversionDecl>(ConvTemplate->getTemplatedDecl());
+        else
+          Conv = cast<CXXConversionDecl>(*I);
+        
+        if (AllowExplicit || !Conv->isExplicit()) {
+          if (ConvTemplate)
+            S.AddTemplateConversionCandidate(ConvTemplate, I.getAccess(),
+                                             ActingDC, Initializer, DestType,
+                                             CandidateSet);
+          else
+            S.AddConversionCandidate(Conv, I.getAccess(), ActingDC,
+                                     Initializer, DestType, CandidateSet);
+        }
+      }
+    }
+  }
+  
+  // Perform overload resolution. If it fails, return the failed result.  
+  OverloadCandidateSet::iterator Best;
+  if (OverloadingResult Result
+        = S.BestViableFunction(CandidateSet, DeclLoc, Best)) {
+    Sequence.SetOverloadFailure(
+                        InitializationSequence::FK_UserConversionOverloadFailed, 
+                                Result);
+    return;
+  }
+
+  FunctionDecl *Function = Best->Function;
+  
+  if (isa<CXXConstructorDecl>(Function)) {
+    // Add the user-defined conversion step. Any cv-qualification conversion is
+    // subsumed by the initialization.
+    Sequence.AddUserConversionStep(Function, Best->getAccess(), DestType);
+    return;
+  }
+
+  // Add the user-defined conversion step that calls the conversion function.
+  QualType ConvType = Function->getResultType().getNonReferenceType();
+  Sequence.AddUserConversionStep(Function, Best->getAccess(), ConvType);
+
+  // If the conversion following the call to the conversion function is 
+  // interesting, add it as a separate step.
+  if (Best->FinalConversion.First || Best->FinalConversion.Second ||
+      Best->FinalConversion.Third) {
+    ImplicitConversionSequence ICS;
+    ICS.setStandard();
+    ICS.Standard = Best->FinalConversion;
+    Sequence.AddConversionSequenceStep(ICS, DestType);
+  }
+}
+
+/// \brief Attempt an implicit conversion (C++ [conv]) converting from one
+/// non-class type to another.
+static void TryImplicitConversion(Sema &S, 
+                                  const InitializedEntity &Entity,
+                                  const InitializationKind &Kind,
+                                  Expr *Initializer,
+                                  InitializationSequence &Sequence) {
+  ImplicitConversionSequence ICS
+    = S.TryImplicitConversion(Initializer, Entity.getType(),
+                              /*SuppressUserConversions=*/true, 
+                              /*AllowExplicit=*/false,
+                              /*ForceRValue=*/false, 
+                              /*FIXME:InOverloadResolution=*/false,
+                              /*UserCast=*/Kind.isExplicitCast());
+  
+  if (ICS.isBad()) {
+    Sequence.SetFailed(InitializationSequence::FK_ConversionFailed);
+    return;
+  }
+  
+  Sequence.AddConversionSequenceStep(ICS, Entity.getType());
+}
+
+InitializationSequence::InitializationSequence(Sema &S,
+                                               const InitializedEntity &Entity,
+                                               const InitializationKind &Kind,
+                                               Expr **Args,
+                                               unsigned NumArgs)
+    : FailedCandidateSet(Kind.getLocation()) {
+  ASTContext &Context = S.Context;
+  
+  // C++0x [dcl.init]p16:
+  //   The semantics of initializers are as follows. The destination type is 
+  //   the type of the object or reference being initialized and the source 
+  //   type is the type of the initializer expression. The source type is not
+  //   defined when the initializer is a braced-init-list or when it is a 
+  //   parenthesized list of expressions.
+  QualType DestType = Entity.getType();
+
+  if (DestType->isDependentType() ||
+      Expr::hasAnyTypeDependentArguments(Args, NumArgs)) {
+    SequenceKind = DependentSequence;
+    return;
+  }
+
+  QualType SourceType;
+  Expr *Initializer = 0;
+  if (NumArgs == 1) {
+    Initializer = Args[0];
+    if (!isa<InitListExpr>(Initializer))
+      SourceType = Initializer->getType();
+  }
+  
+  //     - If the initializer is a braced-init-list, the object is 
+  //       list-initialized (8.5.4).
+  if (InitListExpr *InitList = dyn_cast_or_null<InitListExpr>(Initializer)) {
+    TryListInitialization(S, Entity, Kind, InitList, *this);
+    return;
+  }
+  
+  //     - If the destination type is a reference type, see 8.5.3.
+  if (DestType->isReferenceType()) {
+    // C++0x [dcl.init.ref]p1:
+    //   A variable declared to be a T& or T&&, that is, "reference to type T"
+    //   (8.3.2), shall be initialized by an object, or function, of type T or
+    //   by an object that can be converted into a T.
+    // (Therefore, multiple arguments are not permitted.)
+    if (NumArgs != 1)
+      SetFailed(FK_TooManyInitsForReference);
+    else
+      TryReferenceInitialization(S, Entity, Kind, Args[0], *this);
+    return;
+  }
+  
+  //     - If the destination type is an array of characters, an array of 
+  //       char16_t, an array of char32_t, or an array of wchar_t, and the 
+  //       initializer is a string literal, see 8.5.2.
+  if (Initializer && IsStringInit(Initializer, DestType, Context)) {
+    TryStringLiteralInitialization(S, Entity, Kind, Initializer, *this);
+    return;
+  }
+  
+  //     - If the initializer is (), the object is value-initialized.
+  if (Kind.getKind() == InitializationKind::IK_Value ||
+      (Kind.getKind() == InitializationKind::IK_Direct && NumArgs == 0)) {
+    TryValueInitialization(S, Entity, Kind, *this);
+    return;
+  }
+  
+  // Handle default initialization.
+  if (Kind.getKind() == InitializationKind::IK_Default){
+    TryDefaultInitialization(S, Entity, Kind, *this);
+    return;
+  }
+
+  //     - Otherwise, if the destination type is an array, the program is 
+  //       ill-formed.
+  if (const ArrayType *AT = Context.getAsArrayType(DestType)) {
+    if (AT->getElementType()->isAnyCharacterType())
+      SetFailed(FK_ArrayNeedsInitListOrStringLiteral);
+    else
+      SetFailed(FK_ArrayNeedsInitList);
+    
+    return;
+  }
+
+  // Handle initialization in C
+  if (!S.getLangOptions().CPlusPlus) {
+    setSequenceKind(CAssignment);
+    AddCAssignmentStep(DestType);
+    return;
+  }
+  
+  //     - If the destination type is a (possibly cv-qualified) class type:
+  if (DestType->isRecordType()) {
+    //     - If the initialization is direct-initialization, or if it is 
+    //       copy-initialization where the cv-unqualified version of the 
+    //       source type is the same class as, or a derived class of, the 
+    //       class of the destination, constructors are considered. [...]
+    if (Kind.getKind() == InitializationKind::IK_Direct ||
+        (Kind.getKind() == InitializationKind::IK_Copy &&
+         (Context.hasSameUnqualifiedType(SourceType, DestType) ||
+          S.IsDerivedFrom(SourceType, DestType))))
+      TryConstructorInitialization(S, Entity, Kind, Args, NumArgs, 
+                                   Entity.getType(), *this);
+    //     - Otherwise (i.e., for the remaining copy-initialization cases), 
+    //       user-defined conversion sequences that can convert from the source
+    //       type to the destination type or (when a conversion function is 
+    //       used) to a derived class thereof are enumerated as described in
+    //       13.3.1.4, and the best one is chosen through overload resolution
+    //       (13.3).
+    else
+      TryUserDefinedConversion(S, Entity, Kind, Initializer, *this);
+    return;
+  }
+  
+  if (NumArgs > 1) {
+    SetFailed(FK_TooManyInitsForScalar);
+    return;
+  }
+  assert(NumArgs == 1 && "Zero-argument case handled above");
+  
+  //    - Otherwise, if the source type is a (possibly cv-qualified) class 
+  //      type, conversion functions are considered.
+  if (!SourceType.isNull() && SourceType->isRecordType()) {
+    TryUserDefinedConversion(S, Entity, Kind, Initializer, *this);
+    return;
+  }
+  
+  //    - Otherwise, the initial value of the object being initialized is the
+  //      (possibly converted) value of the initializer expression. Standard
+  //      conversions (Clause 4) will be used, if necessary, to convert the
+  //      initializer expression to the cv-unqualified version of the 
+  //      destination type; no user-defined conversions are considered.
+  setSequenceKind(StandardConversion);
+  TryImplicitConversion(S, Entity, Kind, Initializer, *this);
+}
+
+InitializationSequence::~InitializationSequence() {
+  for (llvm::SmallVectorImpl<Step>::iterator Step = Steps.begin(),
+                                          StepEnd = Steps.end();
+       Step != StepEnd; ++Step)
+    Step->Destroy();
+}
+
+//===----------------------------------------------------------------------===//
+// Perform initialization
+//===----------------------------------------------------------------------===//
+static Sema::AssignmentAction 
+getAssignmentAction(const InitializedEntity &Entity) {
+  switch(Entity.getKind()) {
+  case InitializedEntity::EK_Variable:
+  case InitializedEntity::EK_New:
+    return Sema::AA_Initializing;
+
+  case InitializedEntity::EK_Parameter:
+    // FIXME: Can we tell when we're sending vs. passing?
+    return Sema::AA_Passing;
+
+  case InitializedEntity::EK_Result:
+    return Sema::AA_Returning;
+
+  case InitializedEntity::EK_Exception:
+  case InitializedEntity::EK_Base:
+    llvm_unreachable("No assignment action for C++-specific initialization");
+    break;
+
+  case InitializedEntity::EK_Temporary:
+    // FIXME: Can we tell apart casting vs. converting?
+    return Sema::AA_Casting;
+    
+  case InitializedEntity::EK_Member:
+  case InitializedEntity::EK_ArrayElement:
+  case InitializedEntity::EK_VectorElement:
+    return Sema::AA_Initializing;
+  }
+
+  return Sema::AA_Converting;
+}
+
+static bool shouldBindAsTemporary(const InitializedEntity &Entity,
+                                  bool IsCopy) {
+  switch (Entity.getKind()) {
+  case InitializedEntity::EK_Result:
+  case InitializedEntity::EK_ArrayElement:
+  case InitializedEntity::EK_Member:
+    return !IsCopy;
+      
+  case InitializedEntity::EK_New:
+  case InitializedEntity::EK_Variable:
+  case InitializedEntity::EK_Base:
+  case InitializedEntity::EK_VectorElement:
+  case InitializedEntity::EK_Exception:
+    return false;
+    
+  case InitializedEntity::EK_Parameter:
+  case InitializedEntity::EK_Temporary:
+    return true;
+  }
+  
+  llvm_unreachable("missed an InitializedEntity kind?");
+}
+
+/// \brief If we need to perform an additional copy of the initialized object
+/// for this kind of entity (e.g., the result of a function or an object being
+/// thrown), make the copy. 
+static Sema::OwningExprResult CopyIfRequiredForEntity(Sema &S,
+                                            const InitializedEntity &Entity,
+                                             const InitializationKind &Kind,
+                                             Sema::OwningExprResult CurInit) {
+  Expr *CurInitExpr = (Expr *)CurInit.get();
+  
+  SourceLocation Loc;
+  
+  switch (Entity.getKind()) {
+  case InitializedEntity::EK_Result:
+    if (Entity.getType()->isReferenceType())
+      return move(CurInit);
+    Loc = Entity.getReturnLoc();
+    break;
+      
+  case InitializedEntity::EK_Exception:
+    Loc = Entity.getThrowLoc();
+    break;
+    
+  case InitializedEntity::EK_Variable:
+    if (Entity.getType()->isReferenceType() ||
+        Kind.getKind() != InitializationKind::IK_Copy)
+      return move(CurInit);
+    Loc = Entity.getDecl()->getLocation();
+    break;
+
+  case InitializedEntity::EK_ArrayElement:
+  case InitializedEntity::EK_Member:
+    if (Entity.getType()->isReferenceType() ||
+        Kind.getKind() != InitializationKind::IK_Copy)
+      return move(CurInit);
+    Loc = CurInitExpr->getLocStart();
+    break;
+
+  case InitializedEntity::EK_Parameter:
+    // FIXME: Do we need this initialization for a parameter?
+    return move(CurInit);
+
+  case InitializedEntity::EK_New:
+  case InitializedEntity::EK_Temporary:
+  case InitializedEntity::EK_Base:
+  case InitializedEntity::EK_VectorElement:
+    // We don't need to copy for any of these initialized entities.
+    return move(CurInit);
+  }
+  
+  CXXRecordDecl *Class = 0; 
+  if (const RecordType *Record = CurInitExpr->getType()->getAs<RecordType>())
+    Class = cast<CXXRecordDecl>(Record->getDecl());
+  if (!Class)
+    return move(CurInit);
+  
+  // Perform overload resolution using the class's copy constructors.
+  DeclarationName ConstructorName
+    = S.Context.DeclarationNames.getCXXConstructorName(
+                  S.Context.getCanonicalType(S.Context.getTypeDeclType(Class)));
+  DeclContext::lookup_iterator Con, ConEnd;
+  OverloadCandidateSet CandidateSet(Loc);
+  for (llvm::tie(Con, ConEnd) = Class->lookup(ConstructorName);
+       Con != ConEnd; ++Con) {
+    // Find the constructor (which may be a template).
+    CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(*Con);
+    if (!Constructor || Constructor->isInvalidDecl() ||
+        !Constructor->isCopyConstructor())
+      continue;
+    
+    S.AddOverloadCandidate(Constructor, Constructor->getAccess(),
+                           &CurInitExpr, 1, CandidateSet);
+  }    
+  
+  OverloadCandidateSet::iterator Best;
+  switch (S.BestViableFunction(CandidateSet, Loc, Best)) {
+  case OR_Success:
+    break;
+      
+  case OR_No_Viable_Function:
+    S.Diag(Loc, diag::err_temp_copy_no_viable)
+      << (int)Entity.getKind() << CurInitExpr->getType()
+      << CurInitExpr->getSourceRange();
+    S.PrintOverloadCandidates(CandidateSet, Sema::OCD_AllCandidates,
+                              &CurInitExpr, 1);
+    return S.ExprError();
+      
+  case OR_Ambiguous:
+    S.Diag(Loc, diag::err_temp_copy_ambiguous)
+      << (int)Entity.getKind() << CurInitExpr->getType()
+      << CurInitExpr->getSourceRange();
+    S.PrintOverloadCandidates(CandidateSet, Sema::OCD_ViableCandidates,
+                              &CurInitExpr, 1);
+    return S.ExprError();
+    
+  case OR_Deleted:
+    S.Diag(Loc, diag::err_temp_copy_deleted)
+      << (int)Entity.getKind() << CurInitExpr->getType()
+      << CurInitExpr->getSourceRange();
+    S.Diag(Best->Function->getLocation(), diag::note_unavailable_here)
+      << Best->Function->isDeleted();
+    return S.ExprError();
+  }
+
+  CurInit.release();
+  return S.BuildCXXConstructExpr(Loc, CurInitExpr->getType(),
+                                 cast<CXXConstructorDecl>(Best->Function),
+                                 /*Elidable=*/true,
+                                 Sema::MultiExprArg(S, 
+                                                    (void**)&CurInitExpr, 1));
+}
+
+Action::OwningExprResult 
+InitializationSequence::Perform(Sema &S,
+                                const InitializedEntity &Entity,
+                                const InitializationKind &Kind,
+                                Action::MultiExprArg Args,
+                                QualType *ResultType) {
+  if (SequenceKind == FailedSequence) {
+    unsigned NumArgs = Args.size();
+    Diagnose(S, Entity, Kind, (Expr **)Args.release(), NumArgs);
+    return S.ExprError();
+  }
+  
+  if (SequenceKind == DependentSequence) {
+    // If the declaration is a non-dependent, incomplete array type
+    // that has an initializer, then its type will be completed once
+    // the initializer is instantiated.
+    if (ResultType && !Entity.getType()->isDependentType() &&
+        Args.size() == 1) {
+      QualType DeclType = Entity.getType();
+      if (const IncompleteArrayType *ArrayT
+                           = S.Context.getAsIncompleteArrayType(DeclType)) {
+        // FIXME: We don't currently have the ability to accurately
+        // compute the length of an initializer list without
+        // performing full type-checking of the initializer list
+        // (since we have to determine where braces are implicitly
+        // introduced and such).  So, we fall back to making the array
+        // type a dependently-sized array type with no specified
+        // bound.
+        if (isa<InitListExpr>((Expr *)Args.get()[0])) {
+          SourceRange Brackets;
+
+          // Scavange the location of the brackets from the entity, if we can.
+          if (DeclaratorDecl *DD = Entity.getDecl()) {
+            if (TypeSourceInfo *TInfo = DD->getTypeSourceInfo()) {
+              TypeLoc TL = TInfo->getTypeLoc();
+              if (IncompleteArrayTypeLoc *ArrayLoc
+                                      = dyn_cast<IncompleteArrayTypeLoc>(&TL))
+              Brackets = ArrayLoc->getBracketsRange();
+            }
+          }
+
+          *ResultType
+            = S.Context.getDependentSizedArrayType(ArrayT->getElementType(),
+                                                   /*NumElts=*/0,
+                                                   ArrayT->getSizeModifier(),
+                                       ArrayT->getIndexTypeCVRQualifiers(),
+                                                   Brackets);
+        }
+
+      }
+    }
+
+    if (Kind.getKind() == InitializationKind::IK_Copy || Kind.isExplicitCast())
+      return Sema::OwningExprResult(S, Args.release()[0]);
+
+    if (Args.size() == 0)
+      return S.Owned((Expr *)0);
+
+    unsigned NumArgs = Args.size();
+    return S.Owned(new (S.Context) ParenListExpr(S.Context,
+                                                 SourceLocation(),
+                                                 (Expr **)Args.release(), 
+                                                 NumArgs,
+                                                 SourceLocation()));
+  }
+
+  if (SequenceKind == NoInitialization)
+    return S.Owned((Expr *)0);
+  
+  QualType DestType = Entity.getType().getNonReferenceType();
+  // FIXME: Ugly hack around the fact that Entity.getType() is not
+  // the same as Entity.getDecl()->getType() in cases involving type merging,
+  //  and we want latter when it makes sense.
+  if (ResultType)
+    *ResultType = Entity.getDecl() ? Entity.getDecl()->getType() :
+                                     Entity.getType();
+
+  Sema::OwningExprResult CurInit = S.Owned((Expr *)0);
+  
+  assert(!Steps.empty() && "Cannot have an empty initialization sequence");
+  
+  // For initialization steps that start with a single initializer, 
+  // grab the only argument out the Args and place it into the "current"
+  // initializer.
+  switch (Steps.front().Kind) {
+  case SK_ResolveAddressOfOverloadedFunction:
+  case SK_CastDerivedToBaseRValue:
+  case SK_CastDerivedToBaseLValue:
+  case SK_BindReference:
+  case SK_BindReferenceToTemporary:
+  case SK_UserConversion:
+  case SK_QualificationConversionLValue:
+  case SK_QualificationConversionRValue:
+  case SK_ConversionSequence:
+  case SK_ListInitialization:
+  case SK_CAssignment:
+  case SK_StringInit:
+    assert(Args.size() == 1);
+    CurInit = Sema::OwningExprResult(S, ((Expr **)(Args.get()))[0]->Retain());
+    if (CurInit.isInvalid())
+      return S.ExprError();
+    break;
+    
+  case SK_ConstructorInitialization:
+  case SK_ZeroInitialization:
+    break;
+  }
+    
+  // Walk through the computed steps for the initialization sequence, 
+  // performing the specified conversions along the way.
+  bool ConstructorInitRequiresZeroInit = false;
+  for (step_iterator Step = step_begin(), StepEnd = step_end();
+       Step != StepEnd; ++Step) {
+    if (CurInit.isInvalid())
+      return S.ExprError();
+    
+    Expr *CurInitExpr = (Expr *)CurInit.get();
+    QualType SourceType = CurInitExpr? CurInitExpr->getType() : QualType();
+    
+    switch (Step->Kind) {
+    case SK_ResolveAddressOfOverloadedFunction:
+      // Overload resolution determined which function invoke; update the 
+      // initializer to reflect that choice.
+      // Access control was done in overload resolution.
+      CurInit = S.FixOverloadedFunctionReference(move(CurInit),
+                              cast<FunctionDecl>(Step->Function.getDecl()));
+      break;
+        
+    case SK_CastDerivedToBaseRValue:
+    case SK_CastDerivedToBaseLValue: {
+      // We have a derived-to-base cast that produces either an rvalue or an
+      // lvalue. Perform that cast.
+      
+      // Casts to inaccessible base classes are allowed with C-style casts.
+      bool IgnoreBaseAccess = Kind.isCStyleOrFunctionalCast();
+      if (S.CheckDerivedToBaseConversion(SourceType, Step->Type,
+                                         CurInitExpr->getLocStart(),
+                                         CurInitExpr->getSourceRange(),
+                                         IgnoreBaseAccess))
+        return S.ExprError();
+        
+      CurInit = S.Owned(new (S.Context) ImplicitCastExpr(Step->Type,
+                                                    CastExpr::CK_DerivedToBase,
+                                                      (Expr*)CurInit.release(),
+                                     Step->Kind == SK_CastDerivedToBaseLValue));
+      break;
+    }
+        
+    case SK_BindReference:
+      if (FieldDecl *BitField = CurInitExpr->getBitField()) {
+        // References cannot bind to bit fields (C++ [dcl.init.ref]p5).
+        S.Diag(Kind.getLocation(), diag::err_reference_bind_to_bitfield)
+          << Entity.getType().isVolatileQualified()
+          << BitField->getDeclName()
+          << CurInitExpr->getSourceRange();
+        S.Diag(BitField->getLocation(), diag::note_bitfield_decl);
+        return S.ExprError();
+      }
+
+      if (CurInitExpr->refersToVectorElement()) {
+        // References cannot bind to vector elements.
+        S.Diag(Kind.getLocation(), diag::err_reference_bind_to_vector_element)
+          << Entity.getType().isVolatileQualified()
+          << CurInitExpr->getSourceRange();
+        return S.ExprError();
+      }
+        
+      // Reference binding does not have any corresponding ASTs.
+
+      // Check exception specifications
+      if (S.CheckExceptionSpecCompatibility(CurInitExpr, DestType))
+        return S.ExprError();
+
+      break;
+
+    case SK_BindReferenceToTemporary:
+      // Reference binding does not have any corresponding ASTs.
+
+      // Check exception specifications
+      if (S.CheckExceptionSpecCompatibility(CurInitExpr, DestType))
+        return S.ExprError();
+
+      break;
+        
+    case SK_UserConversion: {
+      // We have a user-defined conversion that invokes either a constructor
+      // or a conversion function.
+      CastExpr::CastKind CastKind = CastExpr::CK_Unknown;
+      bool IsCopy = false;
+      FunctionDecl *Fn = cast<FunctionDecl>(Step->Function.getDecl());
+      AccessSpecifier FnAccess = Step->Function.getAccess();
+      if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(Fn)) {
+        // Build a call to the selected constructor.
+        ASTOwningVector<&ActionBase::DeleteExpr> ConstructorArgs(S);
+        SourceLocation Loc = CurInitExpr->getLocStart();
+        CurInit.release(); // Ownership transferred into MultiExprArg, below.
+
+        // Determine the arguments required to actually perform the constructor
+        // call.
+        if (S.CompleteConstructorCall(Constructor,
+                                      Sema::MultiExprArg(S, 
+                                                         (void **)&CurInitExpr,
+                                                         1),
+                                      Loc, ConstructorArgs))
+          return S.ExprError();
+        
+        // Build the an expression that constructs a temporary.
+        CurInit = S.BuildCXXConstructExpr(Loc, Step->Type, Constructor, 
+                                          move_arg(ConstructorArgs));
+        if (CurInit.isInvalid())
+          return S.ExprError();
+
+        S.CheckConstructorAccess(Kind.getLocation(), Constructor, FnAccess);
+        
+        CastKind = CastExpr::CK_ConstructorConversion;
+        QualType Class = S.Context.getTypeDeclType(Constructor->getParent());
+        if (S.Context.hasSameUnqualifiedType(SourceType, Class) ||
+            S.IsDerivedFrom(SourceType, Class))
+          IsCopy = true;
+      } else {
+        // Build a call to the conversion function.
+        CXXConversionDecl *Conversion = cast<CXXConversionDecl>(Fn);
+
+        S.CheckMemberOperatorAccess(Kind.getLocation(), CurInitExpr,
+                                    Conversion, FnAccess);
+        
+        // FIXME: Should we move this initialization into a separate 
+        // derived-to-base conversion? I believe the answer is "no", because
+        // we don't want to turn off access control here for c-style casts.
+        if (S.PerformObjectArgumentInitialization(CurInitExpr, Conversion))
+          return S.ExprError();
+
+        // Do a little dance to make sure that CurInit has the proper
+        // pointer.
+        CurInit.release();
+        
+        // Build the actual call to the conversion function.
+        CurInit = S.Owned(S.BuildCXXMemberCallExpr(CurInitExpr, Conversion));
+        if (CurInit.isInvalid() || !CurInit.get())
+          return S.ExprError();
+        
+        CastKind = CastExpr::CK_UserDefinedConversion;
+      }
+      
+      if (shouldBindAsTemporary(Entity, IsCopy))
+        CurInit = S.MaybeBindToTemporary(CurInit.takeAs<Expr>());
+
+      CurInitExpr = CurInit.takeAs<Expr>();
+      CurInit = S.Owned(new (S.Context) ImplicitCastExpr(CurInitExpr->getType(),
+                                                         CastKind, 
+                                                         CurInitExpr,
+                                                         false));
+      
+      if (!IsCopy)
+        CurInit = CopyIfRequiredForEntity(S, Entity, Kind, move(CurInit));
+      break;
+    }
+        
+    case SK_QualificationConversionLValue:
+    case SK_QualificationConversionRValue:
+      // Perform a qualification conversion; these can never go wrong.
+      S.ImpCastExprToType(CurInitExpr, Step->Type,
+                          CastExpr::CK_NoOp, 
+                          Step->Kind == SK_QualificationConversionLValue);
+      CurInit.release();
+      CurInit = S.Owned(CurInitExpr);
+      break;
+        
+    case SK_ConversionSequence:
+        if (S.PerformImplicitConversion(CurInitExpr, Step->Type, Sema::AA_Converting, 
+                                      false, false, *Step->ICS))
+        return S.ExprError();
+        
+      CurInit.release();
+      CurInit = S.Owned(CurInitExpr);        
+      break;
+
+    case SK_ListInitialization: {
+      InitListExpr *InitList = cast<InitListExpr>(CurInitExpr);
+      QualType Ty = Step->Type;
+      if (S.CheckInitList(Entity, InitList, ResultType? *ResultType : Ty))
+        return S.ExprError();
+
+      CurInit.release();
+      CurInit = S.Owned(InitList);
+      break;
+    }
+
+    case SK_ConstructorInitialization: {
+      CXXConstructorDecl *Constructor
+        = cast<CXXConstructorDecl>(Step->Function.getDecl());
+
+      // Build a call to the selected constructor.
+      ASTOwningVector<&ActionBase::DeleteExpr> ConstructorArgs(S);
+      SourceLocation Loc = Kind.getLocation();
+          
+      // Determine the arguments required to actually perform the constructor
+      // call.
+      if (S.CompleteConstructorCall(Constructor, move(Args), 
+                                    Loc, ConstructorArgs))
+        return S.ExprError();
+          
+      // Build the an expression that constructs a temporary.
+      CurInit = S.BuildCXXConstructExpr(Loc, Entity.getType(),
+                                        Constructor, 
+                                        move_arg(ConstructorArgs),
+                                        ConstructorInitRequiresZeroInit,
+                               Entity.getKind() == InitializedEntity::EK_Base);
+      if (CurInit.isInvalid())
+        return S.ExprError();
+
+      // Only check access if all of that succeeded.
+      S.CheckConstructorAccess(Loc, Constructor, Step->Function.getAccess());
+      
+      bool Elidable 
+        = cast<CXXConstructExpr>((Expr *)CurInit.get())->isElidable();
+      if (shouldBindAsTemporary(Entity, Elidable))
+        CurInit = S.MaybeBindToTemporary(CurInit.takeAs<Expr>());
+      
+      if (!Elidable)
+        CurInit = CopyIfRequiredForEntity(S, Entity, Kind, move(CurInit));
+      break;
+    }
+        
+    case SK_ZeroInitialization: {
+      step_iterator NextStep = Step;
+      ++NextStep;
+      if (NextStep != StepEnd && 
+          NextStep->Kind == SK_ConstructorInitialization) {
+        // The need for zero-initialization is recorded directly into
+        // the call to the object's constructor within the next step.
+        ConstructorInitRequiresZeroInit = true;
+      } else if (Kind.getKind() == InitializationKind::IK_Value &&
+                 S.getLangOptions().CPlusPlus &&
+                 !Kind.isImplicitValueInit()) {
+        CurInit = S.Owned(new (S.Context) CXXZeroInitValueExpr(Step->Type,
+                                                   Kind.getRange().getBegin(),
+                                                    Kind.getRange().getEnd()));
+      } else {
+        CurInit = S.Owned(new (S.Context) ImplicitValueInitExpr(Step->Type));
+      }
+      break;
+    }
+
+    case SK_CAssignment: {
+      QualType SourceType = CurInitExpr->getType();
+      Sema::AssignConvertType ConvTy =
+        S.CheckSingleAssignmentConstraints(Step->Type, CurInitExpr);
+
+      // If this is a call, allow conversion to a transparent union.
+      if (ConvTy != Sema::Compatible &&
+          Entity.getKind() == InitializedEntity::EK_Parameter &&
+          S.CheckTransparentUnionArgumentConstraints(Step->Type, CurInitExpr)
+            == Sema::Compatible)
+        ConvTy = Sema::Compatible;
+
+      if (S.DiagnoseAssignmentResult(ConvTy, Kind.getLocation(),
+                                     Step->Type, SourceType,
+                                     CurInitExpr, getAssignmentAction(Entity)))
+        return S.ExprError();
+
+      CurInit.release();
+      CurInit = S.Owned(CurInitExpr);
+      break;
+    }
+
+    case SK_StringInit: {
+      QualType Ty = Step->Type;
+      CheckStringInit(CurInitExpr, ResultType ? *ResultType : Ty, S);
+      break;
+    }
+    }
+  }
+  
+  return move(CurInit);
+}
+
+//===----------------------------------------------------------------------===//
+// Diagnose initialization failures
+//===----------------------------------------------------------------------===//
+bool InitializationSequence::Diagnose(Sema &S, 
+                                      const InitializedEntity &Entity,
+                                      const InitializationKind &Kind,
+                                      Expr **Args, unsigned NumArgs) {
+  if (SequenceKind != FailedSequence)
+    return false;
+  
+  QualType DestType = Entity.getType();
+  switch (Failure) {
+  case FK_TooManyInitsForReference:
+    // FIXME: Customize for the initialized entity?
+    if (NumArgs == 0)
+      S.Diag(Kind.getLocation(), diag::err_reference_without_init)
+        << DestType.getNonReferenceType();
+    else  // FIXME: diagnostic below could be better!
+      S.Diag(Kind.getLocation(), diag::err_reference_has_multiple_inits)
+        << SourceRange(Args[0]->getLocStart(), Args[NumArgs - 1]->getLocEnd());
+    break;
+    
+  case FK_ArrayNeedsInitList:
+  case FK_ArrayNeedsInitListOrStringLiteral:
+    S.Diag(Kind.getLocation(), diag::err_array_init_not_init_list)
+      << (Failure == FK_ArrayNeedsInitListOrStringLiteral);
+    break;
+      
+  case FK_AddressOfOverloadFailed:
+    S.ResolveAddressOfOverloadedFunction(Args[0], 
+                                         DestType.getNonReferenceType(),
+                                         true);
+    break;
+      
+  case FK_ReferenceInitOverloadFailed:
+  case FK_UserConversionOverloadFailed:
+    switch (FailedOverloadResult) {
+    case OR_Ambiguous:
+      if (Failure == FK_UserConversionOverloadFailed)
+        S.Diag(Kind.getLocation(), diag::err_typecheck_ambiguous_condition)
+          << Args[0]->getType() << DestType
+          << Args[0]->getSourceRange();
+      else
+        S.Diag(Kind.getLocation(), diag::err_ref_init_ambiguous)
+          << DestType << Args[0]->getType()
+          << Args[0]->getSourceRange();
+
+      S.PrintOverloadCandidates(FailedCandidateSet, Sema::OCD_ViableCandidates,
+                                Args, NumArgs);
+      break;
+        
+    case OR_No_Viable_Function:
+      S.Diag(Kind.getLocation(), diag::err_typecheck_nonviable_condition)
+        << Args[0]->getType() << DestType.getNonReferenceType()
+        << Args[0]->getSourceRange();
+      S.PrintOverloadCandidates(FailedCandidateSet, Sema::OCD_AllCandidates,
+                                Args, NumArgs);
+      break;
+        
+    case OR_Deleted: {
+      S.Diag(Kind.getLocation(), diag::err_typecheck_deleted_function)
+        << Args[0]->getType() << DestType.getNonReferenceType()
+        << Args[0]->getSourceRange();
+      OverloadCandidateSet::iterator Best;
+      OverloadingResult Ovl = S.BestViableFunction(FailedCandidateSet,
+                                                   Kind.getLocation(),
+                                                   Best);
+      if (Ovl == OR_Deleted) {
+        S.Diag(Best->Function->getLocation(), diag::note_unavailable_here)
+          << Best->Function->isDeleted();
+      } else {
+        llvm_unreachable("Inconsistent overload resolution?");
+      }
+      break;
+    }
+        
+    case OR_Success:
+      llvm_unreachable("Conversion did not fail!");
+      break;
+    }
+    break;
+      
+  case FK_NonConstLValueReferenceBindingToTemporary:
+  case FK_NonConstLValueReferenceBindingToUnrelated:
+    S.Diag(Kind.getLocation(), 
+           Failure == FK_NonConstLValueReferenceBindingToTemporary
+             ? diag::err_lvalue_reference_bind_to_temporary
+             : diag::err_lvalue_reference_bind_to_unrelated)
+      << DestType.getNonReferenceType().isVolatileQualified()
+      << DestType.getNonReferenceType()
+      << Args[0]->getType()
+      << Args[0]->getSourceRange();
+    break;
+      
+  case FK_RValueReferenceBindingToLValue:
+    S.Diag(Kind.getLocation(), diag::err_lvalue_to_rvalue_ref)
+      << Args[0]->getSourceRange();
+    break;
+      
+  case FK_ReferenceInitDropsQualifiers:
+    S.Diag(Kind.getLocation(), diag::err_reference_bind_drops_quals)
+      << DestType.getNonReferenceType()
+      << Args[0]->getType()
+      << Args[0]->getSourceRange();
+    break;
+      
+  case FK_ReferenceInitFailed:
+    S.Diag(Kind.getLocation(), diag::err_reference_bind_failed)
+      << DestType.getNonReferenceType()
+      << (Args[0]->isLvalue(S.Context) == Expr::LV_Valid)
+      << Args[0]->getType()
+      << Args[0]->getSourceRange();
+    break;
+      
+  case FK_ConversionFailed:
+    S.Diag(Kind.getLocation(), diag::err_init_conversion_failed)
+      << (int)Entity.getKind()
+      << DestType
+      << (Args[0]->isLvalue(S.Context) == Expr::LV_Valid)
+      << Args[0]->getType()
+      << Args[0]->getSourceRange();
+    break;
+
+  case FK_TooManyInitsForScalar: {
+    SourceRange R;
+
+    if (InitListExpr *InitList = dyn_cast<InitListExpr>(Args[0]))
+      R = SourceRange(InitList->getInit(1)->getLocStart(),
+                      InitList->getLocEnd());
+    else
+      R = SourceRange(Args[0]->getLocStart(), Args[NumArgs - 1]->getLocEnd());
+
+    S.Diag(Kind.getLocation(), diag::err_excess_initializers)
+      << /*scalar=*/2 << R;
+    break;
+  }
+
+  case FK_ReferenceBindingToInitList:
+    S.Diag(Kind.getLocation(), diag::err_reference_bind_init_list)
+      << DestType.getNonReferenceType() << Args[0]->getSourceRange();
+    break;
+
+  case FK_InitListBadDestinationType:
+    S.Diag(Kind.getLocation(), diag::err_init_list_bad_dest_type)
+      << (DestType->isRecordType()) << DestType << Args[0]->getSourceRange();
+    break;
+      
+  case FK_ConstructorOverloadFailed: {
+    SourceRange ArgsRange;
+    if (NumArgs)
+      ArgsRange = SourceRange(Args[0]->getLocStart(), 
+                              Args[NumArgs - 1]->getLocEnd());
+    
+    // FIXME: Using "DestType" for the entity we're printing is probably
+    // bad.
+    switch (FailedOverloadResult) {
+      case OR_Ambiguous:
+        S.Diag(Kind.getLocation(), diag::err_ovl_ambiguous_init)
+          << DestType << ArgsRange;
+        S.PrintOverloadCandidates(FailedCandidateSet,
+                                  Sema::OCD_ViableCandidates, Args, NumArgs);
+        break;
+        
+      case OR_No_Viable_Function:
+        if (Kind.getKind() == InitializationKind::IK_Default &&
+            (Entity.getKind() == InitializedEntity::EK_Base ||
+             Entity.getKind() == InitializedEntity::EK_Member) &&
+            isa<CXXConstructorDecl>(S.CurContext)) {
+          // This is implicit default initialization of a member or
+          // base within a constructor. If no viable function was
+          // found, notify the user that she needs to explicitly
+          // initialize this base/member.
+          CXXConstructorDecl *Constructor
+            = cast<CXXConstructorDecl>(S.CurContext);
+          if (Entity.getKind() == InitializedEntity::EK_Base) {
+            S.Diag(Kind.getLocation(), diag::err_missing_default_ctor)
+              << Constructor->isImplicit()
+              << S.Context.getTypeDeclType(Constructor->getParent())
+              << /*base=*/0
+              << Entity.getType();
+
+            RecordDecl *BaseDecl
+              = Entity.getBaseSpecifier()->getType()->getAs<RecordType>()
+                                                                  ->getDecl();
+            S.Diag(BaseDecl->getLocation(), diag::note_previous_decl)
+              << S.Context.getTagDeclType(BaseDecl);
+          } else {
+            S.Diag(Kind.getLocation(), diag::err_missing_default_ctor)
+              << Constructor->isImplicit()
+              << S.Context.getTypeDeclType(Constructor->getParent())
+              << /*member=*/1
+              << Entity.getName();
+            S.Diag(Entity.getDecl()->getLocation(), diag::note_field_decl);
+
+            if (const RecordType *Record
+                                 = Entity.getType()->getAs<RecordType>())
+              S.Diag(Record->getDecl()->getLocation(), 
+                     diag::note_previous_decl)
+                << S.Context.getTagDeclType(Record->getDecl());
+          }
+          break;
+        }
+
+        S.Diag(Kind.getLocation(), diag::err_ovl_no_viable_function_in_init)
+          << DestType << ArgsRange;
+        S.PrintOverloadCandidates(FailedCandidateSet, Sema::OCD_AllCandidates,
+                                  Args, NumArgs);
+        break;
+        
+      case OR_Deleted: {
+        S.Diag(Kind.getLocation(), diag::err_ovl_deleted_init)
+          << true << DestType << ArgsRange;
+        OverloadCandidateSet::iterator Best;
+        OverloadingResult Ovl = S.BestViableFunction(FailedCandidateSet,
+                                                     Kind.getLocation(),
+                                                     Best);
+        if (Ovl == OR_Deleted) {
+          S.Diag(Best->Function->getLocation(), diag::note_unavailable_here)
+            << Best->Function->isDeleted();
+        } else {
+          llvm_unreachable("Inconsistent overload resolution?");
+        }
+        break;
+      }
+        
+      case OR_Success:
+        llvm_unreachable("Conversion did not fail!");
+        break;
+    }
+    break;
+  }
+      
+  case FK_DefaultInitOfConst:
+    if (Entity.getKind() == InitializedEntity::EK_Member &&
+        isa<CXXConstructorDecl>(S.CurContext)) {
+      // This is implicit default-initialization of a const member in
+      // a constructor. Complain that it needs to be explicitly
+      // initialized.
+      CXXConstructorDecl *Constructor = cast<CXXConstructorDecl>(S.CurContext);
+      S.Diag(Kind.getLocation(), diag::err_uninitialized_member_in_ctor)
+        << Constructor->isImplicit()
+        << S.Context.getTypeDeclType(Constructor->getParent())
+        << /*const=*/1
+        << Entity.getName();
+      S.Diag(Entity.getDecl()->getLocation(), diag::note_previous_decl)
+        << Entity.getName();
+    } else {
+      S.Diag(Kind.getLocation(), diag::err_default_init_const)
+        << DestType << (bool)DestType->getAs<RecordType>();
+    }
+    break;
+  }
+  
+  return true;
+}
+
+void InitializationSequence::dump(llvm::raw_ostream &OS) const {
+  switch (SequenceKind) {
+  case FailedSequence: {
+    OS << "Failed sequence: ";
+    switch (Failure) {
+    case FK_TooManyInitsForReference:
+      OS << "too many initializers for reference";
+      break;
+      
+    case FK_ArrayNeedsInitList:
+      OS << "array requires initializer list";
+      break;
+      
+    case FK_ArrayNeedsInitListOrStringLiteral:
+      OS << "array requires initializer list or string literal";
+      break;
+      
+    case FK_AddressOfOverloadFailed:
+      OS << "address of overloaded function failed";
+      break;
+      
+    case FK_ReferenceInitOverloadFailed:
+      OS << "overload resolution for reference initialization failed";
+      break;
+      
+    case FK_NonConstLValueReferenceBindingToTemporary:
+      OS << "non-const lvalue reference bound to temporary";
+      break;
+      
+    case FK_NonConstLValueReferenceBindingToUnrelated:
+      OS << "non-const lvalue reference bound to unrelated type";
+      break;
+      
+    case FK_RValueReferenceBindingToLValue:
+      OS << "rvalue reference bound to an lvalue";
+      break;
+      
+    case FK_ReferenceInitDropsQualifiers:
+      OS << "reference initialization drops qualifiers";
+      break;
+      
+    case FK_ReferenceInitFailed:
+      OS << "reference initialization failed";
+      break;
+      
+    case FK_ConversionFailed:
+      OS << "conversion failed";
+      break;
+      
+    case FK_TooManyInitsForScalar:
+      OS << "too many initializers for scalar";
+      break;
+      
+    case FK_ReferenceBindingToInitList:
+      OS << "referencing binding to initializer list";
+      break;
+      
+    case FK_InitListBadDestinationType:
+      OS << "initializer list for non-aggregate, non-scalar type";
+      break;
+      
+    case FK_UserConversionOverloadFailed:
+      OS << "overloading failed for user-defined conversion";
+      break;
+      
+    case FK_ConstructorOverloadFailed:
+      OS << "constructor overloading failed";
+      break;
+      
+    case FK_DefaultInitOfConst:
+      OS << "default initialization of a const variable";
+      break;
+    }   
+    OS << '\n';
+    return;
+  }
+      
+  case DependentSequence:
+    OS << "Dependent sequence: ";
+    return;
+      
+  case UserDefinedConversion:
+    OS << "User-defined conversion sequence: ";
+    break;
+      
+  case ConstructorInitialization:
+    OS << "Constructor initialization sequence: ";
+    break;
+      
+  case ReferenceBinding:
+    OS << "Reference binding: ";
+    break;
+      
+  case ListInitialization:
+    OS << "List initialization: ";
+    break;
+
+  case ZeroInitialization:
+    OS << "Zero initialization\n";
+    return;
+      
+  case NoInitialization:
+    OS << "No initialization\n";
+    return;
+      
+  case StandardConversion:
+    OS << "Standard conversion: ";
+    break;
+      
+  case CAssignment:
+    OS << "C assignment: ";
+    break;
+      
+  case StringInit:
+    OS << "String initialization: ";
+    break;
+  }
+  
+  for (step_iterator S = step_begin(), SEnd = step_end(); S != SEnd; ++S) {
+    if (S != step_begin()) {
+      OS << " -> ";
+    }
+    
+    switch (S->Kind) {
+    case SK_ResolveAddressOfOverloadedFunction:
+      OS << "resolve address of overloaded function";
+      break;
+      
+    case SK_CastDerivedToBaseRValue:
+      OS << "derived-to-base case (rvalue" << S->Type.getAsString() << ")";
+      break;
+      
+    case SK_CastDerivedToBaseLValue:
+      OS << "derived-to-base case (lvalue" << S->Type.getAsString() << ")";
+      break;
+      
+    case SK_BindReference:
+      OS << "bind reference to lvalue";
+      break;
+      
+    case SK_BindReferenceToTemporary:
+      OS << "bind reference to a temporary";
+      break;
+      
+    case SK_UserConversion:
+      OS << "user-defined conversion via " << S->Function->getNameAsString();
+      break;
+      
+    case SK_QualificationConversionRValue:
+      OS << "qualification conversion (rvalue)";
+
+    case SK_QualificationConversionLValue:
+      OS << "qualification conversion (lvalue)";
+      break;
+      
+    case SK_ConversionSequence:
+      OS << "implicit conversion sequence (";
+      S->ICS->DebugPrint(); // FIXME: use OS
+      OS << ")";
+      break;
+      
+    case SK_ListInitialization:
+      OS << "list initialization";
+      break;
+      
+    case SK_ConstructorInitialization:
+      OS << "constructor initialization";
+      break;
+      
+    case SK_ZeroInitialization:
+      OS << "zero initialization";
+      break;
+      
+    case SK_CAssignment:
+      OS << "C assignment";
+      break;
+      
+    case SK_StringInit:
+      OS << "string initialization";
+      break;
+    }
+  }
+}
+
+void InitializationSequence::dump() const {
+  dump(llvm::errs());
+}
+
+//===----------------------------------------------------------------------===//
+// Initialization helper functions
+//===----------------------------------------------------------------------===//
+Sema::OwningExprResult 
+Sema::PerformCopyInitialization(const InitializedEntity &Entity,
+                                SourceLocation EqualLoc,
+                                OwningExprResult Init) {
+  if (Init.isInvalid())
+    return ExprError();
+
+  Expr *InitE = (Expr *)Init.get();
+  assert(InitE && "No initialization expression?");
+
+  if (EqualLoc.isInvalid())
+    EqualLoc = InitE->getLocStart();
+
+  InitializationKind Kind = InitializationKind::CreateCopy(InitE->getLocStart(),
+                                                           EqualLoc);
+  InitializationSequence Seq(*this, Entity, Kind, &InitE, 1);
+  Init.release();
+  return Seq.Perform(*this, Entity, Kind, 
+                     MultiExprArg(*this, (void**)&InitE, 1));
+}
diff --git a/lib/Sema/SemaInit.h b/lib/Sema/SemaInit.h
new file mode 100644
index 0000000..2b49df2
--- /dev/null
+++ b/lib/Sema/SemaInit.h
@@ -0,0 +1,690 @@
+//===--- SemaInit.h - Semantic Analysis for Initializers --------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file provides supporting data types for initialization of objects.
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_CLANG_SEMA_INIT_H
+#define LLVM_CLANG_SEMA_INIT_H
+
+#include "SemaOverload.h"
+#include "clang/AST/Type.h"
+#include "clang/AST/UnresolvedSet.h"
+#include "clang/Parse/Action.h"
+#include "clang/Basic/SourceLocation.h"
+#include "llvm/ADT/PointerIntPair.h"
+#include "llvm/ADT/SmallVector.h"
+#include <cassert>
+
+namespace llvm {
+  class raw_ostream;
+}
+
+namespace clang {
+  
+class CXXBaseSpecifier;
+class DeclaratorDecl;
+class DeclaratorInfo;
+class FieldDecl;
+class FunctionDecl;
+class ParmVarDecl;
+class Sema;
+class TypeLoc;
+class VarDecl;
+  
+/// \brief Describes an entity that is being initialized.
+class InitializedEntity {
+public:
+  /// \brief Specifies the kind of entity being initialized.
+  enum EntityKind {
+    /// \brief The entity being initialized is a variable.
+    EK_Variable,
+    /// \brief The entity being initialized is a function parameter.
+    EK_Parameter,
+    /// \brief The entity being initialized is the result of a function call.
+    EK_Result,
+    /// \brief The entity being initialized is an exception object that
+    /// is being thrown.
+    EK_Exception,
+    /// \brief The entity being initialized is a non-static data member 
+    /// subobject.
+    EK_Member,
+    /// \brief The entity being initialized is an element of an array.
+    EK_ArrayElement,
+    /// \brief The entity being initialized is an object (or array of
+    /// objects) allocated via new.
+    EK_New,
+    /// \brief The entity being initialized is a temporary object.
+    EK_Temporary,
+    /// \brief The entity being initialized is a base member subobject.
+    EK_Base,
+    /// \brief The entity being initialized is an element of a vector.
+    /// or vector.
+    EK_VectorElement
+  };
+  
+private:
+  /// \brief The kind of entity being initialized.
+  EntityKind Kind;
+
+  /// \brief If non-NULL, the parent entity in which this
+  /// initialization occurs.
+  const InitializedEntity *Parent;
+
+  /// \brief The type of the object or reference being initialized.
+  QualType Type;
+  
+  union {
+    /// \brief When Kind == EK_Variable, EK_Parameter, or EK_Member, 
+    /// the VarDecl, ParmVarDecl, or FieldDecl, respectively.
+    DeclaratorDecl *VariableOrMember;
+    
+    /// \brief When Kind == EK_Result, EK_Exception, or EK_New, the
+    /// location of the 'return', 'throw', or 'new' keyword,
+    /// respectively. When Kind == EK_Temporary, the location where
+    /// the temporary is being created.
+    unsigned Location;
+    
+    /// \brief When Kind == EK_Base, the base specifier that provides the 
+    /// base class.
+    CXXBaseSpecifier *Base;
+
+    /// \brief When Kind = EK_ArrayElement or EK_VectorElement, the
+    /// index of the array or vector element being initialized.
+    unsigned Index;
+  };
+
+  InitializedEntity() { }
+
+  /// \brief Create the initialization entity for a variable.
+  InitializedEntity(VarDecl *Var)
+    : Kind(EK_Variable), Parent(0), Type(Var->getType()),
+      VariableOrMember(reinterpret_cast<DeclaratorDecl*>(Var)) { }
+  
+  /// \brief Create the initialization entity for a parameter.
+  InitializedEntity(ParmVarDecl *Parm)
+    : Kind(EK_Parameter), Parent(0), Type(Parm->getType().getUnqualifiedType()),
+      VariableOrMember(reinterpret_cast<DeclaratorDecl*>(Parm)) { }
+  
+  /// \brief Create the initialization entity for the result of a
+  /// function, throwing an object, performing an explicit cast, or
+  /// initializing a parameter for which there is no declaration.
+  InitializedEntity(EntityKind Kind, SourceLocation Loc, QualType Type)
+    : Kind(Kind), Parent(0), Type(Type), Location(Loc.getRawEncoding()) { }
+  
+  /// \brief Create the initialization entity for a member subobject.
+  InitializedEntity(FieldDecl *Member, const InitializedEntity *Parent) 
+    : Kind(EK_Member), Parent(Parent), Type(Member->getType()),
+      VariableOrMember(reinterpret_cast<DeclaratorDecl*>(Member)) { }
+  
+  /// \brief Create the initialization entity for an array element.
+  InitializedEntity(ASTContext &Context, unsigned Index, 
+                    const InitializedEntity &Parent);
+
+public:
+  /// \brief Create the initialization entity for a variable.
+  static InitializedEntity InitializeVariable(VarDecl *Var) {
+    return InitializedEntity(Var);
+  }
+  
+  /// \brief Create the initialization entity for a parameter.
+  static InitializedEntity InitializeParameter(ParmVarDecl *Parm) {
+    return InitializedEntity(Parm);
+  }
+
+  /// \brief Create the initialization entity for a parameter that is
+  /// only known by its type.
+  static InitializedEntity InitializeParameter(QualType Type) {
+    return InitializedEntity(EK_Parameter, SourceLocation(), Type);
+  }
+
+  /// \brief Create the initialization entity for the result of a function.
+  static InitializedEntity InitializeResult(SourceLocation ReturnLoc,
+                                            QualType Type) {
+    return InitializedEntity(EK_Result, ReturnLoc, Type);
+  }
+
+  /// \brief Create the initialization entity for an exception object.
+  static InitializedEntity InitializeException(SourceLocation ThrowLoc,
+                                               QualType Type) {
+    return InitializedEntity(EK_Exception, ThrowLoc, Type);
+  }
+
+  /// \brief Create the initialization entity for an object allocated via new.
+  static InitializedEntity InitializeNew(SourceLocation NewLoc, QualType Type) {
+    return InitializedEntity(EK_New, NewLoc, Type);
+  }
+  
+  /// \brief Create the initialization entity for a temporary.
+  static InitializedEntity InitializeTemporary(QualType Type) {
+    return InitializedEntity(EK_Temporary, SourceLocation(), Type);
+  }
+  
+  /// \brief Create the initialization entity for a base class subobject.
+  static InitializedEntity InitializeBase(ASTContext &Context,
+                                          CXXBaseSpecifier *Base);
+  
+  /// \brief Create the initialization entity for a member subobject.
+  static InitializedEntity InitializeMember(FieldDecl *Member,
+                                          const InitializedEntity *Parent = 0) {
+    return InitializedEntity(Member, Parent);
+  }
+  
+  /// \brief Create the initialization entity for an array element.
+  static InitializedEntity InitializeElement(ASTContext &Context, 
+                                             unsigned Index, 
+                                             const InitializedEntity &Parent) {
+    return InitializedEntity(Context, Index, Parent);
+  }
+
+  /// \brief Determine the kind of initialization.
+  EntityKind getKind() const { return Kind; }
+  
+  /// \brief Retrieve the parent of the entity being initialized, when
+  /// the initialization itself is occuring within the context of a
+  /// larger initialization.
+  const InitializedEntity *getParent() const { return Parent; }
+
+  /// \brief Retrieve type being initialized.
+  QualType getType() const { return Type; }
+  
+  /// \brief Retrieve the name of the entity being initialized.
+  DeclarationName getName() const;
+
+  /// \brief Retrieve the variable, parameter, or field being
+  /// initialized.
+  DeclaratorDecl *getDecl() const;
+
+  /// \brief Retrieve the base specifier.
+  CXXBaseSpecifier *getBaseSpecifier() const {
+    assert(getKind() == EK_Base && "Not a base specifier");
+    return Base;
+  }
+
+  /// \brief Determine the location of the 'return' keyword when initializing
+  /// the result of a function call.
+  SourceLocation getReturnLoc() const {
+    assert(getKind() == EK_Result && "No 'return' location!");
+    return SourceLocation::getFromRawEncoding(Location);
+  }
+  
+  /// \brief Determine the location of the 'throw' keyword when initializing
+  /// an exception object.
+  SourceLocation getThrowLoc() const {
+    assert(getKind() == EK_Exception && "No 'throw' location!");
+    return SourceLocation::getFromRawEncoding(Location);
+  }
+
+  /// \brief If this is already the initializer for an array or vector
+  /// element, sets the element index.
+  void setElementIndex(unsigned Index) {
+    assert(getKind() == EK_ArrayElement || getKind() == EK_VectorElement);
+    this->Index = Index;
+  }
+};
+  
+/// \brief Describes the kind of initialization being performed, along with 
+/// location information for tokens related to the initialization (equal sign,
+/// parentheses).
+class InitializationKind {
+public:
+  /// \brief The kind of initialization being performed.
+  enum InitKind {
+    IK_Direct,  ///< Direct initialization
+    IK_Copy,    ///< Copy initialization
+    IK_Default, ///< Default initialization
+    IK_Value    ///< Value initialization
+  };
+  
+private:
+  /// \brief The kind of initialization that we're storing.
+  enum StoredInitKind {
+    SIK_Direct = IK_Direct,   ///< Direct initialization
+    SIK_Copy = IK_Copy,       ///< Copy initialization
+    SIK_Default = IK_Default, ///< Default initialization
+    SIK_Value = IK_Value,     ///< Value initialization
+    SIK_ImplicitValue,        ///< Implicit value initialization
+    SIK_DirectCast,  ///< Direct initialization due to a cast
+    /// \brief Direct initialization due to a C-style or functional cast.
+    SIK_DirectCStyleOrFunctionalCast
+  };
+  
+  /// \brief The kind of initialization being performed.
+  StoredInitKind Kind;
+  
+  /// \brief The source locations involved in the initialization.
+  SourceLocation Locations[3];
+  
+  InitializationKind(StoredInitKind Kind, SourceLocation Loc1, 
+                     SourceLocation Loc2, SourceLocation Loc3)
+    : Kind(Kind) 
+  {
+    Locations[0] = Loc1;
+    Locations[1] = Loc2;
+    Locations[2] = Loc3;
+  }
+  
+public:
+  /// \brief Create a direct initialization.
+  static InitializationKind CreateDirect(SourceLocation InitLoc,
+                                         SourceLocation LParenLoc,
+                                         SourceLocation RParenLoc) {
+    return InitializationKind(SIK_Direct, InitLoc, LParenLoc, RParenLoc);
+  }
+
+  /// \brief Create a direct initialization due to a cast.
+  static InitializationKind CreateCast(SourceRange TypeRange,
+                                       bool IsCStyleCast) {
+    return InitializationKind(IsCStyleCast? SIK_DirectCStyleOrFunctionalCast
+                                          : SIK_DirectCast,
+                              TypeRange.getBegin(), TypeRange.getBegin(), 
+                              TypeRange.getEnd());
+  }
+  
+  /// \brief Create a copy initialization.
+  static InitializationKind CreateCopy(SourceLocation InitLoc,
+                                       SourceLocation EqualLoc) {
+    return InitializationKind(SIK_Copy, InitLoc, EqualLoc, EqualLoc);
+  }
+  
+  /// \brief Create a default initialization.
+  static InitializationKind CreateDefault(SourceLocation InitLoc) {
+    return InitializationKind(SIK_Default, InitLoc, InitLoc, InitLoc);
+  }
+  
+  /// \brief Create a value initialization.
+  static InitializationKind CreateValue(SourceLocation InitLoc,
+                                        SourceLocation LParenLoc,
+                                        SourceLocation RParenLoc,
+                                        bool isImplicit = false) {
+    return InitializationKind(isImplicit? SIK_ImplicitValue : SIK_Value, 
+                              InitLoc, LParenLoc, RParenLoc);
+  }
+  
+  /// \brief Determine the initialization kind.
+  InitKind getKind() const {
+    if (Kind > SIK_ImplicitValue)
+      return IK_Direct;
+    if (Kind == SIK_ImplicitValue)
+      return IK_Value;
+
+    return (InitKind)Kind;
+  }
+  
+  /// \brief Determine whether this initialization is an explicit cast.
+  bool isExplicitCast() const {
+    return Kind == SIK_DirectCast || Kind == SIK_DirectCStyleOrFunctionalCast;
+  }
+  
+  /// \brief Determine whether this initialization is a C-style cast.
+  bool isCStyleOrFunctionalCast() const { 
+    return Kind == SIK_DirectCStyleOrFunctionalCast; 
+  }
+
+  /// \brief Determine whether this initialization is an implicit
+  /// value-initialization, e.g., as occurs during aggregate
+  /// initialization.
+  bool isImplicitValueInit() const { return Kind == SIK_ImplicitValue; }
+
+  /// \brief Retrieve the location at which initialization is occurring.
+  SourceLocation getLocation() const { return Locations[0]; }
+  
+  /// \brief Retrieve the source range that covers the initialization.
+  SourceRange getRange() const { 
+    return SourceRange(Locations[0], Locations[2]);
+  }
+  
+  /// \brief Retrieve the location of the equal sign for copy initialization
+  /// (if present).
+  SourceLocation getEqualLoc() const {
+    assert(Kind == SIK_Copy && "Only copy initialization has an '='");
+    return Locations[1];
+  }
+  
+  /// \brief Retrieve the source range containing the locations of the open
+  /// and closing parentheses for value and direct initializations.
+  SourceRange getParenRange() const {
+    assert((getKind() == IK_Direct || Kind == SIK_Value) &&
+           "Only direct- and value-initialization have parentheses");
+    return SourceRange(Locations[1], Locations[2]);
+  }
+};
+
+/// \brief Describes the sequence of initializations required to initialize
+/// a given object or reference with a set of arguments.
+class InitializationSequence {
+public:
+  /// \brief Describes the kind of initialization sequence computed.
+  ///
+  /// FIXME: Much of this information is in the initialization steps... why is
+  /// it duplicated here?
+  enum SequenceKind {
+    /// \brief A failed initialization sequence. The failure kind tells what
+    /// happened.
+    FailedSequence = 0,
+    
+    /// \brief A dependent initialization, which could not be
+    /// type-checked due to the presence of dependent types or
+    /// dependently-type expressions.
+    DependentSequence,
+
+    /// \brief A user-defined conversion sequence.
+    UserDefinedConversion,
+    
+    /// \brief A constructor call.
+    ConstructorInitialization,
+    
+    /// \brief A reference binding.
+    ReferenceBinding,
+
+    /// \brief List initialization
+    ListInitialization,
+    
+    /// \brief Zero-initialization.
+    ZeroInitialization,
+    
+    /// \brief No initialization required.
+    NoInitialization,
+    
+    /// \brief Standard conversion sequence.
+    StandardConversion,
+
+    /// \brief C conversion sequence.
+    CAssignment,
+
+    /// \brief String initialization
+    StringInit
+  };
+  
+  /// \brief Describes the kind of a particular step in an initialization
+  /// sequence.
+  enum StepKind {
+    /// \brief Resolve the address of an overloaded function to a specific
+    /// function declaration.
+    SK_ResolveAddressOfOverloadedFunction,
+    /// \brief Perform a derived-to-base cast, producing an rvalue.
+    SK_CastDerivedToBaseRValue,
+    /// \brief Perform a derived-to-base cast, producing an lvalue.
+    SK_CastDerivedToBaseLValue,
+    /// \brief Reference binding to an lvalue.
+    SK_BindReference,
+    /// \brief Reference binding to a temporary.
+    SK_BindReferenceToTemporary,
+    /// \brief Perform a user-defined conversion, either via a conversion
+    /// function or via a constructor.
+    SK_UserConversion,
+    /// \brief Perform a qualification conversion, producing an rvalue.
+    SK_QualificationConversionRValue,
+    /// \brief Perform a qualification conversion, producing an lvalue.
+    SK_QualificationConversionLValue,
+    /// \brief Perform an implicit conversion sequence.
+    SK_ConversionSequence,
+    /// \brief Perform list-initialization
+    SK_ListInitialization,
+    /// \brief Perform initialization via a constructor.
+    SK_ConstructorInitialization,
+    /// \brief Zero-initialize the object
+    SK_ZeroInitialization,
+    /// \brief C assignment
+    SK_CAssignment,
+    /// \brief Initialization by string
+    SK_StringInit
+  };
+  
+  /// \brief A single step in the initialization sequence.
+  class Step {
+  public:
+    /// \brief The kind of conversion or initialization step we are taking.
+    StepKind Kind;
+    
+    // \brief The type that results from this initialization.
+    QualType Type;
+    
+    union {
+      /// \brief When Kind == SK_ResolvedOverloadedFunction or Kind ==
+      /// SK_UserConversion, the function that the expression should be 
+      /// resolved to or the conversion function to call, respectively.
+      ///
+      /// Always a FunctionDecl.
+      /// For conversion decls, the naming class is the source type.
+      /// For construct decls, the naming class is the target type.
+      DeclAccessPair Function;
+      
+      /// \brief When Kind = SK_ConversionSequence, the implicit conversion
+      /// sequence 
+      ImplicitConversionSequence *ICS;
+    };
+    
+    void Destroy();
+  };
+  
+private:
+  /// \brief The kind of initialization sequence computed.
+  enum SequenceKind SequenceKind;
+  
+  /// \brief Steps taken by this initialization.
+  llvm::SmallVector<Step, 4> Steps;
+  
+public:
+  /// \brief Describes why initialization failed.
+  enum FailureKind {
+    /// \brief Too many initializers provided for a reference.
+    FK_TooManyInitsForReference,
+    /// \brief Array must be initialized with an initializer list.
+    FK_ArrayNeedsInitList,
+    /// \brief Array must be initialized with an initializer list or a 
+    /// string literal.
+    FK_ArrayNeedsInitListOrStringLiteral,
+    /// \brief Cannot resolve the address of an overloaded function.
+    FK_AddressOfOverloadFailed,
+    /// \brief Overloading due to reference initialization failed.
+    FK_ReferenceInitOverloadFailed,
+    /// \brief Non-const lvalue reference binding to a temporary.
+    FK_NonConstLValueReferenceBindingToTemporary,
+    /// \brief Non-const lvalue reference binding to an lvalue of unrelated
+    /// type.
+    FK_NonConstLValueReferenceBindingToUnrelated,
+    /// \brief Rvalue reference binding to an lvalue.
+    FK_RValueReferenceBindingToLValue,
+    /// \brief Reference binding drops qualifiers.
+    FK_ReferenceInitDropsQualifiers,
+    /// \brief Reference binding failed.
+    FK_ReferenceInitFailed,
+    /// \brief Implicit conversion failed.
+    FK_ConversionFailed,
+    /// \brief Too many initializers for scalar
+    FK_TooManyInitsForScalar,
+    /// \brief Reference initialization from an initializer list
+    FK_ReferenceBindingToInitList,
+    /// \brief Initialization of some unused destination type with an
+    /// initializer list.
+    FK_InitListBadDestinationType,
+    /// \brief Overloading for a user-defined conversion failed.
+    FK_UserConversionOverloadFailed,
+    /// \brief Overloaded for initialization by constructor failed.
+    FK_ConstructorOverloadFailed,
+    /// \brief Default-initialization of a 'const' object.
+    FK_DefaultInitOfConst
+  };
+  
+private:
+  /// \brief The reason why initialization failued.
+  FailureKind Failure;
+
+  /// \brief The failed result of overload resolution.
+  OverloadingResult FailedOverloadResult;
+  
+  /// \brief The candidate set created when initialization failed.
+  OverloadCandidateSet FailedCandidateSet;
+  
+public:
+  /// \brief Try to perform initialization of the given entity, creating a 
+  /// record of the steps required to perform the initialization.
+  ///
+  /// The generated initialization sequence will either contain enough
+  /// information to diagnose 
+  ///
+  /// \param S the semantic analysis object.
+  ///
+  /// \param Entity the entity being initialized.
+  ///
+  /// \param Kind the kind of initialization being performed.
+  ///
+  /// \param Args the argument(s) provided for initialization.
+  ///
+  /// \param NumArgs the number of arguments provided for initialization.
+  InitializationSequence(Sema &S, 
+                         const InitializedEntity &Entity,
+                         const InitializationKind &Kind,
+                         Expr **Args,
+                         unsigned NumArgs);
+  
+  ~InitializationSequence();
+  
+  /// \brief Perform the actual initialization of the given entity based on
+  /// the computed initialization sequence.
+  ///
+  /// \param S the semantic analysis object.
+  ///
+  /// \param Entity the entity being initialized.
+  ///
+  /// \param Kind the kind of initialization being performed.
+  ///
+  /// \param Args the argument(s) provided for initialization, ownership of
+  /// which is transfered into the routine.
+  ///
+  /// \param ResultType if non-NULL, will be set to the type of the
+  /// initialized object, which is the type of the declaration in most
+  /// cases. However, when the initialized object is a variable of
+  /// incomplete array type and the initializer is an initializer
+  /// list, this type will be set to the completed array type.
+  ///
+  /// \returns an expression that performs the actual object initialization, if
+  /// the initialization is well-formed. Otherwise, emits diagnostics
+  /// and returns an invalid expression.
+  Action::OwningExprResult Perform(Sema &S,
+                                   const InitializedEntity &Entity,
+                                   const InitializationKind &Kind,
+                                   Action::MultiExprArg Args,
+                                   QualType *ResultType = 0);
+  
+  /// \brief Diagnose an potentially-invalid initialization sequence.
+  ///
+  /// \returns true if the initialization sequence was ill-formed, 
+  /// false otherwise.
+  bool Diagnose(Sema &S, 
+                const InitializedEntity &Entity,
+                const InitializationKind &Kind,
+                Expr **Args, unsigned NumArgs);
+  
+  /// \brief Determine the kind of initialization sequence computed.
+  enum SequenceKind getKind() const { return SequenceKind; }
+  
+  /// \brief Set the kind of sequence computed.
+  void setSequenceKind(enum SequenceKind SK) { SequenceKind = SK; }
+  
+  /// \brief Determine whether the initialization sequence is valid.
+  operator bool() const { return SequenceKind != FailedSequence; }
+  
+  typedef llvm::SmallVector<Step, 4>::const_iterator step_iterator;
+  step_iterator step_begin() const { return Steps.begin(); }
+  step_iterator step_end()   const { return Steps.end(); }
+
+  /// \brief Add a new step in the initialization that resolves the address
+  /// of an overloaded function to a specific function declaration.
+  ///
+  /// \param Function the function to which the overloaded function reference
+  /// resolves.
+  void AddAddressOverloadResolutionStep(FunctionDecl *Function);
+  
+  /// \brief Add a new step in the initialization that performs a derived-to-
+  /// base cast.
+  ///
+  /// \param BaseType the base type to which we will be casting.
+  ///
+  /// \param IsLValue true if the result of this cast will be treated as 
+  /// an lvalue.
+  void AddDerivedToBaseCastStep(QualType BaseType, bool IsLValue);
+     
+  /// \brief Add a new step binding a reference to an object.
+  ///
+  /// \param BindingTemporary true if we are binding a reference to a temporary
+  /// object (thereby extending its lifetime); false if we are binding to an
+  /// lvalue or an lvalue treated as an rvalue.
+  void AddReferenceBindingStep(QualType T, bool BindingTemporary);
+  
+  /// \brief Add a new step invoking a conversion function, which is either
+  /// a constructor or a conversion function.
+  void AddUserConversionStep(FunctionDecl *Function,
+                             AccessSpecifier Access,
+                             QualType T);
+  
+  /// \brief Add a new step that performs a qualification conversion to the
+  /// given type.
+  void AddQualificationConversionStep(QualType Ty, bool IsLValue);
+  
+  /// \brief Add a new step that applies an implicit conversion sequence.
+  void AddConversionSequenceStep(const ImplicitConversionSequence &ICS,
+                                 QualType T);
+
+  /// \brief Add a list-initialiation step  
+  void AddListInitializationStep(QualType T);
+
+  /// \brief Add a constructor-initialization step.
+  void AddConstructorInitializationStep(CXXConstructorDecl *Constructor,
+                                        AccessSpecifier Access,
+                                        QualType T);
+
+  /// \brief Add a zero-initialization step.
+  void AddZeroInitializationStep(QualType T);
+  
+  /// \brief Add a C assignment step.
+  //
+  // FIXME: It isn't clear whether this should ever be needed;
+  // ideally, we would handle everything needed in C in the common
+  // path. However, that isn't the case yet.
+  void AddCAssignmentStep(QualType T);
+
+  /// \brief Add a string init step.
+  void AddStringInitStep(QualType T);
+
+  /// \brief Note that this initialization sequence failed.
+  void SetFailed(FailureKind Failure) {
+    SequenceKind = FailedSequence;
+    this->Failure = Failure;
+  }
+  
+  /// \brief Note that this initialization sequence failed due to failed
+  /// overload resolution.
+  void SetOverloadFailure(FailureKind Failure, OverloadingResult Result);
+  
+  /// \brief Retrieve a reference to the candidate set when overload
+  /// resolution fails.
+  OverloadCandidateSet &getFailedCandidateSet() {
+    return FailedCandidateSet;
+  }
+
+  /// \brief Determine why initialization failed.
+  FailureKind getFailureKind() const {
+    assert(getKind() == FailedSequence && "Not an initialization failure!");
+    return Failure;
+  }
+  
+  /// \brief Dump a representation of this initialization sequence to 
+  /// the given stream, for debugging purposes.
+  void dump(llvm::raw_ostream &OS) const;
+  
+  /// \brief Dump a representation of this initialization sequence to 
+  /// standard error, for debugging purposes.
+  void dump() const;
+};
+  
+} // end namespace clang
+
+#endif // LLVM_CLANG_SEMA_INIT_H
diff --git a/lib/Sema/SemaLookup.cpp b/lib/Sema/SemaLookup.cpp
new file mode 100644
index 0000000..0d95c71
--- /dev/null
+++ b/lib/Sema/SemaLookup.cpp
@@ -0,0 +1,2469 @@
+//===--------------------- SemaLookup.cpp - Name Lookup  ------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+//  This file implements name lookup for C, C++, Objective-C, and
+//  Objective-C++.
+//
+//===----------------------------------------------------------------------===//
+#include "Sema.h"
+#include "Lookup.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/CXXInheritance.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclCXX.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/AST/DeclTemplate.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/ExprCXX.h"
+#include "clang/Parse/DeclSpec.h"
+#include "clang/Basic/Builtins.h"
+#include "clang/Basic/LangOptions.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/Support/ErrorHandling.h"
+#include <list>
+#include <set>
+#include <vector>
+#include <iterator>
+#include <utility>
+#include <algorithm>
+
+using namespace clang;
+
+namespace {
+  class UnqualUsingEntry {
+    const DeclContext *Nominated;
+    const DeclContext *CommonAncestor;
+
+  public:
+    UnqualUsingEntry(const DeclContext *Nominated,
+                     const DeclContext *CommonAncestor)
+      : Nominated(Nominated), CommonAncestor(CommonAncestor) {
+    }
+
+    const DeclContext *getCommonAncestor() const {
+      return CommonAncestor;
+    }
+
+    const DeclContext *getNominatedNamespace() const {
+      return Nominated;
+    }
+
+    // Sort by the pointer value of the common ancestor.
+    struct Comparator {
+      bool operator()(const UnqualUsingEntry &L, const UnqualUsingEntry &R) {
+        return L.getCommonAncestor() < R.getCommonAncestor();
+      }
+
+      bool operator()(const UnqualUsingEntry &E, const DeclContext *DC) {
+        return E.getCommonAncestor() < DC;
+      }
+
+      bool operator()(const DeclContext *DC, const UnqualUsingEntry &E) {
+        return DC < E.getCommonAncestor();
+      }
+    };
+  };
+
+  /// A collection of using directives, as used by C++ unqualified
+  /// lookup.
+  class UnqualUsingDirectiveSet {
+    typedef llvm::SmallVector<UnqualUsingEntry, 8> ListTy;
+
+    ListTy list;
+    llvm::SmallPtrSet<DeclContext*, 8> visited;
+
+  public:
+    UnqualUsingDirectiveSet() {}
+
+    void visitScopeChain(Scope *S, Scope *InnermostFileScope) {
+      // C++ [namespace.udir]p1: 
+      //   During unqualified name lookup, the names appear as if they
+      //   were declared in the nearest enclosing namespace which contains
+      //   both the using-directive and the nominated namespace.
+      DeclContext *InnermostFileDC
+        = static_cast<DeclContext*>(InnermostFileScope->getEntity());
+      assert(InnermostFileDC && InnermostFileDC->isFileContext());
+
+      for (; S; S = S->getParent()) {
+        if (DeclContext *Ctx = static_cast<DeclContext*>(S->getEntity())) {
+          DeclContext *EffectiveDC = (Ctx->isFileContext() ? Ctx : InnermostFileDC);
+          visit(Ctx, EffectiveDC);
+        } else {
+          Scope::udir_iterator I = S->using_directives_begin(),
+                             End = S->using_directives_end();
+          
+          for (; I != End; ++I)
+            visit(I->getAs<UsingDirectiveDecl>(), InnermostFileDC);
+        }
+      }
+    }
+
+    // Visits a context and collect all of its using directives
+    // recursively.  Treats all using directives as if they were
+    // declared in the context.
+    //
+    // A given context is only every visited once, so it is important
+    // that contexts be visited from the inside out in order to get
+    // the effective DCs right.
+    void visit(DeclContext *DC, DeclContext *EffectiveDC) {
+      if (!visited.insert(DC))
+        return;
+
+      addUsingDirectives(DC, EffectiveDC);
+    }
+
+    // Visits a using directive and collects all of its using
+    // directives recursively.  Treats all using directives as if they
+    // were declared in the effective DC.
+    void visit(UsingDirectiveDecl *UD, DeclContext *EffectiveDC) {
+      DeclContext *NS = UD->getNominatedNamespace();
+      if (!visited.insert(NS))
+        return;
+
+      addUsingDirective(UD, EffectiveDC);
+      addUsingDirectives(NS, EffectiveDC);
+    }
+
+    // Adds all the using directives in a context (and those nominated
+    // by its using directives, transitively) as if they appeared in
+    // the given effective context.
+    void addUsingDirectives(DeclContext *DC, DeclContext *EffectiveDC) {
+      llvm::SmallVector<DeclContext*,4> queue;
+      while (true) {
+        DeclContext::udir_iterator I, End;
+        for (llvm::tie(I, End) = DC->getUsingDirectives(); I != End; ++I) {
+          UsingDirectiveDecl *UD = *I;
+          DeclContext *NS = UD->getNominatedNamespace();
+          if (visited.insert(NS)) {
+            addUsingDirective(UD, EffectiveDC);
+            queue.push_back(NS);
+          }
+        }
+
+        if (queue.empty())
+          return;
+
+        DC = queue.back();
+        queue.pop_back();
+      }
+    }
+
+    // Add a using directive as if it had been declared in the given
+    // context.  This helps implement C++ [namespace.udir]p3:
+    //   The using-directive is transitive: if a scope contains a
+    //   using-directive that nominates a second namespace that itself
+    //   contains using-directives, the effect is as if the
+    //   using-directives from the second namespace also appeared in
+    //   the first.
+    void addUsingDirective(UsingDirectiveDecl *UD, DeclContext *EffectiveDC) {
+      // Find the common ancestor between the effective context and
+      // the nominated namespace.
+      DeclContext *Common = UD->getNominatedNamespace();
+      while (!Common->Encloses(EffectiveDC))
+        Common = Common->getParent();
+      Common = Common->getPrimaryContext();
+      
+      list.push_back(UnqualUsingEntry(UD->getNominatedNamespace(), Common));
+    }
+
+    void done() {
+      std::sort(list.begin(), list.end(), UnqualUsingEntry::Comparator());
+    }
+
+    typedef ListTy::iterator iterator;
+    typedef ListTy::const_iterator const_iterator;
+    
+    iterator begin() { return list.begin(); }
+    iterator end() { return list.end(); }
+    const_iterator begin() const { return list.begin(); }
+    const_iterator end() const { return list.end(); }
+
+    std::pair<const_iterator,const_iterator>
+    getNamespacesFor(DeclContext *DC) const {
+      return std::equal_range(begin(), end(), DC->getPrimaryContext(),
+                              UnqualUsingEntry::Comparator());
+    }
+  };
+}
+
+static bool IsAcceptableIDNS(NamedDecl *D, unsigned IDNS) {
+  return D->isInIdentifierNamespace(IDNS);
+}
+
+static bool IsAcceptableOperatorName(NamedDecl *D, unsigned IDNS) {
+  return D->isInIdentifierNamespace(IDNS) &&
+    !D->getDeclContext()->isRecord();
+}
+
+static bool IsAcceptableNestedNameSpecifierName(NamedDecl *D, unsigned IDNS) {
+  // This lookup ignores everything that isn't a type.
+
+  // This is a fast check for the far most common case.
+  if (D->isInIdentifierNamespace(Decl::IDNS_Tag))
+    return true;
+
+  if (isa<UsingShadowDecl>(D))
+    D = cast<UsingShadowDecl>(D)->getTargetDecl();
+
+  return isa<TypeDecl>(D);
+}
+
+static bool IsAcceptableNamespaceName(NamedDecl *D, unsigned IDNS) {
+  // We don't need to look through using decls here because
+  // using decls aren't allowed to name namespaces.
+
+  return isa<NamespaceDecl>(D) || isa<NamespaceAliasDecl>(D);
+}
+
+/// Gets the default result filter for the given lookup.
+static inline
+LookupResult::ResultFilter getResultFilter(Sema::LookupNameKind NameKind) {
+  switch (NameKind) {
+  case Sema::LookupOrdinaryName:
+  case Sema::LookupTagName:
+  case Sema::LookupMemberName:
+  case Sema::LookupRedeclarationWithLinkage: // FIXME: check linkage, scoping
+  case Sema::LookupUsingDeclName:
+  case Sema::LookupObjCProtocolName:
+  case Sema::LookupObjCImplementationName:
+    return &IsAcceptableIDNS;
+
+  case Sema::LookupOperatorName:
+    return &IsAcceptableOperatorName;
+
+  case Sema::LookupNestedNameSpecifierName:
+    return &IsAcceptableNestedNameSpecifierName;
+
+  case Sema::LookupNamespaceName:
+    return &IsAcceptableNamespaceName;
+  }
+
+  llvm_unreachable("unkknown lookup kind");
+  return 0;
+}
+
+// Retrieve the set of identifier namespaces that correspond to a
+// specific kind of name lookup.
+static inline unsigned getIDNS(Sema::LookupNameKind NameKind,
+                               bool CPlusPlus,
+                               bool Redeclaration) {
+  unsigned IDNS = 0;
+  switch (NameKind) {
+  case Sema::LookupOrdinaryName:
+  case Sema::LookupOperatorName:
+  case Sema::LookupRedeclarationWithLinkage:
+    IDNS = Decl::IDNS_Ordinary;
+    if (CPlusPlus) {
+      IDNS |= Decl::IDNS_Tag | Decl::IDNS_Member;
+      if (Redeclaration) IDNS |= Decl::IDNS_TagFriend | Decl::IDNS_OrdinaryFriend;
+    }
+    break;
+
+  case Sema::LookupTagName:
+    IDNS = Decl::IDNS_Tag;
+    if (CPlusPlus && Redeclaration)
+      IDNS |= Decl::IDNS_TagFriend;
+    break;
+
+  case Sema::LookupMemberName:
+    IDNS = Decl::IDNS_Member;
+    if (CPlusPlus)
+      IDNS |= Decl::IDNS_Tag | Decl::IDNS_Ordinary;
+    break;
+
+  case Sema::LookupNestedNameSpecifierName:
+  case Sema::LookupNamespaceName:
+    IDNS = Decl::IDNS_Ordinary | Decl::IDNS_Tag | Decl::IDNS_Member;
+    break;
+
+  case Sema::LookupUsingDeclName:
+    IDNS = Decl::IDNS_Ordinary | Decl::IDNS_Tag
+         | Decl::IDNS_Member | Decl::IDNS_Using;
+    break;
+
+  case Sema::LookupObjCProtocolName:
+    IDNS = Decl::IDNS_ObjCProtocol;
+    break;
+
+  case Sema::LookupObjCImplementationName:
+    IDNS = Decl::IDNS_ObjCImplementation;
+    break;
+  }
+  return IDNS;
+}
+
+void LookupResult::configure() {
+  IDNS = getIDNS(LookupKind,
+                 SemaRef.getLangOptions().CPlusPlus,
+                 isForRedeclaration());
+  IsAcceptableFn = getResultFilter(LookupKind);
+}
+
+// Necessary because CXXBasePaths is not complete in Sema.h
+void LookupResult::deletePaths(CXXBasePaths *Paths) {
+  delete Paths;
+}
+
+/// Resolves the result kind of this lookup.
+void LookupResult::resolveKind() {
+  unsigned N = Decls.size();
+ 
+  // Fast case: no possible ambiguity.
+  if (N == 0) {
+    assert(ResultKind == NotFound || ResultKind == NotFoundInCurrentInstantiation);
+    return;
+  }
+
+  // If there's a single decl, we need to examine it to decide what
+  // kind of lookup this is.
+  if (N == 1) {
+    if (isa<FunctionTemplateDecl>(*Decls.begin()))
+      ResultKind = FoundOverloaded;
+    else if (isa<UnresolvedUsingValueDecl>(*Decls.begin()))
+      ResultKind = FoundUnresolvedValue;
+    return;
+  }
+
+  // Don't do any extra resolution if we've already resolved as ambiguous.
+  if (ResultKind == Ambiguous) return;
+
+  llvm::SmallPtrSet<NamedDecl*, 16> Unique;
+
+  bool Ambiguous = false;
+  bool HasTag = false, HasFunction = false, HasNonFunction = false;
+  bool HasFunctionTemplate = false, HasUnresolved = false;
+
+  unsigned UniqueTagIndex = 0;
+  
+  unsigned I = 0;
+  while (I < N) {
+    NamedDecl *D = Decls[I]->getUnderlyingDecl();
+    D = cast<NamedDecl>(D->getCanonicalDecl());
+
+    if (!Unique.insert(D)) {
+      // If it's not unique, pull something off the back (and
+      // continue at this index).
+      Decls[I] = Decls[--N];
+    } else {
+      // Otherwise, do some decl type analysis and then continue.
+
+      if (isa<UnresolvedUsingValueDecl>(D)) {
+        HasUnresolved = true;
+      } else if (isa<TagDecl>(D)) {
+        if (HasTag)
+          Ambiguous = true;
+        UniqueTagIndex = I;
+        HasTag = true;
+      } else if (isa<FunctionTemplateDecl>(D)) {
+        HasFunction = true;
+        HasFunctionTemplate = true;
+      } else if (isa<FunctionDecl>(D)) {
+        HasFunction = true;
+      } else {
+        if (HasNonFunction)
+          Ambiguous = true;
+        HasNonFunction = true;
+      }
+      I++;
+    }
+  }
+
+  // C++ [basic.scope.hiding]p2:
+  //   A class name or enumeration name can be hidden by the name of
+  //   an object, function, or enumerator declared in the same
+  //   scope. If a class or enumeration name and an object, function,
+  //   or enumerator are declared in the same scope (in any order)
+  //   with the same name, the class or enumeration name is hidden
+  //   wherever the object, function, or enumerator name is visible.
+  // But it's still an error if there are distinct tag types found,
+  // even if they're not visible. (ref?)
+  if (HideTags && HasTag && !Ambiguous &&
+      (HasFunction || HasNonFunction || HasUnresolved))
+    Decls[UniqueTagIndex] = Decls[--N];
+
+  Decls.set_size(N);
+
+  if (HasNonFunction && (HasFunction || HasUnresolved))
+    Ambiguous = true;
+
+  if (Ambiguous)
+    setAmbiguous(LookupResult::AmbiguousReference);
+  else if (HasUnresolved)
+    ResultKind = LookupResult::FoundUnresolvedValue;
+  else if (N > 1 || HasFunctionTemplate)
+    ResultKind = LookupResult::FoundOverloaded;
+  else
+    ResultKind = LookupResult::Found;
+}
+
+void LookupResult::addDeclsFromBasePaths(const CXXBasePaths &P) {
+  CXXBasePaths::const_paths_iterator I, E;
+  DeclContext::lookup_iterator DI, DE;
+  for (I = P.begin(), E = P.end(); I != E; ++I)
+    for (llvm::tie(DI,DE) = I->Decls; DI != DE; ++DI)
+      addDecl(*DI);
+}
+
+void LookupResult::setAmbiguousBaseSubobjects(CXXBasePaths &P) {
+  Paths = new CXXBasePaths;
+  Paths->swap(P);
+  addDeclsFromBasePaths(*Paths);
+  resolveKind();
+  setAmbiguous(AmbiguousBaseSubobjects);
+}
+
+void LookupResult::setAmbiguousBaseSubobjectTypes(CXXBasePaths &P) {
+  Paths = new CXXBasePaths;
+  Paths->swap(P);
+  addDeclsFromBasePaths(*Paths);
+  resolveKind();
+  setAmbiguous(AmbiguousBaseSubobjectTypes);
+}
+
+void LookupResult::print(llvm::raw_ostream &Out) {
+  Out << Decls.size() << " result(s)";
+  if (isAmbiguous()) Out << ", ambiguous";
+  if (Paths) Out << ", base paths present";
+  
+  for (iterator I = begin(), E = end(); I != E; ++I) {
+    Out << "\n";
+    (*I)->print(Out, 2);
+  }
+}
+
+// Adds all qualifying matches for a name within a decl context to the
+// given lookup result.  Returns true if any matches were found.
+static bool LookupDirect(LookupResult &R, const DeclContext *DC) {
+  bool Found = false;
+
+  DeclContext::lookup_const_iterator I, E;
+  for (llvm::tie(I, E) = DC->lookup(R.getLookupName()); I != E; ++I) {
+    NamedDecl *D = *I;
+    if (R.isAcceptableDecl(D)) {
+      R.addDecl(D);
+      Found = true;
+    }
+  }
+
+  if (R.getLookupName().getNameKind()
+        != DeclarationName::CXXConversionFunctionName ||
+      R.getLookupName().getCXXNameType()->isDependentType() ||
+      !isa<CXXRecordDecl>(DC))
+    return Found;
+
+  // C++ [temp.mem]p6:
+  //   A specialization of a conversion function template is not found by 
+  //   name lookup. Instead, any conversion function templates visible in the
+  //   context of the use are considered. [...]
+  const CXXRecordDecl *Record = cast<CXXRecordDecl>(DC);
+  if (!Record->isDefinition())
+    return Found;
+
+  const UnresolvedSetImpl *Unresolved = Record->getConversionFunctions();
+  for (UnresolvedSetImpl::iterator U = Unresolved->begin(), 
+         UEnd = Unresolved->end(); U != UEnd; ++U) {
+    FunctionTemplateDecl *ConvTemplate = dyn_cast<FunctionTemplateDecl>(*U);
+    if (!ConvTemplate)
+      continue;
+    
+    // When we're performing lookup for the purposes of redeclaration, just
+    // add the conversion function template. When we deduce template 
+    // arguments for specializations, we'll end up unifying the return 
+    // type of the new declaration with the type of the function template.
+    if (R.isForRedeclaration()) {
+      R.addDecl(ConvTemplate);
+      Found = true;
+      continue;
+    }
+    
+    // C++ [temp.mem]p6:
+    //   [...] For each such operator, if argument deduction succeeds 
+    //   (14.9.2.3), the resulting specialization is used as if found by 
+    //   name lookup.
+    //
+    // When referencing a conversion function for any purpose other than
+    // a redeclaration (such that we'll be building an expression with the
+    // result), perform template argument deduction and place the 
+    // specialization into the result set. We do this to avoid forcing all
+    // callers to perform special deduction for conversion functions.
+    Sema::TemplateDeductionInfo Info(R.getSema().Context, R.getNameLoc());
+    FunctionDecl *Specialization = 0;
+    
+    const FunctionProtoType *ConvProto        
+      = ConvTemplate->getTemplatedDecl()->getType()->getAs<FunctionProtoType>();
+    assert(ConvProto && "Nonsensical conversion function template type");
+
+    // Compute the type of the function that we would expect the conversion
+    // function to have, if it were to match the name given.
+    // FIXME: Calling convention!
+    QualType ExpectedType
+      = R.getSema().Context.getFunctionType(R.getLookupName().getCXXNameType(),
+                                            0, 0, ConvProto->isVariadic(),
+                                            ConvProto->getTypeQuals(),
+                                            false, false, 0, 0,
+                                            ConvProto->getNoReturnAttr());
+ 
+    // Perform template argument deduction against the type that we would
+    // expect the function to have.
+    if (R.getSema().DeduceTemplateArguments(ConvTemplate, 0, ExpectedType,
+                                            Specialization, Info)
+          == Sema::TDK_Success) {
+      R.addDecl(Specialization);
+      Found = true;
+    }
+  }
+
+  return Found;
+}
+
+// Performs C++ unqualified lookup into the given file context.
+static bool
+CppNamespaceLookup(LookupResult &R, ASTContext &Context, DeclContext *NS,
+                   UnqualUsingDirectiveSet &UDirs) {
+
+  assert(NS && NS->isFileContext() && "CppNamespaceLookup() requires namespace!");
+
+  // Perform direct name lookup into the LookupCtx.
+  bool Found = LookupDirect(R, NS);
+
+  // Perform direct name lookup into the namespaces nominated by the
+  // using directives whose common ancestor is this namespace.
+  UnqualUsingDirectiveSet::const_iterator UI, UEnd;
+  llvm::tie(UI, UEnd) = UDirs.getNamespacesFor(NS);
+
+  for (; UI != UEnd; ++UI)
+    if (LookupDirect(R, UI->getNominatedNamespace()))
+      Found = true;
+
+  R.resolveKind();
+
+  return Found;
+}
+
+static bool isNamespaceOrTranslationUnitScope(Scope *S) {
+  if (DeclContext *Ctx = static_cast<DeclContext*>(S->getEntity()))
+    return Ctx->isFileContext();
+  return false;
+}
+
+// Find the next outer declaration context corresponding to this scope.
+static DeclContext *findOuterContext(Scope *S) {
+  for (S = S->getParent(); S; S = S->getParent())
+    if (S->getEntity())
+      return static_cast<DeclContext *>(S->getEntity())->getPrimaryContext();
+  
+  return 0;
+}
+
+bool Sema::CppLookupName(LookupResult &R, Scope *S) {
+  assert(getLangOptions().CPlusPlus && "Can perform only C++ lookup");
+
+  DeclarationName Name = R.getLookupName();
+
+  Scope *Initial = S;
+  IdentifierResolver::iterator
+    I = IdResolver.begin(Name),
+    IEnd = IdResolver.end();
+
+  // First we lookup local scope.
+  // We don't consider using-directives, as per 7.3.4.p1 [namespace.udir]
+  // ...During unqualified name lookup (3.4.1), the names appear as if
+  // they were declared in the nearest enclosing namespace which contains
+  // both the using-directive and the nominated namespace.
+  // [Note: in this context, "contains" means "contains directly or
+  // indirectly".
+  //
+  // For example:
+  // namespace A { int i; }
+  // void foo() {
+  //   int i;
+  //   {
+  //     using namespace A;
+  //     ++i; // finds local 'i', A::i appears at global scope
+  //   }
+  // }
+  //
+  for (; S && !isNamespaceOrTranslationUnitScope(S); S = S->getParent()) {
+    // Check whether the IdResolver has anything in this scope.
+    bool Found = false;
+    for (; I != IEnd && S->isDeclScope(DeclPtrTy::make(*I)); ++I) {
+      if (R.isAcceptableDecl(*I)) {
+        Found = true;
+        R.addDecl(*I);
+      }
+    }
+    if (Found) {
+      R.resolveKind();
+      return true;
+    }
+
+    if (DeclContext *Ctx = static_cast<DeclContext*>(S->getEntity())) {
+      DeclContext *OuterCtx = findOuterContext(S);
+      for (; Ctx && Ctx->getPrimaryContext() != OuterCtx; 
+           Ctx = Ctx->getLookupParent()) {
+        // We do not directly look into function or method contexts
+        // (since all local variables are found via the identifier
+        // changes) or in transparent contexts (since those entities
+        // will be found in the nearest enclosing non-transparent
+        // context).
+        if (Ctx->isFunctionOrMethod() || Ctx->isTransparentContext())
+          continue;
+        
+        // Perform qualified name lookup into this context.
+        // FIXME: In some cases, we know that every name that could be found by
+        // this qualified name lookup will also be on the identifier chain. For
+        // example, inside a class without any base classes, we never need to
+        // perform qualified lookup because all of the members are on top of the
+        // identifier chain.
+        if (LookupQualifiedName(R, Ctx, /*InUnqualifiedLookup=*/true))
+          return true;
+      }
+    }
+  }
+
+  // Stop if we ran out of scopes.
+  // FIXME:  This really, really shouldn't be happening.
+  if (!S) return false;
+
+  // Collect UsingDirectiveDecls in all scopes, and recursively all
+  // nominated namespaces by those using-directives.
+  //
+  // FIXME: Cache this sorted list in Scope structure, and DeclContext, so we
+  // don't build it for each lookup!
+
+  UnqualUsingDirectiveSet UDirs;
+  UDirs.visitScopeChain(Initial, S);
+  UDirs.done();
+
+  // Lookup namespace scope, and global scope.
+  // Unqualified name lookup in C++ requires looking into scopes
+  // that aren't strictly lexical, and therefore we walk through the
+  // context as well as walking through the scopes.
+
+  for (; S; S = S->getParent()) {
+    DeclContext *Ctx = static_cast<DeclContext *>(S->getEntity());
+    if (Ctx && Ctx->isTransparentContext())
+      continue;
+
+    // Check whether the IdResolver has anything in this scope.
+    bool Found = false;
+    for (; I != IEnd && S->isDeclScope(DeclPtrTy::make(*I)); ++I) {
+      if (R.isAcceptableDecl(*I)) {
+        // We found something.  Look for anything else in our scope
+        // with this same name and in an acceptable identifier
+        // namespace, so that we can construct an overload set if we
+        // need to.
+        Found = true;
+        R.addDecl(*I);
+      }
+    }
+
+    if (Ctx) {
+      assert(Ctx->isFileContext() &&
+             "We should have been looking only at file context here already.");
+
+      // Look into context considering using-directives.
+      if (CppNamespaceLookup(R, Context, Ctx, UDirs))
+        Found = true;
+    }
+
+    if (Found) {
+      R.resolveKind();
+      return true;
+    }
+
+    if (R.isForRedeclaration() && Ctx && !Ctx->isTransparentContext())
+      return false;
+  }
+
+  return !R.empty();
+}
+
+/// @brief Perform unqualified name lookup starting from a given
+/// scope.
+///
+/// Unqualified name lookup (C++ [basic.lookup.unqual], C99 6.2.1) is
+/// used to find names within the current scope. For example, 'x' in
+/// @code
+/// int x;
+/// int f() {
+///   return x; // unqualified name look finds 'x' in the global scope
+/// }
+/// @endcode
+///
+/// Different lookup criteria can find different names. For example, a
+/// particular scope can have both a struct and a function of the same
+/// name, and each can be found by certain lookup criteria. For more
+/// information about lookup criteria, see the documentation for the
+/// class LookupCriteria.
+///
+/// @param S        The scope from which unqualified name lookup will
+/// begin. If the lookup criteria permits, name lookup may also search
+/// in the parent scopes.
+///
+/// @param Name     The name of the entity that we are searching for.
+///
+/// @param Loc      If provided, the source location where we're performing
+/// name lookup. At present, this is only used to produce diagnostics when
+/// C library functions (like "malloc") are implicitly declared.
+///
+/// @returns The result of name lookup, which includes zero or more
+/// declarations and possibly additional information used to diagnose
+/// ambiguities.
+bool Sema::LookupName(LookupResult &R, Scope *S, bool AllowBuiltinCreation) {
+  DeclarationName Name = R.getLookupName();
+  if (!Name) return false;
+
+  LookupNameKind NameKind = R.getLookupKind();
+
+  if (!getLangOptions().CPlusPlus) {
+    // Unqualified name lookup in C/Objective-C is purely lexical, so
+    // search in the declarations attached to the name.
+
+    if (NameKind == Sema::LookupRedeclarationWithLinkage) {
+      // Find the nearest non-transparent declaration scope.
+      while (!(S->getFlags() & Scope::DeclScope) ||
+             (S->getEntity() &&
+              static_cast<DeclContext *>(S->getEntity())
+                ->isTransparentContext()))
+        S = S->getParent();
+    }
+
+    unsigned IDNS = R.getIdentifierNamespace();
+
+    // 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.
+    bool LeftStartingScope = false;
+
+    for (IdentifierResolver::iterator I = IdResolver.begin(Name),
+                                   IEnd = IdResolver.end();
+         I != IEnd; ++I)
+      if ((*I)->isInIdentifierNamespace(IDNS)) {
+        if (NameKind == LookupRedeclarationWithLinkage) {
+          // Determine whether this (or a previous) declaration is
+          // out-of-scope.
+          if (!LeftStartingScope && !S->isDeclScope(DeclPtrTy::make(*I)))
+            LeftStartingScope = true;
+
+          // If we found something outside of our starting scope that
+          // does not have linkage, skip it.
+          if (LeftStartingScope && !((*I)->hasLinkage()))
+            continue;
+        }
+
+        R.addDecl(*I);
+
+        if ((*I)->getAttr<OverloadableAttr>()) {
+          // If this declaration has the "overloadable" attribute, we
+          // might have a set of overloaded functions.
+
+          // Figure out what scope the identifier is in.
+          while (!(S->getFlags() & Scope::DeclScope) ||
+                 !S->isDeclScope(DeclPtrTy::make(*I)))
+            S = S->getParent();
+
+          // Find the last declaration in this scope (with the same
+          // name, naturally).
+          IdentifierResolver::iterator LastI = I;
+          for (++LastI; LastI != IEnd; ++LastI) {
+            if (!S->isDeclScope(DeclPtrTy::make(*LastI)))
+              break;
+            R.addDecl(*LastI);
+          }
+        }
+
+        R.resolveKind();
+
+        return true;
+      }
+  } else {
+    // Perform C++ unqualified name lookup.
+    if (CppLookupName(R, S))
+      return true;
+  }
+
+  // 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 (NameKind == LookupOrdinaryName ||
+      NameKind == LookupRedeclarationWithLinkage) {
+    IdentifierInfo *II = Name.getAsIdentifierInfo();
+    if (II && AllowBuiltinCreation) {
+      // If this is a builtin on this (or all) targets, create the decl.
+      if (unsigned BuiltinID = II->getBuiltinID()) {
+        // In C++, we don't have any predefined library functions like
+        // 'malloc'. Instead, we'll just error.
+        if (getLangOptions().CPlusPlus &&
+            Context.BuiltinInfo.isPredefinedLibFunction(BuiltinID))
+          return false;
+
+        NamedDecl *D = LazilyCreateBuiltin((IdentifierInfo *)II, BuiltinID,
+                                           S, R.isForRedeclaration(),
+                                           R.getNameLoc());
+        if (D) R.addDecl(D);
+        return (D != NULL);
+      }
+    }
+  }
+  return false;
+}
+
+/// @brief Perform qualified name lookup in the namespaces nominated by
+/// using directives by the given context.
+///
+/// C++98 [namespace.qual]p2:
+///   Given X::m (where X is a user-declared namespace), or given ::m
+///   (where X is the global namespace), let S be the set of all
+///   declarations of m in X and in the transitive closure of all
+///   namespaces nominated by using-directives in X and its used
+///   namespaces, except that using-directives are ignored in any
+///   namespace, including X, directly containing one or more
+///   declarations of m. No namespace is searched more than once in
+///   the lookup of a name. If S is the empty set, the program is
+///   ill-formed. Otherwise, if S has exactly one member, or if the
+///   context of the reference is a using-declaration
+///   (namespace.udecl), S is the required set of declarations of
+///   m. Otherwise if the use of m is not one that allows a unique
+///   declaration to be chosen from S, the program is ill-formed.
+/// C++98 [namespace.qual]p5:
+///   During the lookup of a qualified namespace member name, if the
+///   lookup finds more than one declaration of the member, and if one
+///   declaration introduces a class name or enumeration name and the
+///   other declarations either introduce the same object, the same
+///   enumerator or a set of functions, the non-type name hides the
+///   class or enumeration name if and only if the declarations are
+///   from the same namespace; otherwise (the declarations are from
+///   different namespaces), the program is ill-formed.
+static bool LookupQualifiedNameInUsingDirectives(LookupResult &R,
+                                                 DeclContext *StartDC) {
+  assert(StartDC->isFileContext() && "start context is not a file context");
+
+  DeclContext::udir_iterator I = StartDC->using_directives_begin();
+  DeclContext::udir_iterator E = StartDC->using_directives_end();
+
+  if (I == E) return false;
+
+  // We have at least added all these contexts to the queue.
+  llvm::DenseSet<DeclContext*> Visited;
+  Visited.insert(StartDC);
+
+  // We have not yet looked into these namespaces, much less added
+  // their "using-children" to the queue.
+  llvm::SmallVector<NamespaceDecl*, 8> Queue;
+
+  // We have already looked into the initial namespace; seed the queue
+  // with its using-children.
+  for (; I != E; ++I) {
+    NamespaceDecl *ND = (*I)->getNominatedNamespace()->getOriginalNamespace();
+    if (Visited.insert(ND).second)
+      Queue.push_back(ND);
+  }
+
+  // The easiest way to implement the restriction in [namespace.qual]p5
+  // is to check whether any of the individual results found a tag
+  // and, if so, to declare an ambiguity if the final result is not
+  // a tag.
+  bool FoundTag = false;
+  bool FoundNonTag = false;
+
+  LookupResult LocalR(LookupResult::Temporary, R);
+
+  bool Found = false;
+  while (!Queue.empty()) {
+    NamespaceDecl *ND = Queue.back();
+    Queue.pop_back();
+
+    // We go through some convolutions here to avoid copying results
+    // between LookupResults.
+    bool UseLocal = !R.empty();
+    LookupResult &DirectR = UseLocal ? LocalR : R;
+    bool FoundDirect = LookupDirect(DirectR, ND);
+
+    if (FoundDirect) {
+      // First do any local hiding.
+      DirectR.resolveKind();
+
+      // If the local result is a tag, remember that.
+      if (DirectR.isSingleTagDecl())
+        FoundTag = true;
+      else
+        FoundNonTag = true;
+
+      // Append the local results to the total results if necessary.
+      if (UseLocal) {
+        R.addAllDecls(LocalR);
+        LocalR.clear();
+      }
+    }
+
+    // If we find names in this namespace, ignore its using directives.
+    if (FoundDirect) {
+      Found = true;
+      continue;
+    }
+
+    for (llvm::tie(I,E) = ND->getUsingDirectives(); I != E; ++I) {
+      NamespaceDecl *Nom = (*I)->getNominatedNamespace();
+      if (Visited.insert(Nom).second)
+        Queue.push_back(Nom);
+    }
+  }
+
+  if (Found) {
+    if (FoundTag && FoundNonTag)
+      R.setAmbiguousQualifiedTagHiding();
+    else
+      R.resolveKind();
+  }
+
+  return Found;
+}
+
+/// \brief Perform qualified name lookup into a given context.
+///
+/// Qualified name lookup (C++ [basic.lookup.qual]) is used to find
+/// names when the context of those names is explicit specified, e.g.,
+/// "std::vector" or "x->member", or as part of unqualified name lookup.
+///
+/// Different lookup criteria can find different names. For example, a
+/// particular scope can have both a struct and a function of the same
+/// name, and each can be found by certain lookup criteria. For more
+/// information about lookup criteria, see the documentation for the
+/// class LookupCriteria.
+///
+/// \param R captures both the lookup criteria and any lookup results found.
+///
+/// \param LookupCtx The context in which qualified name lookup will
+/// search. If the lookup criteria permits, name lookup may also search
+/// in the parent contexts or (for C++ classes) base classes.
+///
+/// \param InUnqualifiedLookup true if this is qualified name lookup that 
+/// occurs as part of unqualified name lookup.
+///
+/// \returns true if lookup succeeded, false if it failed.
+bool Sema::LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx,
+                               bool InUnqualifiedLookup) {
+  assert(LookupCtx && "Sema::LookupQualifiedName requires a lookup context");
+
+  if (!R.getLookupName())
+    return false;
+
+  // Make sure that the declaration context is complete.
+  assert((!isa<TagDecl>(LookupCtx) ||
+          LookupCtx->isDependentContext() ||
+          cast<TagDecl>(LookupCtx)->isDefinition() ||
+          Context.getTypeDeclType(cast<TagDecl>(LookupCtx))->getAs<TagType>()
+            ->isBeingDefined()) &&
+         "Declaration context must already be complete!");
+
+  // Perform qualified name lookup into the LookupCtx.
+  if (LookupDirect(R, LookupCtx)) {
+    R.resolveKind();
+    if (isa<CXXRecordDecl>(LookupCtx))
+      R.setNamingClass(cast<CXXRecordDecl>(LookupCtx));
+    return true;
+  }
+
+  // Don't descend into implied contexts for redeclarations.
+  // C++98 [namespace.qual]p6:
+  //   In a declaration for a namespace member in which the
+  //   declarator-id is a qualified-id, given that the qualified-id
+  //   for the namespace member has the form
+  //     nested-name-specifier unqualified-id
+  //   the unqualified-id shall name a member of the namespace
+  //   designated by the nested-name-specifier.
+  // See also [class.mfct]p5 and [class.static.data]p2.
+  if (R.isForRedeclaration())
+    return false;
+
+  // If this is a namespace, look it up in the implied namespaces.
+  if (LookupCtx->isFileContext())
+    return LookupQualifiedNameInUsingDirectives(R, LookupCtx);
+
+  // If this isn't a C++ class, we aren't allowed to look into base
+  // classes, we're done.
+  CXXRecordDecl *LookupRec = dyn_cast<CXXRecordDecl>(LookupCtx);
+  if (!LookupRec)
+    return false;
+
+  // If we're performing qualified name lookup into a dependent class,
+  // then we are actually looking into a current instantiation. If we have any
+  // dependent base classes, then we either have to delay lookup until 
+  // template instantiation time (at which point all bases will be available)
+  // or we have to fail.
+  if (!InUnqualifiedLookup && LookupRec->isDependentContext() &&
+      LookupRec->hasAnyDependentBases()) {
+    R.setNotFoundInCurrentInstantiation();
+    return false;
+  }
+    
+  // Perform lookup into our base classes.
+  CXXBasePaths Paths;
+  Paths.setOrigin(LookupRec);
+
+  // Look for this member in our base classes
+  CXXRecordDecl::BaseMatchesCallback *BaseCallback = 0;
+  switch (R.getLookupKind()) {
+    case LookupOrdinaryName:
+    case LookupMemberName:
+    case LookupRedeclarationWithLinkage:
+      BaseCallback = &CXXRecordDecl::FindOrdinaryMember;
+      break;
+      
+    case LookupTagName:
+      BaseCallback = &CXXRecordDecl::FindTagMember;
+      break;
+
+    case LookupUsingDeclName:
+      // This lookup is for redeclarations only.
+      
+    case LookupOperatorName:
+    case LookupNamespaceName:
+    case LookupObjCProtocolName:
+    case LookupObjCImplementationName:
+      // These lookups will never find a member in a C++ class (or base class).
+      return false;
+      
+    case LookupNestedNameSpecifierName:
+      BaseCallback = &CXXRecordDecl::FindNestedNameSpecifierMember;
+      break;
+  }
+  
+  if (!LookupRec->lookupInBases(BaseCallback,
+                                R.getLookupName().getAsOpaquePtr(), Paths))
+    return false;
+
+  R.setNamingClass(LookupRec);
+
+  // C++ [class.member.lookup]p2:
+  //   [...] If the resulting set of declarations are not all from
+  //   sub-objects of the same type, or the set has a nonstatic member
+  //   and includes members from distinct sub-objects, there is an
+  //   ambiguity and the program is ill-formed. Otherwise that set is
+  //   the result of the lookup.
+  // FIXME: support using declarations!
+  QualType SubobjectType;
+  int SubobjectNumber = 0;
+  AccessSpecifier SubobjectAccess = AS_private;
+  for (CXXBasePaths::paths_iterator Path = Paths.begin(), PathEnd = Paths.end();
+       Path != PathEnd; ++Path) {
+    const CXXBasePathElement &PathElement = Path->back();
+
+    // Pick the best (i.e. most permissive i.e. numerically lowest) access
+    // across all paths.
+    SubobjectAccess = std::min(SubobjectAccess, Path->Access);
+    
+    // Determine whether we're looking at a distinct sub-object or not.
+    if (SubobjectType.isNull()) {
+      // This is the first subobject we've looked at. Record its type.
+      SubobjectType = Context.getCanonicalType(PathElement.Base->getType());
+      SubobjectNumber = PathElement.SubobjectNumber;
+    } else if (SubobjectType
+                 != Context.getCanonicalType(PathElement.Base->getType())) {
+      // We found members of the given name in two subobjects of
+      // different types. This lookup is ambiguous.
+      R.setAmbiguousBaseSubobjectTypes(Paths);
+      return true;
+    } else if (SubobjectNumber != PathElement.SubobjectNumber) {
+      // We have a different subobject of the same type.
+
+      // C++ [class.member.lookup]p5:
+      //   A static member, a nested type or an enumerator defined in
+      //   a base class T can unambiguously be found even if an object
+      //   has more than one base class subobject of type T.
+      Decl *FirstDecl = *Path->Decls.first;
+      if (isa<VarDecl>(FirstDecl) ||
+          isa<TypeDecl>(FirstDecl) ||
+          isa<EnumConstantDecl>(FirstDecl))
+        continue;
+
+      if (isa<CXXMethodDecl>(FirstDecl)) {
+        // Determine whether all of the methods are static.
+        bool AllMethodsAreStatic = true;
+        for (DeclContext::lookup_iterator Func = Path->Decls.first;
+             Func != Path->Decls.second; ++Func) {
+          if (!isa<CXXMethodDecl>(*Func)) {
+            assert(isa<TagDecl>(*Func) && "Non-function must be a tag decl");
+            break;
+          }
+
+          if (!cast<CXXMethodDecl>(*Func)->isStatic()) {
+            AllMethodsAreStatic = false;
+            break;
+          }
+        }
+
+        if (AllMethodsAreStatic)
+          continue;
+      }
+
+      // We have found a nonstatic member name in multiple, distinct
+      // subobjects. Name lookup is ambiguous.
+      R.setAmbiguousBaseSubobjects(Paths);
+      return true;
+    }
+  }
+
+  // Lookup in a base class succeeded; return these results.
+
+  DeclContext::lookup_iterator I, E;
+  for (llvm::tie(I,E) = Paths.front().Decls; I != E; ++I) {
+    NamedDecl *D = *I;
+    AccessSpecifier AS = CXXRecordDecl::MergeAccess(SubobjectAccess,
+                                                    D->getAccess());
+    R.addDecl(D, AS);
+  }
+  R.resolveKind();
+  return true;
+}
+
+/// @brief Performs name lookup for a name that was parsed in the
+/// source code, and may contain a C++ scope specifier.
+///
+/// This routine is a convenience routine meant to be called from
+/// contexts that receive a name and an optional C++ scope specifier
+/// (e.g., "N::M::x"). It will then perform either qualified or
+/// unqualified name lookup (with LookupQualifiedName or LookupName,
+/// respectively) on the given name and return those results.
+///
+/// @param S        The scope from which unqualified name lookup will
+/// begin.
+///
+/// @param SS       An optional C++ scope-specifier, e.g., "::N::M".
+///
+/// @param Name     The name of the entity that name lookup will
+/// search for.
+///
+/// @param Loc      If provided, the source location where we're performing
+/// name lookup. At present, this is only used to produce diagnostics when
+/// C library functions (like "malloc") are implicitly declared.
+///
+/// @param EnteringContext Indicates whether we are going to enter the
+/// context of the scope-specifier SS (if present).
+///
+/// @returns True if any decls were found (but possibly ambiguous)
+bool Sema::LookupParsedName(LookupResult &R, Scope *S, const CXXScopeSpec *SS,
+                            bool AllowBuiltinCreation, bool EnteringContext) {
+  if (SS && SS->isInvalid()) {
+    // When the scope specifier is invalid, don't even look for
+    // anything.
+    return false;
+  }
+
+  if (SS && SS->isSet()) {
+    if (DeclContext *DC = computeDeclContext(*SS, EnteringContext)) {
+      // We have resolved the scope specifier to a particular declaration
+      // contex, and will perform name lookup in that context.
+      if (!DC->isDependentContext() && RequireCompleteDeclContext(*SS))
+        return false;
+
+      R.setContextRange(SS->getRange());
+
+      return LookupQualifiedName(R, DC);
+    }
+
+    // We could not resolve the scope specified to a specific declaration
+    // context, which means that SS refers to an unknown specialization.
+    // Name lookup can't find anything in this case.
+    return false;
+  }
+
+  // Perform unqualified name lookup starting in the given scope.
+  return LookupName(R, S, AllowBuiltinCreation);
+}
+
+
+/// @brief Produce a diagnostic describing the ambiguity that resulted
+/// from name lookup.
+///
+/// @param Result       The ambiguous name lookup result.
+///
+/// @param Name         The name of the entity that name lookup was
+/// searching for.
+///
+/// @param NameLoc      The location of the name within the source code.
+///
+/// @param LookupRange  A source range that provides more
+/// source-location information concerning the lookup itself. For
+/// example, this range might highlight a nested-name-specifier that
+/// precedes the name.
+///
+/// @returns true
+bool Sema::DiagnoseAmbiguousLookup(LookupResult &Result) {
+  assert(Result.isAmbiguous() && "Lookup result must be ambiguous");
+
+  DeclarationName Name = Result.getLookupName();
+  SourceLocation NameLoc = Result.getNameLoc();
+  SourceRange LookupRange = Result.getContextRange();
+
+  switch (Result.getAmbiguityKind()) {
+  case LookupResult::AmbiguousBaseSubobjects: {
+    CXXBasePaths *Paths = Result.getBasePaths();
+    QualType SubobjectType = Paths->front().back().Base->getType();
+    Diag(NameLoc, diag::err_ambiguous_member_multiple_subobjects)
+      << Name << SubobjectType << getAmbiguousPathsDisplayString(*Paths)
+      << LookupRange;
+    
+    DeclContext::lookup_iterator Found = Paths->front().Decls.first;
+    while (isa<CXXMethodDecl>(*Found) &&
+           cast<CXXMethodDecl>(*Found)->isStatic())
+      ++Found;
+    
+    Diag((*Found)->getLocation(), diag::note_ambiguous_member_found);
+    
+    return true;
+  }
+
+  case LookupResult::AmbiguousBaseSubobjectTypes: {
+    Diag(NameLoc, diag::err_ambiguous_member_multiple_subobject_types)
+      << Name << LookupRange;
+    
+    CXXBasePaths *Paths = Result.getBasePaths();
+    std::set<Decl *> DeclsPrinted;
+    for (CXXBasePaths::paths_iterator Path = Paths->begin(),
+                                      PathEnd = Paths->end();
+         Path != PathEnd; ++Path) {
+      Decl *D = *Path->Decls.first;
+      if (DeclsPrinted.insert(D).second)
+        Diag(D->getLocation(), diag::note_ambiguous_member_found);
+    }
+
+    return true;
+  }
+
+  case LookupResult::AmbiguousTagHiding: {
+    Diag(NameLoc, diag::err_ambiguous_tag_hiding) << Name << LookupRange;
+
+    llvm::SmallPtrSet<NamedDecl*,8> TagDecls;
+
+    LookupResult::iterator DI, DE = Result.end();
+    for (DI = Result.begin(); DI != DE; ++DI)
+      if (TagDecl *TD = dyn_cast<TagDecl>(*DI)) {
+        TagDecls.insert(TD);
+        Diag(TD->getLocation(), diag::note_hidden_tag);
+      }
+
+    for (DI = Result.begin(); DI != DE; ++DI)
+      if (!isa<TagDecl>(*DI))
+        Diag((*DI)->getLocation(), diag::note_hiding_object);
+
+    // For recovery purposes, go ahead and implement the hiding.
+    LookupResult::Filter F = Result.makeFilter();
+    while (F.hasNext()) {
+      if (TagDecls.count(F.next()))
+        F.erase();
+    }
+    F.done();
+
+    return true;
+  }
+
+  case LookupResult::AmbiguousReference: {
+    Diag(NameLoc, diag::err_ambiguous_reference) << Name << LookupRange;
+  
+    LookupResult::iterator DI = Result.begin(), DE = Result.end();
+    for (; DI != DE; ++DI)
+      Diag((*DI)->getLocation(), diag::note_ambiguous_candidate) << *DI;
+
+    return true;
+  }
+  }
+
+  llvm_unreachable("unknown ambiguity kind");
+  return true;
+}
+
+static void
+addAssociatedClassesAndNamespaces(QualType T,
+                                  ASTContext &Context,
+                          Sema::AssociatedNamespaceSet &AssociatedNamespaces,
+                                  Sema::AssociatedClassSet &AssociatedClasses);
+
+static void CollectNamespace(Sema::AssociatedNamespaceSet &Namespaces,
+                             DeclContext *Ctx) {
+  if (Ctx->isFileContext())
+    Namespaces.insert(Ctx);
+}
+
+// \brief Add the associated classes and namespaces for argument-dependent
+// lookup that involves a template argument (C++ [basic.lookup.koenig]p2).
+static void
+addAssociatedClassesAndNamespaces(const TemplateArgument &Arg,
+                                  ASTContext &Context,
+                           Sema::AssociatedNamespaceSet &AssociatedNamespaces,
+                                  Sema::AssociatedClassSet &AssociatedClasses) {
+  // C++ [basic.lookup.koenig]p2, last bullet:
+  //   -- [...] ;
+  switch (Arg.getKind()) {
+    case TemplateArgument::Null:
+      break;
+
+    case TemplateArgument::Type:
+      // [...] the namespaces and classes associated with the types of the
+      // template arguments provided for template type parameters (excluding
+      // template template parameters)
+      addAssociatedClassesAndNamespaces(Arg.getAsType(), Context,
+                                        AssociatedNamespaces,
+                                        AssociatedClasses);
+      break;
+
+    case TemplateArgument::Template: {
+      // [...] the namespaces in which any template template arguments are
+      // defined; and the classes in which any member templates used as
+      // template template arguments are defined.
+      TemplateName Template = Arg.getAsTemplate();
+      if (ClassTemplateDecl *ClassTemplate
+                 = dyn_cast<ClassTemplateDecl>(Template.getAsTemplateDecl())) {
+        DeclContext *Ctx = ClassTemplate->getDeclContext();
+        if (CXXRecordDecl *EnclosingClass = dyn_cast<CXXRecordDecl>(Ctx))
+          AssociatedClasses.insert(EnclosingClass);
+        // Add the associated namespace for this class.
+        while (Ctx->isRecord())
+          Ctx = Ctx->getParent();
+        CollectNamespace(AssociatedNamespaces, Ctx);
+      }
+      break;
+    }
+      
+    case TemplateArgument::Declaration:
+    case TemplateArgument::Integral:
+    case TemplateArgument::Expression:
+      // [Note: non-type template arguments do not contribute to the set of
+      //  associated namespaces. ]
+      break;
+
+    case TemplateArgument::Pack:
+      for (TemplateArgument::pack_iterator P = Arg.pack_begin(),
+                                        PEnd = Arg.pack_end();
+           P != PEnd; ++P)
+        addAssociatedClassesAndNamespaces(*P, Context,
+                                          AssociatedNamespaces,
+                                          AssociatedClasses);
+      break;
+  }
+}
+
+// \brief Add the associated classes and namespaces for
+// argument-dependent lookup with an argument of class type
+// (C++ [basic.lookup.koenig]p2).
+static void
+addAssociatedClassesAndNamespaces(CXXRecordDecl *Class,
+                                  ASTContext &Context,
+                            Sema::AssociatedNamespaceSet &AssociatedNamespaces,
+                            Sema::AssociatedClassSet &AssociatedClasses) {
+  // C++ [basic.lookup.koenig]p2:
+  //   [...]
+  //     -- If T is a class type (including unions), its associated
+  //        classes are: the class itself; the class of which it is a
+  //        member, if any; and its direct and indirect base
+  //        classes. Its associated namespaces are the namespaces in
+  //        which its associated classes are defined.
+
+  // Add the class of which it is a member, if any.
+  DeclContext *Ctx = Class->getDeclContext();
+  if (CXXRecordDecl *EnclosingClass = dyn_cast<CXXRecordDecl>(Ctx))
+    AssociatedClasses.insert(EnclosingClass);
+  // Add the associated namespace for this class.
+  while (Ctx->isRecord())
+    Ctx = Ctx->getParent();
+  CollectNamespace(AssociatedNamespaces, Ctx);
+
+  // Add the class itself. If we've already seen this class, we don't
+  // need to visit base classes.
+  if (!AssociatedClasses.insert(Class))
+    return;
+
+  // -- If T is a template-id, its associated namespaces and classes are
+  //    the namespace in which the template is defined; for member
+  //    templates, the member template’s class; the namespaces and classes
+  //    associated with the types of the template arguments provided for
+  //    template type parameters (excluding template template parameters); the
+  //    namespaces in which any template template arguments are defined; and
+  //    the classes in which any member templates used as template template
+  //    arguments are defined. [Note: non-type template arguments do not
+  //    contribute to the set of associated namespaces. ]
+  if (ClassTemplateSpecializationDecl *Spec
+        = dyn_cast<ClassTemplateSpecializationDecl>(Class)) {
+    DeclContext *Ctx = Spec->getSpecializedTemplate()->getDeclContext();
+    if (CXXRecordDecl *EnclosingClass = dyn_cast<CXXRecordDecl>(Ctx))
+      AssociatedClasses.insert(EnclosingClass);
+    // Add the associated namespace for this class.
+    while (Ctx->isRecord())
+      Ctx = Ctx->getParent();
+    CollectNamespace(AssociatedNamespaces, Ctx);
+
+    const TemplateArgumentList &TemplateArgs = Spec->getTemplateArgs();
+    for (unsigned I = 0, N = TemplateArgs.size(); I != N; ++I)
+      addAssociatedClassesAndNamespaces(TemplateArgs[I], Context,
+                                        AssociatedNamespaces,
+                                        AssociatedClasses);
+  }
+
+  // Only recurse into base classes for complete types.
+  if (!Class->hasDefinition()) {
+    // FIXME: we might need to instantiate templates here
+    return;
+  }
+
+  // Add direct and indirect base classes along with their associated
+  // namespaces.
+  llvm::SmallVector<CXXRecordDecl *, 32> Bases;
+  Bases.push_back(Class);
+  while (!Bases.empty()) {
+    // Pop this class off the stack.
+    Class = Bases.back();
+    Bases.pop_back();
+
+    // Visit the base classes.
+    for (CXXRecordDecl::base_class_iterator Base = Class->bases_begin(),
+                                         BaseEnd = Class->bases_end();
+         Base != BaseEnd; ++Base) {
+      const RecordType *BaseType = Base->getType()->getAs<RecordType>();
+      // In dependent contexts, we do ADL twice, and the first time around,
+      // the base type might be a dependent TemplateSpecializationType, or a
+      // TemplateTypeParmType. If that happens, simply ignore it.
+      // FIXME: If we want to support export, we probably need to add the
+      // namespace of the template in a TemplateSpecializationType, or even
+      // the classes and namespaces of known non-dependent arguments.
+      if (!BaseType)
+        continue;
+      CXXRecordDecl *BaseDecl = cast<CXXRecordDecl>(BaseType->getDecl());
+      if (AssociatedClasses.insert(BaseDecl)) {
+        // Find the associated namespace for this base class.
+        DeclContext *BaseCtx = BaseDecl->getDeclContext();
+        while (BaseCtx->isRecord())
+          BaseCtx = BaseCtx->getParent();
+        CollectNamespace(AssociatedNamespaces, BaseCtx);
+
+        // Make sure we visit the bases of this base class.
+        if (BaseDecl->bases_begin() != BaseDecl->bases_end())
+          Bases.push_back(BaseDecl);
+      }
+    }
+  }
+}
+
+// \brief Add the associated classes and namespaces for
+// argument-dependent lookup with an argument of type T
+// (C++ [basic.lookup.koenig]p2).
+static void
+addAssociatedClassesAndNamespaces(QualType T,
+                                  ASTContext &Context,
+                            Sema::AssociatedNamespaceSet &AssociatedNamespaces,
+                                  Sema::AssociatedClassSet &AssociatedClasses) {
+  // C++ [basic.lookup.koenig]p2:
+  //
+  //   For each argument type T in the function call, there is a set
+  //   of zero or more associated namespaces and a set of zero or more
+  //   associated classes to be considered. The sets of namespaces and
+  //   classes is determined entirely by the types of the function
+  //   arguments (and the namespace of any template template
+  //   argument). Typedef names and using-declarations used to specify
+  //   the types do not contribute to this set. The sets of namespaces
+  //   and classes are determined in the following way:
+  T = Context.getCanonicalType(T).getUnqualifiedType();
+
+  //    -- If T is a pointer to U or an array of U, its associated
+  //       namespaces and classes are those associated with U.
+  //
+  // We handle this by unwrapping pointer and array types immediately,
+  // to avoid unnecessary recursion.
+  while (true) {
+    if (const PointerType *Ptr = T->getAs<PointerType>())
+      T = Ptr->getPointeeType();
+    else if (const ArrayType *Ptr = Context.getAsArrayType(T))
+      T = Ptr->getElementType();
+    else
+      break;
+  }
+
+  //     -- If T is a fundamental type, its associated sets of
+  //        namespaces and classes are both empty.
+  if (T->getAs<BuiltinType>())
+    return;
+
+  //     -- If T is a class type (including unions), its associated
+  //        classes are: the class itself; the class of which it is a
+  //        member, if any; and its direct and indirect base
+  //        classes. Its associated namespaces are the namespaces in
+  //        which its associated classes are defined.
+  if (const RecordType *ClassType = T->getAs<RecordType>())
+    if (CXXRecordDecl *ClassDecl
+        = dyn_cast<CXXRecordDecl>(ClassType->getDecl())) {
+      addAssociatedClassesAndNamespaces(ClassDecl, Context,
+                                        AssociatedNamespaces,
+                                        AssociatedClasses);
+      return;
+    }
+
+  //     -- If T is an enumeration type, its associated namespace is
+  //        the namespace in which it is defined. If it is class
+  //        member, its associated class is the member’s class; else
+  //        it has no associated class.
+  if (const EnumType *EnumT = T->getAs<EnumType>()) {
+    EnumDecl *Enum = EnumT->getDecl();
+
+    DeclContext *Ctx = Enum->getDeclContext();
+    if (CXXRecordDecl *EnclosingClass = dyn_cast<CXXRecordDecl>(Ctx))
+      AssociatedClasses.insert(EnclosingClass);
+
+    // Add the associated namespace for this class.
+    while (Ctx->isRecord())
+      Ctx = Ctx->getParent();
+    CollectNamespace(AssociatedNamespaces, Ctx);
+
+    return;
+  }
+
+  //     -- If T is a function type, its associated namespaces and
+  //        classes are those associated with the function parameter
+  //        types and those associated with the return type.
+  if (const FunctionType *FnType = T->getAs<FunctionType>()) {
+    // Return type
+    addAssociatedClassesAndNamespaces(FnType->getResultType(),
+                                      Context,
+                                      AssociatedNamespaces, AssociatedClasses);
+
+    const FunctionProtoType *Proto = dyn_cast<FunctionProtoType>(FnType);
+    if (!Proto)
+      return;
+
+    // Argument types
+    for (FunctionProtoType::arg_type_iterator Arg = Proto->arg_type_begin(),
+                                           ArgEnd = Proto->arg_type_end();
+         Arg != ArgEnd; ++Arg)
+      addAssociatedClassesAndNamespaces(*Arg, Context,
+                                        AssociatedNamespaces, AssociatedClasses);
+
+    return;
+  }
+
+  //     -- If T is a pointer to a member function of a class X, its
+  //        associated namespaces and classes are those associated
+  //        with the function parameter types and return type,
+  //        together with those associated with X.
+  //
+  //     -- If T is a pointer to a data member of class X, its
+  //        associated namespaces and classes are those associated
+  //        with the member type together with those associated with
+  //        X.
+  if (const MemberPointerType *MemberPtr = T->getAs<MemberPointerType>()) {
+    // Handle the type that the pointer to member points to.
+    addAssociatedClassesAndNamespaces(MemberPtr->getPointeeType(),
+                                      Context,
+                                      AssociatedNamespaces,
+                                      AssociatedClasses);
+
+    // Handle the class type into which this points.
+    if (const RecordType *Class = MemberPtr->getClass()->getAs<RecordType>())
+      addAssociatedClassesAndNamespaces(cast<CXXRecordDecl>(Class->getDecl()),
+                                        Context,
+                                        AssociatedNamespaces,
+                                        AssociatedClasses);
+
+    return;
+  }
+
+  // FIXME: What about block pointers?
+  // FIXME: What about Objective-C message sends?
+}
+
+/// \brief Find the associated classes and namespaces for
+/// argument-dependent lookup for a call with the given set of
+/// arguments.
+///
+/// This routine computes the sets of associated classes and associated
+/// namespaces searched by argument-dependent lookup
+/// (C++ [basic.lookup.argdep]) for a given set of arguments.
+void
+Sema::FindAssociatedClassesAndNamespaces(Expr **Args, unsigned NumArgs,
+                                 AssociatedNamespaceSet &AssociatedNamespaces,
+                                 AssociatedClassSet &AssociatedClasses) {
+  AssociatedNamespaces.clear();
+  AssociatedClasses.clear();
+
+  // C++ [basic.lookup.koenig]p2:
+  //   For each argument type T in the function call, there is a set
+  //   of zero or more associated namespaces and a set of zero or more
+  //   associated classes to be considered. The sets of namespaces and
+  //   classes is determined entirely by the types of the function
+  //   arguments (and the namespace of any template template
+  //   argument).
+  for (unsigned ArgIdx = 0; ArgIdx != NumArgs; ++ArgIdx) {
+    Expr *Arg = Args[ArgIdx];
+
+    if (Arg->getType() != Context.OverloadTy) {
+      addAssociatedClassesAndNamespaces(Arg->getType(), Context,
+                                        AssociatedNamespaces,
+                                        AssociatedClasses);
+      continue;
+    }
+
+    // [...] In addition, if the argument is the name or address of a
+    // set of overloaded functions and/or function templates, its
+    // associated classes and namespaces are the union of those
+    // associated with each of the members of the set: the namespace
+    // in which the function or function template is defined and the
+    // classes and namespaces associated with its (non-dependent)
+    // parameter types and return type.
+    Arg = Arg->IgnoreParens();
+    if (UnaryOperator *unaryOp = dyn_cast<UnaryOperator>(Arg))
+      if (unaryOp->getOpcode() == UnaryOperator::AddrOf)
+        Arg = unaryOp->getSubExpr();
+
+    // TODO: avoid the copies.  This should be easy when the cases
+    // share a storage implementation.
+    llvm::SmallVector<NamedDecl*, 8> Functions;
+
+    if (UnresolvedLookupExpr *ULE = dyn_cast<UnresolvedLookupExpr>(Arg))
+      Functions.append(ULE->decls_begin(), ULE->decls_end());
+    else
+      continue;
+
+    for (llvm::SmallVectorImpl<NamedDecl*>::iterator I = Functions.begin(),
+           E = Functions.end(); I != E; ++I) {
+      // Look through any using declarations to find the underlying function.
+      NamedDecl *Fn = (*I)->getUnderlyingDecl();
+
+      FunctionDecl *FDecl = dyn_cast<FunctionDecl>(Fn);
+      if (!FDecl)
+        FDecl = cast<FunctionTemplateDecl>(Fn)->getTemplatedDecl();
+
+      // Add the classes and namespaces associated with the parameter
+      // types and return type of this function.
+      addAssociatedClassesAndNamespaces(FDecl->getType(), Context,
+                                        AssociatedNamespaces,
+                                        AssociatedClasses);
+    }
+  }
+}
+
+/// IsAcceptableNonMemberOperatorCandidate - Determine whether Fn is
+/// an acceptable non-member overloaded operator for a call whose
+/// arguments have types T1 (and, if non-empty, T2). This routine
+/// implements the check in C++ [over.match.oper]p3b2 concerning
+/// enumeration types.
+static bool
+IsAcceptableNonMemberOperatorCandidate(FunctionDecl *Fn,
+                                       QualType T1, QualType T2,
+                                       ASTContext &Context) {
+  if (T1->isDependentType() || (!T2.isNull() && T2->isDependentType()))
+    return true;
+
+  if (T1->isRecordType() || (!T2.isNull() && T2->isRecordType()))
+    return true;
+
+  const FunctionProtoType *Proto = Fn->getType()->getAs<FunctionProtoType>();
+  if (Proto->getNumArgs() < 1)
+    return false;
+
+  if (T1->isEnumeralType()) {
+    QualType ArgType = Proto->getArgType(0).getNonReferenceType();
+    if (Context.hasSameUnqualifiedType(T1, ArgType))
+      return true;
+  }
+
+  if (Proto->getNumArgs() < 2)
+    return false;
+
+  if (!T2.isNull() && T2->isEnumeralType()) {
+    QualType ArgType = Proto->getArgType(1).getNonReferenceType();
+    if (Context.hasSameUnqualifiedType(T2, ArgType))
+      return true;
+  }
+
+  return false;
+}
+
+NamedDecl *Sema::LookupSingleName(Scope *S, DeclarationName Name,
+                                  LookupNameKind NameKind,
+                                  RedeclarationKind Redecl) {
+  LookupResult R(*this, Name, SourceLocation(), NameKind, Redecl);
+  LookupName(R, S);
+  return R.getAsSingle<NamedDecl>();
+}
+
+/// \brief Find the protocol with the given name, if any.
+ObjCProtocolDecl *Sema::LookupProtocol(IdentifierInfo *II) {
+  Decl *D = LookupSingleName(TUScope, II, LookupObjCProtocolName);
+  return cast_or_null<ObjCProtocolDecl>(D);
+}
+
+void Sema::LookupOverloadedOperatorName(OverloadedOperatorKind Op, Scope *S,
+                                        QualType T1, QualType T2,
+                                        UnresolvedSetImpl &Functions) {
+  // C++ [over.match.oper]p3:
+  //     -- The set of non-member candidates is the result of the
+  //        unqualified lookup of operator@ in the context of the
+  //        expression according to the usual rules for name lookup in
+  //        unqualified function calls (3.4.2) except that all member
+  //        functions are ignored. However, if no operand has a class
+  //        type, only those non-member functions in the lookup set
+  //        that have a first parameter of type T1 or "reference to
+  //        (possibly cv-qualified) T1", when T1 is an enumeration
+  //        type, or (if there is a right operand) a second parameter
+  //        of type T2 or "reference to (possibly cv-qualified) T2",
+  //        when T2 is an enumeration type, are candidate functions.
+  DeclarationName OpName = Context.DeclarationNames.getCXXOperatorName(Op);
+  LookupResult Operators(*this, OpName, SourceLocation(), LookupOperatorName);
+  LookupName(Operators, S);
+
+  assert(!Operators.isAmbiguous() && "Operator lookup cannot be ambiguous");
+
+  if (Operators.empty())
+    return;
+
+  for (LookupResult::iterator Op = Operators.begin(), OpEnd = Operators.end();
+       Op != OpEnd; ++Op) {
+    if (FunctionDecl *FD = dyn_cast<FunctionDecl>(*Op)) {
+      if (IsAcceptableNonMemberOperatorCandidate(FD, T1, T2, Context))
+        Functions.addDecl(FD, Op.getAccess()); // FIXME: canonical FD
+    } else if (FunctionTemplateDecl *FunTmpl
+                 = dyn_cast<FunctionTemplateDecl>(*Op)) {
+      // FIXME: friend operators?
+      // FIXME: do we need to check IsAcceptableNonMemberOperatorCandidate,
+      // later?
+      if (!FunTmpl->getDeclContext()->isRecord())
+        Functions.addDecl(FunTmpl, Op.getAccess());
+    }
+  }
+}
+
+void ADLResult::insert(NamedDecl *New) {
+  NamedDecl *&Old = Decls[cast<NamedDecl>(New->getCanonicalDecl())];
+
+  // If we haven't yet seen a decl for this key, or the last decl
+  // was exactly this one, we're done.
+  if (Old == 0 || Old == New) {
+    Old = New;
+    return;
+  }
+
+  // Otherwise, decide which is a more recent redeclaration.
+  FunctionDecl *OldFD, *NewFD;
+  if (isa<FunctionTemplateDecl>(New)) {
+    OldFD = cast<FunctionTemplateDecl>(Old)->getTemplatedDecl();
+    NewFD = cast<FunctionTemplateDecl>(New)->getTemplatedDecl();
+  } else {
+    OldFD = cast<FunctionDecl>(Old);
+    NewFD = cast<FunctionDecl>(New);
+  }
+
+  FunctionDecl *Cursor = NewFD;
+  while (true) {
+    Cursor = Cursor->getPreviousDeclaration();
+
+    // If we got to the end without finding OldFD, OldFD is the newer
+    // declaration;  leave things as they are.
+    if (!Cursor) return;
+
+    // If we do find OldFD, then NewFD is newer.
+    if (Cursor == OldFD) break;
+
+    // Otherwise, keep looking.
+  }
+
+  Old = New;
+}
+
+void Sema::ArgumentDependentLookup(DeclarationName Name, bool Operator,
+                                   Expr **Args, unsigned NumArgs,
+                                   ADLResult &Result) {
+  // Find all of the associated namespaces and classes based on the
+  // arguments we have.
+  AssociatedNamespaceSet AssociatedNamespaces;
+  AssociatedClassSet AssociatedClasses;
+  FindAssociatedClassesAndNamespaces(Args, NumArgs,
+                                     AssociatedNamespaces,
+                                     AssociatedClasses);
+
+  QualType T1, T2;
+  if (Operator) {
+    T1 = Args[0]->getType();
+    if (NumArgs >= 2)
+      T2 = Args[1]->getType();
+  }
+
+  // C++ [basic.lookup.argdep]p3:
+  //   Let X be the lookup set produced by unqualified lookup (3.4.1)
+  //   and let Y be the lookup set produced by argument dependent
+  //   lookup (defined as follows). If X contains [...] then Y is
+  //   empty. Otherwise Y is the set of declarations found in the
+  //   namespaces associated with the argument types as described
+  //   below. The set of declarations found by the lookup of the name
+  //   is the union of X and Y.
+  //
+  // Here, we compute Y and add its members to the overloaded
+  // candidate set.
+  for (AssociatedNamespaceSet::iterator NS = AssociatedNamespaces.begin(),
+                                     NSEnd = AssociatedNamespaces.end();
+       NS != NSEnd; ++NS) {
+    //   When considering an associated namespace, the lookup is the
+    //   same as the lookup performed when the associated namespace is
+    //   used as a qualifier (3.4.3.2) except that:
+    //
+    //     -- Any using-directives in the associated namespace are
+    //        ignored.
+    //
+    //     -- Any namespace-scope friend functions declared in
+    //        associated classes are visible within their respective
+    //        namespaces even if they are not visible during an ordinary
+    //        lookup (11.4).
+    DeclContext::lookup_iterator I, E;
+    for (llvm::tie(I, E) = (*NS)->lookup(Name); I != E; ++I) {
+      NamedDecl *D = *I;
+      // If the only declaration here is an ordinary friend, consider
+      // it only if it was declared in an associated classes.
+      if (D->getIdentifierNamespace() == Decl::IDNS_OrdinaryFriend) {
+        DeclContext *LexDC = D->getLexicalDeclContext();
+        if (!AssociatedClasses.count(cast<CXXRecordDecl>(LexDC)))
+          continue;
+      }
+
+      if (isa<UsingShadowDecl>(D))
+        D = cast<UsingShadowDecl>(D)->getTargetDecl();
+
+      if (isa<FunctionDecl>(D)) {
+        if (Operator &&
+            !IsAcceptableNonMemberOperatorCandidate(cast<FunctionDecl>(D),
+                                                    T1, T2, Context))
+          continue;
+      } else if (!isa<FunctionTemplateDecl>(D))
+        continue;
+
+      Result.insert(D);
+    }
+  }
+}
+
+//----------------------------------------------------------------------------
+// Search for all visible declarations.
+//----------------------------------------------------------------------------
+VisibleDeclConsumer::~VisibleDeclConsumer() { }
+
+namespace {
+
+class ShadowContextRAII;
+
+class VisibleDeclsRecord {
+public:
+  /// \brief An entry in the shadow map, which is optimized to store a
+  /// single declaration (the common case) but can also store a list
+  /// of declarations.
+  class ShadowMapEntry {
+    typedef llvm::SmallVector<NamedDecl *, 4> DeclVector;
+    
+    /// \brief Contains either the solitary NamedDecl * or a vector
+    /// of declarations.
+    llvm::PointerUnion<NamedDecl *, DeclVector*> DeclOrVector;
+
+  public:
+    ShadowMapEntry() : DeclOrVector() { }
+
+    void Add(NamedDecl *ND);
+    void Destroy();
+
+    // Iteration.
+    typedef NamedDecl **iterator;
+    iterator begin();
+    iterator end();
+  };
+
+private:
+  /// \brief A mapping from declaration names to the declarations that have
+  /// this name within a particular scope.
+  typedef llvm::DenseMap<DeclarationName, ShadowMapEntry> ShadowMap;
+
+  /// \brief A list of shadow maps, which is used to model name hiding.
+  std::list<ShadowMap> ShadowMaps;
+
+  /// \brief The declaration contexts we have already visited.
+  llvm::SmallPtrSet<DeclContext *, 8> VisitedContexts;
+
+  friend class ShadowContextRAII;
+
+public:
+  /// \brief Determine whether we have already visited this context
+  /// (and, if not, note that we are going to visit that context now).
+  bool visitedContext(DeclContext *Ctx) {
+    return !VisitedContexts.insert(Ctx);
+  }
+
+  /// \brief Determine whether the given declaration is hidden in the
+  /// current scope.
+  ///
+  /// \returns the declaration that hides the given declaration, or
+  /// NULL if no such declaration exists.
+  NamedDecl *checkHidden(NamedDecl *ND);
+
+  /// \brief Add a declaration to the current shadow map.
+  void add(NamedDecl *ND) { ShadowMaps.back()[ND->getDeclName()].Add(ND); }
+};
+
+/// \brief RAII object that records when we've entered a shadow context.
+class ShadowContextRAII {
+  VisibleDeclsRecord &Visible;
+
+  typedef VisibleDeclsRecord::ShadowMap ShadowMap;
+
+public:
+  ShadowContextRAII(VisibleDeclsRecord &Visible) : Visible(Visible) {
+    Visible.ShadowMaps.push_back(ShadowMap());
+  }
+
+  ~ShadowContextRAII() {
+    for (ShadowMap::iterator E = Visible.ShadowMaps.back().begin(),
+                          EEnd = Visible.ShadowMaps.back().end();
+         E != EEnd;
+         ++E)
+      E->second.Destroy();
+
+    Visible.ShadowMaps.pop_back();
+  }
+};
+
+} // end anonymous namespace
+
+void VisibleDeclsRecord::ShadowMapEntry::Add(NamedDecl *ND) {
+  if (DeclOrVector.isNull()) {
+    // 0 - > 1 elements: just set the single element information.
+    DeclOrVector = ND;
+    return;
+  }
+  
+  if (NamedDecl *PrevND = DeclOrVector.dyn_cast<NamedDecl *>()) {
+    // 1 -> 2 elements: create the vector of results and push in the
+    // existing declaration.
+    DeclVector *Vec = new DeclVector;
+    Vec->push_back(PrevND);
+    DeclOrVector = Vec;
+  }
+
+  // Add the new element to the end of the vector.
+  DeclOrVector.get<DeclVector*>()->push_back(ND);
+}
+
+void VisibleDeclsRecord::ShadowMapEntry::Destroy() {
+  if (DeclVector *Vec = DeclOrVector.dyn_cast<DeclVector *>()) {
+    delete Vec;
+    DeclOrVector = ((NamedDecl *)0);
+  }
+}
+
+VisibleDeclsRecord::ShadowMapEntry::iterator 
+VisibleDeclsRecord::ShadowMapEntry::begin() {
+  if (DeclOrVector.isNull())
+    return 0;
+
+  if (DeclOrVector.dyn_cast<NamedDecl *>())
+    return &reinterpret_cast<NamedDecl*&>(DeclOrVector);
+
+  return DeclOrVector.get<DeclVector *>()->begin();
+}
+
+VisibleDeclsRecord::ShadowMapEntry::iterator 
+VisibleDeclsRecord::ShadowMapEntry::end() {
+  if (DeclOrVector.isNull())
+    return 0;
+
+  if (DeclOrVector.dyn_cast<NamedDecl *>())
+    return &reinterpret_cast<NamedDecl*&>(DeclOrVector) + 1;
+
+  return DeclOrVector.get<DeclVector *>()->end();
+}
+
+NamedDecl *VisibleDeclsRecord::checkHidden(NamedDecl *ND) {
+  // Look through using declarations.
+  ND = ND->getUnderlyingDecl();
+  
+  unsigned IDNS = ND->getIdentifierNamespace();
+  std::list<ShadowMap>::reverse_iterator SM = ShadowMaps.rbegin();
+  for (std::list<ShadowMap>::reverse_iterator SMEnd = ShadowMaps.rend();
+       SM != SMEnd; ++SM) {
+    ShadowMap::iterator Pos = SM->find(ND->getDeclName());
+    if (Pos == SM->end())
+      continue;
+
+    for (ShadowMapEntry::iterator I = Pos->second.begin(), 
+                               IEnd = Pos->second.end();
+         I != IEnd; ++I) {
+      // A tag declaration does not hide a non-tag declaration.
+      if ((*I)->getIdentifierNamespace() == Decl::IDNS_Tag &&
+          (IDNS & (Decl::IDNS_Member | Decl::IDNS_Ordinary | 
+                   Decl::IDNS_ObjCProtocol)))
+        continue;
+
+      // Protocols are in distinct namespaces from everything else.
+      if ((((*I)->getIdentifierNamespace() & Decl::IDNS_ObjCProtocol)
+           || (IDNS & Decl::IDNS_ObjCProtocol)) &&
+          (*I)->getIdentifierNamespace() != IDNS)
+        continue;
+
+      // Functions and function templates in the same scope overload
+      // rather than hide.  FIXME: Look for hiding based on function
+      // signatures!
+      if ((*I)->isFunctionOrFunctionTemplate() &&
+          ND->isFunctionOrFunctionTemplate() &&
+          SM == ShadowMaps.rbegin())
+        continue;
+          
+      // We've found a declaration that hides this one.
+      return *I;
+    }
+  }
+
+  return 0;
+}
+
+static void LookupVisibleDecls(DeclContext *Ctx, LookupResult &Result,
+                               bool QualifiedNameLookup,
+                               bool InBaseClass,
+                               VisibleDeclConsumer &Consumer,
+                               VisibleDeclsRecord &Visited) {
+  if (!Ctx)
+    return;
+
+  // Make sure we don't visit the same context twice.
+  if (Visited.visitedContext(Ctx->getPrimaryContext()))
+    return;
+  
+  // Enumerate all of the results in this context.
+  for (DeclContext *CurCtx = Ctx->getPrimaryContext(); CurCtx; 
+       CurCtx = CurCtx->getNextContext()) {
+    for (DeclContext::decl_iterator D = CurCtx->decls_begin(), 
+                                 DEnd = CurCtx->decls_end();
+         D != DEnd; ++D) {
+      if (NamedDecl *ND = dyn_cast<NamedDecl>(*D))
+        if (Result.isAcceptableDecl(ND)) {
+          Consumer.FoundDecl(ND, Visited.checkHidden(ND), InBaseClass);
+          Visited.add(ND);
+        }
+
+      // Visit transparent contexts inside this context.
+      if (DeclContext *InnerCtx = dyn_cast<DeclContext>(*D)) {
+        if (InnerCtx->isTransparentContext())
+          LookupVisibleDecls(InnerCtx, Result, QualifiedNameLookup, InBaseClass,
+                             Consumer, Visited);
+      }
+    }
+  }
+
+  // Traverse using directives for qualified name lookup.
+  if (QualifiedNameLookup) {
+    ShadowContextRAII Shadow(Visited);
+    DeclContext::udir_iterator I, E;
+    for (llvm::tie(I, E) = Ctx->getUsingDirectives(); I != E; ++I) {
+      LookupVisibleDecls((*I)->getNominatedNamespace(), Result, 
+                         QualifiedNameLookup, InBaseClass, Consumer, Visited);
+    }
+  }
+
+  // Traverse the contexts of inherited C++ classes.
+  if (CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(Ctx)) {
+    if (!Record->hasDefinition())
+      return;
+
+    for (CXXRecordDecl::base_class_iterator B = Record->bases_begin(),
+                                         BEnd = Record->bases_end();
+         B != BEnd; ++B) {
+      QualType BaseType = B->getType();
+      
+      // Don't look into dependent bases, because name lookup can't look
+      // there anyway.
+      if (BaseType->isDependentType())
+        continue;
+      
+      const RecordType *Record = BaseType->getAs<RecordType>();
+      if (!Record)
+        continue;
+      
+      // FIXME: It would be nice to be able to determine whether referencing
+      // a particular member would be ambiguous. For example, given
+      //
+      //   struct A { int member; };
+      //   struct B { int member; };
+      //   struct C : A, B { };
+      //
+      //   void f(C *c) { c->### }
+      //
+      // accessing 'member' would result in an ambiguity. However, we
+      // could be smart enough to qualify the member with the base
+      // class, e.g.,
+      //
+      //   c->B::member
+      //
+      // or
+      //
+      //   c->A::member
+      
+      // Find results in this base class (and its bases).
+      ShadowContextRAII Shadow(Visited);
+      LookupVisibleDecls(Record->getDecl(), Result, QualifiedNameLookup,
+                         true, Consumer, Visited);
+    }
+  }
+  
+  // Traverse the contexts of Objective-C classes.
+  if (ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Ctx)) {
+    // Traverse categories.
+    for (ObjCCategoryDecl *Category = IFace->getCategoryList();
+         Category; Category = Category->getNextClassCategory()) {
+      ShadowContextRAII Shadow(Visited);
+      LookupVisibleDecls(Category, Result, QualifiedNameLookup, false, 
+                         Consumer, Visited);
+    }
+
+    // Traverse protocols.
+    for (ObjCInterfaceDecl::protocol_iterator I = IFace->protocol_begin(),
+         E = IFace->protocol_end(); I != E; ++I) {
+      ShadowContextRAII Shadow(Visited);
+      LookupVisibleDecls(*I, Result, QualifiedNameLookup, false, Consumer, 
+                         Visited);
+    }
+
+    // Traverse the superclass.
+    if (IFace->getSuperClass()) {
+      ShadowContextRAII Shadow(Visited);
+      LookupVisibleDecls(IFace->getSuperClass(), Result, QualifiedNameLookup,
+                         true, Consumer, Visited);
+    }
+  } else if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Ctx)) {
+    for (ObjCProtocolDecl::protocol_iterator I = Protocol->protocol_begin(),
+           E = Protocol->protocol_end(); I != E; ++I) {
+      ShadowContextRAII Shadow(Visited);
+      LookupVisibleDecls(*I, Result, QualifiedNameLookup, false, Consumer, 
+                         Visited);
+    }
+  } else if (ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(Ctx)) {
+    for (ObjCCategoryDecl::protocol_iterator I = Category->protocol_begin(),
+           E = Category->protocol_end(); I != E; ++I) {
+      ShadowContextRAII Shadow(Visited);
+      LookupVisibleDecls(*I, Result, QualifiedNameLookup, false, Consumer, 
+                         Visited);
+    }
+  }
+}
+
+static void LookupVisibleDecls(Scope *S, LookupResult &Result,
+                               UnqualUsingDirectiveSet &UDirs,
+                               VisibleDeclConsumer &Consumer,
+                               VisibleDeclsRecord &Visited) {
+  if (!S)
+    return;
+
+  if (!S->getEntity() || !S->getParent() ||
+      ((DeclContext *)S->getEntity())->isFunctionOrMethod()) {
+    // Walk through the declarations in this Scope.
+    for (Scope::decl_iterator D = S->decl_begin(), DEnd = S->decl_end();
+         D != DEnd; ++D) {
+      if (NamedDecl *ND = dyn_cast<NamedDecl>((Decl *)((*D).get())))
+        if (Result.isAcceptableDecl(ND)) {
+          Consumer.FoundDecl(ND, Visited.checkHidden(ND), false);
+          Visited.add(ND);
+        }
+    }
+  }
+  
+  DeclContext *Entity = 0;
+  if (S->getEntity()) {
+    // Look into this scope's declaration context, along with any of its
+    // parent lookup contexts (e.g., enclosing classes), up to the point
+    // where we hit the context stored in the next outer scope.
+    Entity = (DeclContext *)S->getEntity();
+    DeclContext *OuterCtx = findOuterContext(S);
+    
+    for (DeclContext *Ctx = Entity; Ctx && Ctx->getPrimaryContext() != OuterCtx;
+         Ctx = Ctx->getLookupParent()) {
+      if (ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(Ctx)) {
+        if (Method->isInstanceMethod()) {
+          // For instance methods, look for ivars in the method's interface.
+          LookupResult IvarResult(Result.getSema(), Result.getLookupName(),
+                                  Result.getNameLoc(), Sema::LookupMemberName);
+          if (ObjCInterfaceDecl *IFace = Method->getClassInterface())
+            LookupVisibleDecls(IFace, IvarResult, /*QualifiedNameLookup=*/false, 
+                               /*InBaseClass=*/false, Consumer, Visited);
+        }
+
+        // We've already performed all of the name lookup that we need
+        // to for Objective-C methods; the next context will be the
+        // outer scope.
+        break;
+      }
+
+      if (Ctx->isFunctionOrMethod())
+        continue;
+      
+      LookupVisibleDecls(Ctx, Result, /*QualifiedNameLookup=*/false, 
+                         /*InBaseClass=*/false, Consumer, Visited);
+    }
+  } else if (!S->getParent()) {
+    // Look into the translation unit scope. We walk through the translation
+    // unit's declaration context, because the Scope itself won't have all of
+    // the declarations if we loaded a precompiled header.
+    // FIXME: We would like the translation unit's Scope object to point to the
+    // translation unit, so we don't need this special "if" branch. However,
+    // doing so would force the normal C++ name-lookup code to look into the
+    // translation unit decl when the IdentifierInfo chains would suffice. 
+    // Once we fix that problem (which is part of a more general "don't look
+    // in DeclContexts unless we have to" optimization), we can eliminate this.
+    Entity = Result.getSema().Context.getTranslationUnitDecl();
+    LookupVisibleDecls(Entity, Result, /*QualifiedNameLookup=*/false, 
+                       /*InBaseClass=*/false, Consumer, Visited);
+  } 
+  
+  if (Entity) {
+    // Lookup visible declarations in any namespaces found by using
+    // directives.
+    UnqualUsingDirectiveSet::const_iterator UI, UEnd;
+    llvm::tie(UI, UEnd) = UDirs.getNamespacesFor(Entity);
+    for (; UI != UEnd; ++UI)
+      LookupVisibleDecls(const_cast<DeclContext *>(UI->getNominatedNamespace()),
+                         Result, /*QualifiedNameLookup=*/false, 
+                         /*InBaseClass=*/false, Consumer, Visited);
+  }
+
+  // Lookup names in the parent scope.
+  ShadowContextRAII Shadow(Visited);
+  LookupVisibleDecls(S->getParent(), Result, UDirs, Consumer, Visited);
+}
+
+void Sema::LookupVisibleDecls(Scope *S, LookupNameKind Kind,
+                              VisibleDeclConsumer &Consumer) {
+  // Determine the set of using directives available during
+  // unqualified name lookup.
+  Scope *Initial = S;
+  UnqualUsingDirectiveSet UDirs;
+  if (getLangOptions().CPlusPlus) {
+    // Find the first namespace or translation-unit scope.
+    while (S && !isNamespaceOrTranslationUnitScope(S))
+      S = S->getParent();
+
+    UDirs.visitScopeChain(Initial, S);
+  }
+  UDirs.done();
+
+  // Look for visible declarations.
+  LookupResult Result(*this, DeclarationName(), SourceLocation(), Kind);
+  VisibleDeclsRecord Visited;
+  ShadowContextRAII Shadow(Visited);
+  ::LookupVisibleDecls(Initial, Result, UDirs, Consumer, Visited);
+}
+
+void Sema::LookupVisibleDecls(DeclContext *Ctx, LookupNameKind Kind,
+                              VisibleDeclConsumer &Consumer) {
+  LookupResult Result(*this, DeclarationName(), SourceLocation(), Kind);
+  VisibleDeclsRecord Visited;
+  ShadowContextRAII Shadow(Visited);
+  ::LookupVisibleDecls(Ctx, Result, /*QualifiedNameLookup=*/true, 
+                       /*InBaseClass=*/false, Consumer, Visited);
+}
+
+//----------------------------------------------------------------------------
+// Typo correction
+//----------------------------------------------------------------------------
+
+namespace {
+class TypoCorrectionConsumer : public VisibleDeclConsumer {
+  /// \brief The name written that is a typo in the source.
+  llvm::StringRef Typo;
+
+  /// \brief The results found that have the smallest edit distance
+  /// found (so far) with the typo name.
+  llvm::SmallVector<NamedDecl *, 4> BestResults;
+
+  /// \brief The best edit distance found so far.
+  unsigned BestEditDistance;
+  
+public:
+  explicit TypoCorrectionConsumer(IdentifierInfo *Typo)
+    : Typo(Typo->getName()) { }
+
+  virtual void FoundDecl(NamedDecl *ND, NamedDecl *Hiding, bool InBaseClass);
+
+  typedef llvm::SmallVector<NamedDecl *, 4>::const_iterator iterator;
+  iterator begin() const { return BestResults.begin(); }
+  iterator end() const { return BestResults.end(); }
+  bool empty() const { return BestResults.empty(); }
+
+  unsigned getBestEditDistance() const { return BestEditDistance; }
+};
+
+}
+
+void TypoCorrectionConsumer::FoundDecl(NamedDecl *ND, NamedDecl *Hiding, 
+                                       bool InBaseClass) {
+  // Don't consider hidden names for typo correction.
+  if (Hiding)
+    return;
+  
+  // Only consider entities with identifiers for names, ignoring
+  // special names (constructors, overloaded operators, selectors,
+  // etc.).
+  IdentifierInfo *Name = ND->getIdentifier();
+  if (!Name)
+    return;
+
+  // Compute the edit distance between the typo and the name of this
+  // entity. If this edit distance is not worse than the best edit
+  // distance we've seen so far, add it to the list of results.
+  unsigned ED = Typo.edit_distance(Name->getName());
+  if (!BestResults.empty()) {
+    if (ED < BestEditDistance) {
+      // This result is better than any we've seen before; clear out
+      // the previous results.
+      BestResults.clear();
+      BestEditDistance = ED;
+    } else if (ED > BestEditDistance) {
+      // This result is worse than the best results we've seen so far;
+      // ignore it.
+      return;
+    }
+  } else
+    BestEditDistance = ED;
+
+  BestResults.push_back(ND);
+}
+
+/// \brief Try to "correct" a typo in the source code by finding
+/// visible declarations whose names are similar to the name that was
+/// present in the source code.
+///
+/// \param Res the \c LookupResult structure that contains the name
+/// that was present in the source code along with the name-lookup
+/// criteria used to search for the name. On success, this structure
+/// will contain the results of name lookup.
+///
+/// \param S the scope in which name lookup occurs.
+///
+/// \param SS the nested-name-specifier that precedes the name we're
+/// looking for, if present.
+///
+/// \param MemberContext if non-NULL, the context in which to look for
+/// a member access expression.
+///
+/// \param EnteringContext whether we're entering the context described by 
+/// the nested-name-specifier SS.
+///
+/// \param OPT when non-NULL, the search for visible declarations will
+/// also walk the protocols in the qualified interfaces of \p OPT.
+///
+/// \returns true if the typo was corrected, in which case the \p Res
+/// structure will contain the results of name lookup for the
+/// corrected name. Otherwise, returns false.
+bool Sema::CorrectTypo(LookupResult &Res, Scope *S, const CXXScopeSpec *SS,
+                       DeclContext *MemberContext, bool EnteringContext,
+                       const ObjCObjectPointerType *OPT) {
+  if (Diags.hasFatalErrorOccurred())
+    return false;
+
+  // Provide a stop gap for files that are just seriously broken.  Trying
+  // to correct all typos can turn into a HUGE performance penalty, causing
+  // some files to take minutes to get rejected by the parser.
+  // FIXME: Is this the right solution?
+  if (TyposCorrected == 20)
+    return false;
+  ++TyposCorrected;
+  
+  // We only attempt to correct typos for identifiers.
+  IdentifierInfo *Typo = Res.getLookupName().getAsIdentifierInfo();
+  if (!Typo)
+    return false;
+
+  // If the scope specifier itself was invalid, don't try to correct
+  // typos.
+  if (SS && SS->isInvalid())
+    return false;
+
+  // Never try to correct typos during template deduction or
+  // instantiation.
+  if (!ActiveTemplateInstantiations.empty())
+    return false;
+
+  TypoCorrectionConsumer Consumer(Typo);
+  if (MemberContext) {
+    LookupVisibleDecls(MemberContext, Res.getLookupKind(), Consumer);
+
+    // Look in qualified interfaces.
+    if (OPT) {
+      for (ObjCObjectPointerType::qual_iterator 
+             I = OPT->qual_begin(), E = OPT->qual_end(); 
+           I != E; ++I)
+        LookupVisibleDecls(*I, Res.getLookupKind(), Consumer);
+    }
+  } else if (SS && SS->isSet()) {
+    DeclContext *DC = computeDeclContext(*SS, EnteringContext);
+    if (!DC)
+      return false;
+    
+    LookupVisibleDecls(DC, Res.getLookupKind(), Consumer);
+  } else {
+    LookupVisibleDecls(S, Res.getLookupKind(), Consumer);
+  }
+
+  if (Consumer.empty())
+    return false;
+
+  // Only allow a single, closest name in the result set (it's okay to
+  // have overloads of that name, though).
+  TypoCorrectionConsumer::iterator I = Consumer.begin();
+  DeclarationName BestName = (*I)->getDeclName();
+
+  // If we've found an Objective-C ivar or property, don't perform
+  // name lookup again; we'll just return the result directly.
+  NamedDecl *FoundBest = 0;
+  if (isa<ObjCIvarDecl>(*I) || isa<ObjCPropertyDecl>(*I))
+    FoundBest = *I;
+  ++I;
+  for(TypoCorrectionConsumer::iterator IEnd = Consumer.end(); I != IEnd; ++I) {
+    if (BestName != (*I)->getDeclName())
+      return false;
+
+    // FIXME: If there are both ivars and properties of the same name,
+    // don't return both because the callee can't handle two
+    // results. We really need to separate ivar lookup from property
+    // lookup to avoid this problem.
+    FoundBest = 0;
+  }
+
+  // BestName is the closest viable name to what the user
+  // typed. However, to make sure that we don't pick something that's
+  // way off, make sure that the user typed at least 3 characters for
+  // each correction.
+  unsigned ED = Consumer.getBestEditDistance();
+  if (ED == 0 || (BestName.getAsIdentifierInfo()->getName().size() / ED) < 3)
+    return false;
+
+  // Perform name lookup again with the name we chose, and declare
+  // success if we found something that was not ambiguous.
+  Res.clear();
+  Res.setLookupName(BestName);
+
+  // If we found an ivar or property, add that result; no further
+  // lookup is required.
+  if (FoundBest)
+    Res.addDecl(FoundBest);  
+  // If we're looking into the context of a member, perform qualified
+  // name lookup on the best name.
+  else if (MemberContext)
+    LookupQualifiedName(Res, MemberContext);
+  // Perform lookup as if we had just parsed the best name.
+  else
+    LookupParsedName(Res, S, SS, /*AllowBuiltinCreation=*/false, 
+                     EnteringContext);
+
+  if (Res.isAmbiguous()) {
+    Res.suppressDiagnostics();
+    return false;
+  }
+
+  return Res.getResultKind() != LookupResult::NotFound;
+}
diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp
new file mode 100644
index 0000000..b79b1cc
--- /dev/null
+++ b/lib/Sema/SemaOverload.cpp
@@ -0,0 +1,6631 @@
+//===--- SemaOverload.cpp - C++ Overloading ---------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file provides Sema routines for C++ overloading.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Sema.h"
+#include "Lookup.h"
+#include "SemaInit.h"
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Lex/Preprocessor.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/CXXInheritance.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/ExprCXX.h"
+#include "clang/AST/TypeOrdering.h"
+#include "clang/Basic/PartialDiagnostic.h"
+#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/STLExtras.h"
+#include <algorithm>
+
+namespace clang {
+
+/// GetConversionCategory - Retrieve the implicit conversion
+/// category corresponding to the given implicit conversion kind.
+ImplicitConversionCategory
+GetConversionCategory(ImplicitConversionKind Kind) {
+  static const ImplicitConversionCategory
+    Category[(int)ICK_Num_Conversion_Kinds] = {
+    ICC_Identity,
+    ICC_Lvalue_Transformation,
+    ICC_Lvalue_Transformation,
+    ICC_Lvalue_Transformation,
+    ICC_Identity,
+    ICC_Qualification_Adjustment,
+    ICC_Promotion,
+    ICC_Promotion,
+    ICC_Promotion,
+    ICC_Conversion,
+    ICC_Conversion,
+    ICC_Conversion,
+    ICC_Conversion,
+    ICC_Conversion,
+    ICC_Conversion,
+    ICC_Conversion,
+    ICC_Conversion,
+    ICC_Conversion,
+    ICC_Conversion
+  };
+  return Category[(int)Kind];
+}
+
+/// GetConversionRank - Retrieve the implicit conversion rank
+/// corresponding to the given implicit conversion kind.
+ImplicitConversionRank GetConversionRank(ImplicitConversionKind Kind) {
+  static const ImplicitConversionRank
+    Rank[(int)ICK_Num_Conversion_Kinds] = {
+    ICR_Exact_Match,
+    ICR_Exact_Match,
+    ICR_Exact_Match,
+    ICR_Exact_Match,
+    ICR_Exact_Match,
+    ICR_Exact_Match,
+    ICR_Promotion,
+    ICR_Promotion,
+    ICR_Promotion,
+    ICR_Conversion,
+    ICR_Conversion,
+    ICR_Conversion,
+    ICR_Conversion,
+    ICR_Conversion,
+    ICR_Conversion,
+    ICR_Conversion,
+    ICR_Conversion,
+    ICR_Conversion,
+    ICR_Conversion
+  };
+  return Rank[(int)Kind];
+}
+
+/// GetImplicitConversionName - Return the name of this kind of
+/// implicit conversion.
+const char* GetImplicitConversionName(ImplicitConversionKind Kind) {
+  static const char* const Name[(int)ICK_Num_Conversion_Kinds] = {
+    "No conversion",
+    "Lvalue-to-rvalue",
+    "Array-to-pointer",
+    "Function-to-pointer",
+    "Noreturn adjustment",
+    "Qualification",
+    "Integral promotion",
+    "Floating point promotion",
+    "Complex promotion",
+    "Integral conversion",
+    "Floating conversion",
+    "Complex conversion",
+    "Floating-integral conversion",
+    "Complex-real conversion",
+    "Pointer conversion",
+    "Pointer-to-member conversion",
+    "Boolean conversion",
+    "Compatible-types conversion",
+    "Derived-to-base conversion"
+  };
+  return Name[Kind];
+}
+
+/// StandardConversionSequence - Set the standard conversion
+/// sequence to the identity conversion.
+void StandardConversionSequence::setAsIdentityConversion() {
+  First = ICK_Identity;
+  Second = ICK_Identity;
+  Third = ICK_Identity;
+  Deprecated = false;
+  ReferenceBinding = false;
+  DirectBinding = false;
+  RRefBinding = false;
+  CopyConstructor = 0;
+}
+
+/// getRank - Retrieve the rank of this standard conversion sequence
+/// (C++ 13.3.3.1.1p3). The rank is the largest rank of each of the
+/// implicit conversions.
+ImplicitConversionRank StandardConversionSequence::getRank() const {
+  ImplicitConversionRank Rank = ICR_Exact_Match;
+  if  (GetConversionRank(First) > Rank)
+    Rank = GetConversionRank(First);
+  if  (GetConversionRank(Second) > Rank)
+    Rank = GetConversionRank(Second);
+  if  (GetConversionRank(Third) > Rank)
+    Rank = GetConversionRank(Third);
+  return Rank;
+}
+
+/// isPointerConversionToBool - Determines whether this conversion is
+/// a conversion of a pointer or pointer-to-member to bool. This is
+/// used as part of the ranking of standard conversion sequences
+/// (C++ 13.3.3.2p4).
+bool StandardConversionSequence::isPointerConversionToBool() const {
+  // Note that FromType has not necessarily been transformed by the
+  // array-to-pointer or function-to-pointer implicit conversions, so
+  // check for their presence as well as checking whether FromType is
+  // a pointer.
+  if (getToType(1)->isBooleanType() &&
+      (getFromType()->isPointerType() || getFromType()->isBlockPointerType() ||
+       First == ICK_Array_To_Pointer || First == ICK_Function_To_Pointer))
+    return true;
+
+  return false;
+}
+
+/// isPointerConversionToVoidPointer - Determines whether this
+/// conversion is a conversion of a pointer to a void pointer. This is
+/// used as part of the ranking of standard conversion sequences (C++
+/// 13.3.3.2p4).
+bool
+StandardConversionSequence::
+isPointerConversionToVoidPointer(ASTContext& Context) const {
+  QualType FromType = getFromType();
+  QualType ToType = getToType(1);
+
+  // Note that FromType has not necessarily been transformed by the
+  // array-to-pointer implicit conversion, so check for its presence
+  // and redo the conversion to get a pointer.
+  if (First == ICK_Array_To_Pointer)
+    FromType = Context.getArrayDecayedType(FromType);
+
+  if (Second == ICK_Pointer_Conversion && FromType->isPointerType())
+    if (const PointerType* ToPtrType = ToType->getAs<PointerType>())
+      return ToPtrType->getPointeeType()->isVoidType();
+
+  return false;
+}
+
+/// DebugPrint - Print this standard conversion sequence to standard
+/// error. Useful for debugging overloading issues.
+void StandardConversionSequence::DebugPrint() const {
+  llvm::raw_ostream &OS = llvm::errs();
+  bool PrintedSomething = false;
+  if (First != ICK_Identity) {
+    OS << GetImplicitConversionName(First);
+    PrintedSomething = true;
+  }
+
+  if (Second != ICK_Identity) {
+    if (PrintedSomething) {
+      OS << " -> ";
+    }
+    OS << GetImplicitConversionName(Second);
+
+    if (CopyConstructor) {
+      OS << " (by copy constructor)";
+    } else if (DirectBinding) {
+      OS << " (direct reference binding)";
+    } else if (ReferenceBinding) {
+      OS << " (reference binding)";
+    }
+    PrintedSomething = true;
+  }
+
+  if (Third != ICK_Identity) {
+    if (PrintedSomething) {
+      OS << " -> ";
+    }
+    OS << GetImplicitConversionName(Third);
+    PrintedSomething = true;
+  }
+
+  if (!PrintedSomething) {
+    OS << "No conversions required";
+  }
+}
+
+/// DebugPrint - Print this user-defined conversion sequence to standard
+/// error. Useful for debugging overloading issues.
+void UserDefinedConversionSequence::DebugPrint() const {
+  llvm::raw_ostream &OS = llvm::errs();
+  if (Before.First || Before.Second || Before.Third) {
+    Before.DebugPrint();
+    OS << " -> ";
+  }
+  OS << "'" << ConversionFunction->getNameAsString() << "'";
+  if (After.First || After.Second || After.Third) {
+    OS << " -> ";
+    After.DebugPrint();
+  }
+}
+
+/// DebugPrint - Print this implicit conversion sequence to standard
+/// error. Useful for debugging overloading issues.
+void ImplicitConversionSequence::DebugPrint() const {
+  llvm::raw_ostream &OS = llvm::errs();
+  switch (ConversionKind) {
+  case StandardConversion:
+    OS << "Standard conversion: ";
+    Standard.DebugPrint();
+    break;
+  case UserDefinedConversion:
+    OS << "User-defined conversion: ";
+    UserDefined.DebugPrint();
+    break;
+  case EllipsisConversion:
+    OS << "Ellipsis conversion";
+    break;
+  case AmbiguousConversion:
+    OS << "Ambiguous conversion";
+    break;
+  case BadConversion:
+    OS << "Bad conversion";
+    break;
+  }
+
+  OS << "\n";
+}
+
+void AmbiguousConversionSequence::construct() {
+  new (&conversions()) ConversionSet();
+}
+
+void AmbiguousConversionSequence::destruct() {
+  conversions().~ConversionSet();
+}
+
+void
+AmbiguousConversionSequence::copyFrom(const AmbiguousConversionSequence &O) {
+  FromTypePtr = O.FromTypePtr;
+  ToTypePtr = O.ToTypePtr;
+  new (&conversions()) ConversionSet(O.conversions());
+}
+
+
+// IsOverload - Determine whether the given New declaration is an
+// overload of the declarations in Old. This routine returns false if
+// New and Old cannot be overloaded, e.g., if New has the same
+// signature as some function in Old (C++ 1.3.10) or if the Old
+// declarations aren't functions (or function templates) at all. When
+// it does return false, MatchedDecl will point to the decl that New
+// cannot be overloaded with.  This decl may be a UsingShadowDecl on
+// top of the underlying declaration.
+//
+// Example: Given the following input:
+//
+//   void f(int, float); // #1
+//   void f(int, int); // #2
+//   int f(int, int); // #3
+//
+// When we process #1, there is no previous declaration of "f",
+// so IsOverload will not be used.
+//
+// When we process #2, Old contains only the FunctionDecl for #1.  By
+// comparing the parameter types, we see that #1 and #2 are overloaded
+// (since they have different signatures), so this routine returns
+// false; MatchedDecl is unchanged.
+//
+// When we process #3, Old is an overload set containing #1 and #2. We
+// compare the signatures of #3 to #1 (they're overloaded, so we do
+// nothing) and then #3 to #2. Since the signatures of #3 and #2 are
+// identical (return types of functions are not part of the
+// signature), IsOverload returns false and MatchedDecl will be set to
+// point to the FunctionDecl for #2.
+Sema::OverloadKind
+Sema::CheckOverload(FunctionDecl *New, const LookupResult &Old,
+                    NamedDecl *&Match) {
+  for (LookupResult::iterator I = Old.begin(), E = Old.end();
+         I != E; ++I) {
+    NamedDecl *OldD = (*I)->getUnderlyingDecl();
+    if (FunctionTemplateDecl *OldT = dyn_cast<FunctionTemplateDecl>(OldD)) {
+      if (!IsOverload(New, OldT->getTemplatedDecl())) {
+        Match = *I;
+        return Ovl_Match;
+      }
+    } else if (FunctionDecl *OldF = dyn_cast<FunctionDecl>(OldD)) {
+      if (!IsOverload(New, OldF)) {
+        Match = *I;
+        return Ovl_Match;
+      }
+    } else if (isa<UsingDecl>(OldD) || isa<TagDecl>(OldD)) {
+      // We can overload with these, which can show up when doing
+      // redeclaration checks for UsingDecls.
+      assert(Old.getLookupKind() == LookupUsingDeclName);
+    } else if (isa<UnresolvedUsingValueDecl>(OldD)) {
+      // Optimistically assume that an unresolved using decl will
+      // overload; if it doesn't, we'll have to diagnose during
+      // template instantiation.
+    } else {
+      // (C++ 13p1):
+      //   Only function declarations can be overloaded; object and type
+      //   declarations cannot be overloaded.
+      Match = *I;
+      return Ovl_NonFunction;
+    }
+  }
+
+  return Ovl_Overload;
+}
+
+bool Sema::IsOverload(FunctionDecl *New, FunctionDecl *Old) {
+  FunctionTemplateDecl *OldTemplate = Old->getDescribedFunctionTemplate();
+  FunctionTemplateDecl *NewTemplate = New->getDescribedFunctionTemplate();
+
+  // C++ [temp.fct]p2:
+  //   A function template can be overloaded with other function templates
+  //   and with normal (non-template) functions.
+  if ((OldTemplate == 0) != (NewTemplate == 0))
+    return true;
+
+  // Is the function New an overload of the function Old?
+  QualType OldQType = Context.getCanonicalType(Old->getType());
+  QualType NewQType = Context.getCanonicalType(New->getType());
+
+  // Compare the signatures (C++ 1.3.10) of the two functions to
+  // determine whether they are overloads. If we find any mismatch
+  // in the signature, they are overloads.
+
+  // If either of these functions is a K&R-style function (no
+  // prototype), then we consider them to have matching signatures.
+  if (isa<FunctionNoProtoType>(OldQType.getTypePtr()) ||
+      isa<FunctionNoProtoType>(NewQType.getTypePtr()))
+    return false;
+
+  FunctionProtoType* OldType = cast<FunctionProtoType>(OldQType);
+  FunctionProtoType* NewType = cast<FunctionProtoType>(NewQType);
+
+  // The signature of a function includes the types of its
+  // parameters (C++ 1.3.10), which includes the presence or absence
+  // of the ellipsis; see C++ DR 357).
+  if (OldQType != NewQType &&
+      (OldType->getNumArgs() != NewType->getNumArgs() ||
+       OldType->isVariadic() != NewType->isVariadic() ||
+       !std::equal(OldType->arg_type_begin(), OldType->arg_type_end(),
+                   NewType->arg_type_begin())))
+    return true;
+
+  // C++ [temp.over.link]p4:
+  //   The signature of a function template consists of its function
+  //   signature, its return type and its template parameter list. The names
+  //   of the template parameters are significant only for establishing the
+  //   relationship between the template parameters and the rest of the
+  //   signature.
+  //
+  // We check the return type and template parameter lists for function
+  // templates first; the remaining checks follow.
+  if (NewTemplate &&
+      (!TemplateParameterListsAreEqual(NewTemplate->getTemplateParameters(),
+                                       OldTemplate->getTemplateParameters(),
+                                       false, TPL_TemplateMatch) ||
+       OldType->getResultType() != NewType->getResultType()))
+    return true;
+
+  // If the function is a class member, its signature includes the
+  // cv-qualifiers (if any) on the function itself.
+  //
+  // As part of this, also check whether one of the member functions
+  // is static, in which case they are not overloads (C++
+  // 13.1p2). While not part of the definition of the signature,
+  // this check is important to determine whether these functions
+  // can be overloaded.
+  CXXMethodDecl* OldMethod = dyn_cast<CXXMethodDecl>(Old);
+  CXXMethodDecl* NewMethod = dyn_cast<CXXMethodDecl>(New);
+  if (OldMethod && NewMethod &&
+      !OldMethod->isStatic() && !NewMethod->isStatic() &&
+      OldMethod->getTypeQualifiers() != NewMethod->getTypeQualifiers())
+    return true;
+  
+  // The signatures match; this is not an overload.
+  return false;
+}
+
+/// TryImplicitConversion - Attempt to perform an implicit conversion
+/// from the given expression (Expr) to the given type (ToType). This
+/// function returns an implicit conversion sequence that can be used
+/// to perform the initialization. Given
+///
+///   void f(float f);
+///   void g(int i) { f(i); }
+///
+/// this routine would produce an implicit conversion sequence to
+/// describe the initialization of f from i, which will be a standard
+/// conversion sequence containing an lvalue-to-rvalue conversion (C++
+/// 4.1) followed by a floating-integral conversion (C++ 4.9).
+//
+/// Note that this routine only determines how the conversion can be
+/// performed; it does not actually perform the conversion. As such,
+/// it will not produce any diagnostics if no conversion is available,
+/// but will instead return an implicit conversion sequence of kind
+/// "BadConversion".
+///
+/// If @p SuppressUserConversions, then user-defined conversions are
+/// not permitted.
+/// If @p AllowExplicit, then explicit user-defined conversions are
+/// permitted.
+/// If @p ForceRValue, then overloading is performed as if From was an rvalue,
+/// no matter its actual lvalueness.
+/// If @p UserCast, the implicit conversion is being done for a user-specified
+/// cast.
+ImplicitConversionSequence
+Sema::TryImplicitConversion(Expr* From, QualType ToType,
+                            bool SuppressUserConversions,
+                            bool AllowExplicit, bool ForceRValue,
+                            bool InOverloadResolution,
+                            bool UserCast) {
+  ImplicitConversionSequence ICS;
+  if (IsStandardConversion(From, ToType, InOverloadResolution, ICS.Standard)) {
+    ICS.setStandard();
+    return ICS;
+  }
+
+  if (!getLangOptions().CPlusPlus) {
+    ICS.setBad();
+    ICS.Bad.init(BadConversionSequence::no_conversion, From, ToType);
+    return ICS;
+  }
+
+  OverloadCandidateSet Conversions(From->getExprLoc());
+  OverloadingResult UserDefResult
+    = IsUserDefinedConversion(From, ToType, ICS.UserDefined, Conversions,
+                              !SuppressUserConversions, AllowExplicit,
+                              ForceRValue, UserCast);
+
+  if (UserDefResult == OR_Success) {
+    ICS.setUserDefined();
+    // C++ [over.ics.user]p4:
+    //   A conversion of an expression of class type to the same class
+    //   type is given Exact Match rank, and a conversion of an
+    //   expression of class type to a base class of that type is
+    //   given Conversion rank, in spite of the fact that a copy
+    //   constructor (i.e., a user-defined conversion function) is
+    //   called for those cases.
+    if (CXXConstructorDecl *Constructor
+          = dyn_cast<CXXConstructorDecl>(ICS.UserDefined.ConversionFunction)) {
+      QualType FromCanon
+        = Context.getCanonicalType(From->getType().getUnqualifiedType());
+      QualType ToCanon = Context.getCanonicalType(ToType).getUnqualifiedType();
+      if (Constructor->isCopyConstructor() &&
+          (FromCanon == ToCanon || IsDerivedFrom(FromCanon, ToCanon))) {
+        // Turn this into a "standard" conversion sequence, so that it
+        // gets ranked with standard conversion sequences.
+        ICS.setStandard();
+        ICS.Standard.setAsIdentityConversion();
+        ICS.Standard.setFromType(From->getType());
+        ICS.Standard.setAllToTypes(ToType);
+        ICS.Standard.CopyConstructor = Constructor;
+        if (ToCanon != FromCanon)
+          ICS.Standard.Second = ICK_Derived_To_Base;
+      }
+    }
+
+    // C++ [over.best.ics]p4:
+    //   However, when considering the argument of a user-defined
+    //   conversion function that is a candidate by 13.3.1.3 when
+    //   invoked for the copying of the temporary in the second step
+    //   of a class copy-initialization, or by 13.3.1.4, 13.3.1.5, or
+    //   13.3.1.6 in all cases, only standard conversion sequences and
+    //   ellipsis conversion sequences are allowed.
+    if (SuppressUserConversions && ICS.isUserDefined()) {
+      ICS.setBad();
+      ICS.Bad.init(BadConversionSequence::suppressed_user, From, ToType);
+    }
+  } else if (UserDefResult == OR_Ambiguous && !SuppressUserConversions) {
+    ICS.setAmbiguous();
+    ICS.Ambiguous.setFromType(From->getType());
+    ICS.Ambiguous.setToType(ToType);
+    for (OverloadCandidateSet::iterator Cand = Conversions.begin();
+         Cand != Conversions.end(); ++Cand)
+      if (Cand->Viable)
+        ICS.Ambiguous.addConversion(Cand->Function);
+  } else {
+    ICS.setBad();
+    ICS.Bad.init(BadConversionSequence::no_conversion, From, ToType);
+  }
+
+  return ICS;
+}
+
+/// \brief Determine whether the conversion from FromType to ToType is a valid 
+/// conversion that strips "noreturn" off the nested function type.
+static bool IsNoReturnConversion(ASTContext &Context, QualType FromType, 
+                                 QualType ToType, QualType &ResultTy) {
+  if (Context.hasSameUnqualifiedType(FromType, ToType))
+    return false;
+  
+  // Strip the noreturn off the type we're converting from; noreturn can
+  // safely be removed.
+  FromType = Context.getNoReturnType(FromType, false);
+  if (!Context.hasSameUnqualifiedType(FromType, ToType))
+    return false;
+
+  ResultTy = FromType;
+  return true;
+}
+  
+/// IsStandardConversion - Determines whether there is a standard
+/// conversion sequence (C++ [conv], C++ [over.ics.scs]) from the
+/// expression From to the type ToType. Standard conversion sequences
+/// only consider non-class types; for conversions that involve class
+/// types, use TryImplicitConversion. If a conversion exists, SCS will
+/// contain the standard conversion sequence required to perform this
+/// conversion and this routine will return true. Otherwise, this
+/// routine will return false and the value of SCS is unspecified.
+bool
+Sema::IsStandardConversion(Expr* From, QualType ToType,
+                           bool InOverloadResolution,
+                           StandardConversionSequence &SCS) {
+  QualType FromType = From->getType();
+
+  // Standard conversions (C++ [conv])
+  SCS.setAsIdentityConversion();
+  SCS.Deprecated = false;
+  SCS.IncompatibleObjC = false;
+  SCS.setFromType(FromType);
+  SCS.CopyConstructor = 0;
+
+  // There are no standard conversions for class types in C++, so
+  // abort early. When overloading in C, however, we do permit
+  if (FromType->isRecordType() || ToType->isRecordType()) {
+    if (getLangOptions().CPlusPlus)
+      return false;
+
+    // When we're overloading in C, we allow, as standard conversions,
+  }
+
+  // The first conversion can be an lvalue-to-rvalue conversion,
+  // array-to-pointer conversion, or function-to-pointer conversion
+  // (C++ 4p1).
+
+  // Lvalue-to-rvalue conversion (C++ 4.1):
+  //   An lvalue (3.10) of a non-function, non-array type T can be
+  //   converted to an rvalue.
+  Expr::isLvalueResult argIsLvalue = From->isLvalue(Context);
+  if (argIsLvalue == Expr::LV_Valid &&
+      !FromType->isFunctionType() && !FromType->isArrayType() &&
+      Context.getCanonicalType(FromType) != Context.OverloadTy) {
+    SCS.First = ICK_Lvalue_To_Rvalue;
+
+    // If T is a non-class type, the type of the rvalue is the
+    // cv-unqualified version of T. Otherwise, the type of the rvalue
+    // is T (C++ 4.1p1). C++ can't get here with class types; in C, we
+    // just strip the qualifiers because they don't matter.
+    FromType = FromType.getUnqualifiedType();
+  } else if (FromType->isArrayType()) {
+    // Array-to-pointer conversion (C++ 4.2)
+    SCS.First = ICK_Array_To_Pointer;
+
+    // An lvalue or rvalue of type "array of N T" or "array of unknown
+    // bound of T" can be converted to an rvalue of type "pointer to
+    // T" (C++ 4.2p1).
+    FromType = Context.getArrayDecayedType(FromType);
+
+    if (IsStringLiteralToNonConstPointerConversion(From, ToType)) {
+      // This conversion is deprecated. (C++ D.4).
+      SCS.Deprecated = true;
+
+      // For the purpose of ranking in overload resolution
+      // (13.3.3.1.1), this conversion is considered an
+      // array-to-pointer conversion followed by a qualification
+      // conversion (4.4). (C++ 4.2p2)
+      SCS.Second = ICK_Identity;
+      SCS.Third = ICK_Qualification;
+      SCS.setAllToTypes(FromType);
+      return true;
+    }
+  } else if (FromType->isFunctionType() && argIsLvalue == Expr::LV_Valid) {
+    // Function-to-pointer conversion (C++ 4.3).
+    SCS.First = ICK_Function_To_Pointer;
+
+    // An lvalue of function type T can be converted to an rvalue of
+    // type "pointer to T." The result is a pointer to the
+    // function. (C++ 4.3p1).
+    FromType = Context.getPointerType(FromType);
+  } else if (FunctionDecl *Fn
+               = ResolveAddressOfOverloadedFunction(From, ToType, false)) {
+    // Address of overloaded function (C++ [over.over]).
+    SCS.First = ICK_Function_To_Pointer;
+
+    // We were able to resolve the address of the overloaded function,
+    // so we can convert to the type of that function.
+    FromType = Fn->getType();
+    if (ToType->isLValueReferenceType())
+      FromType = Context.getLValueReferenceType(FromType);
+    else if (ToType->isRValueReferenceType())
+      FromType = Context.getRValueReferenceType(FromType);
+    else if (ToType->isMemberPointerType()) {
+      // Resolve address only succeeds if both sides are member pointers,
+      // but it doesn't have to be the same class. See DR 247.
+      // Note that this means that the type of &Derived::fn can be
+      // Ret (Base::*)(Args) if the fn overload actually found is from the
+      // base class, even if it was brought into the derived class via a
+      // using declaration. The standard isn't clear on this issue at all.
+      CXXMethodDecl *M = cast<CXXMethodDecl>(Fn);
+      FromType = Context.getMemberPointerType(FromType,
+                    Context.getTypeDeclType(M->getParent()).getTypePtr());
+    } else
+      FromType = Context.getPointerType(FromType);
+  } else {
+    // We don't require any conversions for the first step.
+    SCS.First = ICK_Identity;
+  }
+  SCS.setToType(0, FromType);
+
+  // The second conversion can be an integral promotion, floating
+  // point promotion, integral conversion, floating point conversion,
+  // floating-integral conversion, pointer conversion,
+  // pointer-to-member conversion, or boolean conversion (C++ 4p1).
+  // For overloading in C, this can also be a "compatible-type"
+  // conversion.
+  bool IncompatibleObjC = false;
+  if (Context.hasSameUnqualifiedType(FromType, ToType)) {
+    // The unqualified versions of the types are the same: there's no
+    // conversion to do.
+    SCS.Second = ICK_Identity;
+  } else if (IsIntegralPromotion(From, FromType, ToType)) {
+    // Integral promotion (C++ 4.5).
+    SCS.Second = ICK_Integral_Promotion;
+    FromType = ToType.getUnqualifiedType();
+  } else if (IsFloatingPointPromotion(FromType, ToType)) {
+    // Floating point promotion (C++ 4.6).
+    SCS.Second = ICK_Floating_Promotion;
+    FromType = ToType.getUnqualifiedType();
+  } else if (IsComplexPromotion(FromType, ToType)) {
+    // Complex promotion (Clang extension)
+    SCS.Second = ICK_Complex_Promotion;
+    FromType = ToType.getUnqualifiedType();
+  } else if ((FromType->isIntegralType() || FromType->isEnumeralType()) &&
+           (ToType->isIntegralType() && !ToType->isEnumeralType())) {
+    // Integral conversions (C++ 4.7).
+    SCS.Second = ICK_Integral_Conversion;
+    FromType = ToType.getUnqualifiedType();
+  } else if (FromType->isFloatingType() && ToType->isFloatingType()) {
+    // Floating point conversions (C++ 4.8).
+    SCS.Second = ICK_Floating_Conversion;
+    FromType = ToType.getUnqualifiedType();
+  } else if (FromType->isComplexType() && ToType->isComplexType()) {
+    // Complex conversions (C99 6.3.1.6)
+    SCS.Second = ICK_Complex_Conversion;
+    FromType = ToType.getUnqualifiedType();
+  } else if ((FromType->isFloatingType() &&
+              ToType->isIntegralType() && (!ToType->isBooleanType() &&
+                                           !ToType->isEnumeralType())) ||
+             ((FromType->isIntegralType() || FromType->isEnumeralType()) &&
+              ToType->isFloatingType())) {
+    // Floating-integral conversions (C++ 4.9).
+    SCS.Second = ICK_Floating_Integral;
+    FromType = ToType.getUnqualifiedType();
+  } else if ((FromType->isComplexType() && ToType->isArithmeticType()) ||
+             (ToType->isComplexType() && FromType->isArithmeticType())) {
+    // Complex-real conversions (C99 6.3.1.7)
+    SCS.Second = ICK_Complex_Real;
+    FromType = ToType.getUnqualifiedType();
+  } else if (IsPointerConversion(From, FromType, ToType, InOverloadResolution,
+                                 FromType, IncompatibleObjC)) {
+    // Pointer conversions (C++ 4.10).
+    SCS.Second = ICK_Pointer_Conversion;
+    SCS.IncompatibleObjC = IncompatibleObjC;
+  } else if (IsMemberPointerConversion(From, FromType, ToType, 
+                                       InOverloadResolution, FromType)) {
+    // Pointer to member conversions (4.11).
+    SCS.Second = ICK_Pointer_Member;
+  } else if (ToType->isBooleanType() &&
+             (FromType->isArithmeticType() ||
+              FromType->isEnumeralType() ||
+              FromType->isAnyPointerType() ||
+              FromType->isBlockPointerType() ||
+              FromType->isMemberPointerType() ||
+              FromType->isNullPtrType())) {
+    // Boolean conversions (C++ 4.12).
+    SCS.Second = ICK_Boolean_Conversion;
+    FromType = Context.BoolTy;
+  } else if (!getLangOptions().CPlusPlus &&
+             Context.typesAreCompatible(ToType, FromType)) {
+    // Compatible conversions (Clang extension for C function overloading)
+    SCS.Second = ICK_Compatible_Conversion;
+  } else if (IsNoReturnConversion(Context, FromType, ToType, FromType)) {
+    // Treat a conversion that strips "noreturn" as an identity conversion.
+    SCS.Second = ICK_NoReturn_Adjustment;
+  } else {
+    // No second conversion required.
+    SCS.Second = ICK_Identity;
+  }
+  SCS.setToType(1, FromType);
+
+  QualType CanonFrom;
+  QualType CanonTo;
+  // The third conversion can be a qualification conversion (C++ 4p1).
+  if (IsQualificationConversion(FromType, ToType)) {
+    SCS.Third = ICK_Qualification;
+    FromType = ToType;
+    CanonFrom = Context.getCanonicalType(FromType);
+    CanonTo = Context.getCanonicalType(ToType);
+  } else {
+    // No conversion required
+    SCS.Third = ICK_Identity;
+
+    // C++ [over.best.ics]p6:
+    //   [...] Any difference in top-level cv-qualification is
+    //   subsumed by the initialization itself and does not constitute
+    //   a conversion. [...]
+    CanonFrom = Context.getCanonicalType(FromType);
+    CanonTo = Context.getCanonicalType(ToType);
+    if (CanonFrom.getLocalUnqualifiedType() 
+                                       == CanonTo.getLocalUnqualifiedType() &&
+        CanonFrom.getLocalCVRQualifiers() != CanonTo.getLocalCVRQualifiers()) {
+      FromType = ToType;
+      CanonFrom = CanonTo;
+    }
+  }
+  SCS.setToType(2, FromType);
+
+  // If we have not converted the argument type to the parameter type,
+  // this is a bad conversion sequence.
+  if (CanonFrom != CanonTo)
+    return false;
+
+  return true;
+}
+
+/// IsIntegralPromotion - Determines whether the conversion from the
+/// expression From (whose potentially-adjusted type is FromType) to
+/// ToType is an integral promotion (C++ 4.5). If so, returns true and
+/// sets PromotedType to the promoted type.
+bool Sema::IsIntegralPromotion(Expr *From, QualType FromType, QualType ToType) {
+  const BuiltinType *To = ToType->getAs<BuiltinType>();
+  // All integers are built-in.
+  if (!To) {
+    return false;
+  }
+
+  // An rvalue of type char, signed char, unsigned char, short int, or
+  // unsigned short int can be converted to an rvalue of type int if
+  // int can represent all the values of the source type; otherwise,
+  // the source rvalue can be converted to an rvalue of type unsigned
+  // int (C++ 4.5p1).
+  if (FromType->isPromotableIntegerType() && !FromType->isBooleanType() &&
+      !FromType->isEnumeralType()) {
+    if (// We can promote any signed, promotable integer type to an int
+        (FromType->isSignedIntegerType() ||
+         // We can promote any unsigned integer type whose size is
+         // less than int to an int.
+         (!FromType->isSignedIntegerType() &&
+          Context.getTypeSize(FromType) < Context.getTypeSize(ToType)))) {
+      return To->getKind() == BuiltinType::Int;
+    }
+
+    return To->getKind() == BuiltinType::UInt;
+  }
+
+  // An rvalue of type wchar_t (3.9.1) or an enumeration type (7.2)
+  // can be converted to an rvalue of the first of the following types
+  // that can represent all the values of its underlying type: int,
+  // unsigned int, long, or unsigned long (C++ 4.5p2).
+
+  // We pre-calculate the promotion type for enum types.
+  if (const EnumType *FromEnumType = FromType->getAs<EnumType>())
+    if (ToType->isIntegerType())
+      return Context.hasSameUnqualifiedType(ToType,
+                                FromEnumType->getDecl()->getPromotionType());
+
+  if (FromType->isWideCharType() && ToType->isIntegerType()) {
+    // Determine whether the type we're converting from is signed or
+    // unsigned.
+    bool FromIsSigned;
+    uint64_t FromSize = Context.getTypeSize(FromType);
+    
+    // FIXME: Is wchar_t signed or unsigned? We assume it's signed for now.
+    FromIsSigned = true;
+
+    // The types we'll try to promote to, in the appropriate
+    // order. Try each of these types.
+    QualType PromoteTypes[6] = {
+      Context.IntTy, Context.UnsignedIntTy,
+      Context.LongTy, Context.UnsignedLongTy ,
+      Context.LongLongTy, Context.UnsignedLongLongTy
+    };
+    for (int Idx = 0; Idx < 6; ++Idx) {
+      uint64_t ToSize = Context.getTypeSize(PromoteTypes[Idx]);
+      if (FromSize < ToSize ||
+          (FromSize == ToSize &&
+           FromIsSigned == PromoteTypes[Idx]->isSignedIntegerType())) {
+        // We found the type that we can promote to. If this is the
+        // type we wanted, we have a promotion. Otherwise, no
+        // promotion.
+        return Context.hasSameUnqualifiedType(ToType, PromoteTypes[Idx]);
+      }
+    }
+  }
+
+  // An rvalue for an integral bit-field (9.6) can be converted to an
+  // rvalue of type int if int can represent all the values of the
+  // bit-field; otherwise, it can be converted to unsigned int if
+  // unsigned int can represent all the values of the bit-field. If
+  // the bit-field is larger yet, no integral promotion applies to
+  // it. If the bit-field has an enumerated type, it is treated as any
+  // other value of that type for promotion purposes (C++ 4.5p3).
+  // FIXME: We should delay checking of bit-fields until we actually perform the
+  // conversion.
+  using llvm::APSInt;
+  if (From)
+    if (FieldDecl *MemberDecl = From->getBitField()) {
+      APSInt BitWidth;
+      if (FromType->isIntegralType() && !FromType->isEnumeralType() &&
+          MemberDecl->getBitWidth()->isIntegerConstantExpr(BitWidth, Context)) {
+        APSInt ToSize(BitWidth.getBitWidth(), BitWidth.isUnsigned());
+        ToSize = Context.getTypeSize(ToType);
+
+        // Are we promoting to an int from a bitfield that fits in an int?
+        if (BitWidth < ToSize ||
+            (FromType->isSignedIntegerType() && BitWidth <= ToSize)) {
+          return To->getKind() == BuiltinType::Int;
+        }
+
+        // Are we promoting to an unsigned int from an unsigned bitfield
+        // that fits into an unsigned int?
+        if (FromType->isUnsignedIntegerType() && BitWidth <= ToSize) {
+          return To->getKind() == BuiltinType::UInt;
+        }
+
+        return false;
+      }
+    }
+
+  // An rvalue of type bool can be converted to an rvalue of type int,
+  // with false becoming zero and true becoming one (C++ 4.5p4).
+  if (FromType->isBooleanType() && To->getKind() == BuiltinType::Int) {
+    return true;
+  }
+
+  return false;
+}
+
+/// IsFloatingPointPromotion - Determines whether the conversion from
+/// FromType to ToType is a floating point promotion (C++ 4.6). If so,
+/// returns true and sets PromotedType to the promoted type.
+bool Sema::IsFloatingPointPromotion(QualType FromType, QualType ToType) {
+  /// An rvalue of type float can be converted to an rvalue of type
+  /// double. (C++ 4.6p1).
+  if (const BuiltinType *FromBuiltin = FromType->getAs<BuiltinType>())
+    if (const BuiltinType *ToBuiltin = ToType->getAs<BuiltinType>()) {
+      if (FromBuiltin->getKind() == BuiltinType::Float &&
+          ToBuiltin->getKind() == BuiltinType::Double)
+        return true;
+
+      // C99 6.3.1.5p1:
+      //   When a float is promoted to double or long double, or a
+      //   double is promoted to long double [...].
+      if (!getLangOptions().CPlusPlus &&
+          (FromBuiltin->getKind() == BuiltinType::Float ||
+           FromBuiltin->getKind() == BuiltinType::Double) &&
+          (ToBuiltin->getKind() == BuiltinType::LongDouble))
+        return true;
+    }
+
+  return false;
+}
+
+/// \brief Determine if a conversion is a complex promotion.
+///
+/// A complex promotion is defined as a complex -> complex conversion
+/// where the conversion between the underlying real types is a
+/// floating-point or integral promotion.
+bool Sema::IsComplexPromotion(QualType FromType, QualType ToType) {
+  const ComplexType *FromComplex = FromType->getAs<ComplexType>();
+  if (!FromComplex)
+    return false;
+
+  const ComplexType *ToComplex = ToType->getAs<ComplexType>();
+  if (!ToComplex)
+    return false;
+
+  return IsFloatingPointPromotion(FromComplex->getElementType(),
+                                  ToComplex->getElementType()) ||
+    IsIntegralPromotion(0, FromComplex->getElementType(),
+                        ToComplex->getElementType());
+}
+
+/// BuildSimilarlyQualifiedPointerType - In a pointer conversion from
+/// the pointer type FromPtr to a pointer to type ToPointee, with the
+/// same type qualifiers as FromPtr has on its pointee type. ToType,
+/// if non-empty, will be a pointer to ToType that may or may not have
+/// the right set of qualifiers on its pointee.
+static QualType
+BuildSimilarlyQualifiedPointerType(const PointerType *FromPtr,
+                                   QualType ToPointee, QualType ToType,
+                                   ASTContext &Context) {
+  QualType CanonFromPointee = Context.getCanonicalType(FromPtr->getPointeeType());
+  QualType CanonToPointee = Context.getCanonicalType(ToPointee);
+  Qualifiers Quals = CanonFromPointee.getQualifiers();
+
+  // Exact qualifier match -> return the pointer type we're converting to.
+  if (CanonToPointee.getLocalQualifiers() == Quals) {
+    // ToType is exactly what we need. Return it.
+    if (!ToType.isNull())
+      return ToType;
+
+    // Build a pointer to ToPointee. It has the right qualifiers
+    // already.
+    return Context.getPointerType(ToPointee);
+  }
+
+  // Just build a canonical type that has the right qualifiers.
+  return Context.getPointerType(
+         Context.getQualifiedType(CanonToPointee.getLocalUnqualifiedType(), 
+                                  Quals));
+}
+
+/// BuildSimilarlyQualifiedObjCObjectPointerType - In a pointer conversion from
+/// the FromType, which is an objective-c pointer, to ToType, which may or may
+/// not have the right set of qualifiers.
+static QualType
+BuildSimilarlyQualifiedObjCObjectPointerType(QualType FromType,
+                                             QualType ToType,
+                                             ASTContext &Context) {
+  QualType CanonFromType = Context.getCanonicalType(FromType);
+  QualType CanonToType = Context.getCanonicalType(ToType);
+  Qualifiers Quals = CanonFromType.getQualifiers();
+    
+  // Exact qualifier match -> return the pointer type we're converting to.
+  if (CanonToType.getLocalQualifiers() == Quals)
+    return ToType;
+  
+  // Just build a canonical type that has the right qualifiers.
+  return Context.getQualifiedType(CanonToType.getLocalUnqualifiedType(), Quals);
+}
+  
+static bool isNullPointerConstantForConversion(Expr *Expr,
+                                               bool InOverloadResolution,
+                                               ASTContext &Context) {
+  // Handle value-dependent integral null pointer constants correctly.
+  // http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#903
+  if (Expr->isValueDependent() && !Expr->isTypeDependent() &&
+      Expr->getType()->isIntegralType())
+    return !InOverloadResolution;
+
+  return Expr->isNullPointerConstant(Context,
+                    InOverloadResolution? Expr::NPC_ValueDependentIsNotNull
+                                        : Expr::NPC_ValueDependentIsNull);
+}
+
+/// IsPointerConversion - Determines whether the conversion of the
+/// expression From, which has the (possibly adjusted) type FromType,
+/// can be converted to the type ToType via a pointer conversion (C++
+/// 4.10). If so, returns true and places the converted type (that
+/// might differ from ToType in its cv-qualifiers at some level) into
+/// ConvertedType.
+///
+/// This routine also supports conversions to and from block pointers
+/// and conversions with Objective-C's 'id', 'id<protocols...>', and
+/// pointers to interfaces. FIXME: Once we've determined the
+/// appropriate overloading rules for Objective-C, we may want to
+/// split the Objective-C checks into a different routine; however,
+/// GCC seems to consider all of these conversions to be pointer
+/// conversions, so for now they live here. IncompatibleObjC will be
+/// set if the conversion is an allowed Objective-C conversion that
+/// should result in a warning.
+bool Sema::IsPointerConversion(Expr *From, QualType FromType, QualType ToType,
+                               bool InOverloadResolution,
+                               QualType& ConvertedType,
+                               bool &IncompatibleObjC) {
+  IncompatibleObjC = false;
+  if (isObjCPointerConversion(FromType, ToType, ConvertedType, IncompatibleObjC))
+    return true;
+
+  // Conversion from a null pointer constant to any Objective-C pointer type.
+  if (ToType->isObjCObjectPointerType() &&
+      isNullPointerConstantForConversion(From, InOverloadResolution, Context)) {
+    ConvertedType = ToType;
+    return true;
+  }
+
+  // Blocks: Block pointers can be converted to void*.
+  if (FromType->isBlockPointerType() && ToType->isPointerType() &&
+      ToType->getAs<PointerType>()->getPointeeType()->isVoidType()) {
+    ConvertedType = ToType;
+    return true;
+  }
+  // Blocks: A null pointer constant can be converted to a block
+  // pointer type.
+  if (ToType->isBlockPointerType() &&
+      isNullPointerConstantForConversion(From, InOverloadResolution, Context)) {
+    ConvertedType = ToType;
+    return true;
+  }
+
+  // If the left-hand-side is nullptr_t, the right side can be a null
+  // pointer constant.
+  if (ToType->isNullPtrType() &&
+      isNullPointerConstantForConversion(From, InOverloadResolution, Context)) {
+    ConvertedType = ToType;
+    return true;
+  }
+
+  const PointerType* ToTypePtr = ToType->getAs<PointerType>();
+  if (!ToTypePtr)
+    return false;
+
+  // A null pointer constant can be converted to a pointer type (C++ 4.10p1).
+  if (isNullPointerConstantForConversion(From, InOverloadResolution, Context)) {
+    ConvertedType = ToType;
+    return true;
+  }
+
+  // Beyond this point, both types need to be pointers 
+  // , including objective-c pointers.
+  QualType ToPointeeType = ToTypePtr->getPointeeType();
+  if (FromType->isObjCObjectPointerType() && ToPointeeType->isVoidType()) {
+    ConvertedType = BuildSimilarlyQualifiedObjCObjectPointerType(FromType,
+                                                       ToType, Context);
+    return true;
+    
+  }
+  const PointerType *FromTypePtr = FromType->getAs<PointerType>();
+  if (!FromTypePtr)
+    return false;
+
+  QualType FromPointeeType = FromTypePtr->getPointeeType();
+
+  // An rvalue of type "pointer to cv T," where T is an object type,
+  // can be converted to an rvalue of type "pointer to cv void" (C++
+  // 4.10p2).
+  if (FromPointeeType->isObjectType() && ToPointeeType->isVoidType()) {
+    ConvertedType = BuildSimilarlyQualifiedPointerType(FromTypePtr,
+                                                       ToPointeeType,
+                                                       ToType, Context);
+    return true;
+  }
+
+  // When we're overloading in C, we allow a special kind of pointer
+  // conversion for compatible-but-not-identical pointee types.
+  if (!getLangOptions().CPlusPlus &&
+      Context.typesAreCompatible(FromPointeeType, ToPointeeType)) {
+    ConvertedType = BuildSimilarlyQualifiedPointerType(FromTypePtr,
+                                                       ToPointeeType,
+                                                       ToType, Context);
+    return true;
+  }
+
+  // C++ [conv.ptr]p3:
+  //
+  //   An rvalue of type "pointer to cv D," where D is a class type,
+  //   can be converted to an rvalue of type "pointer to cv B," where
+  //   B is a base class (clause 10) of D. If B is an inaccessible
+  //   (clause 11) or ambiguous (10.2) base class of D, a program that
+  //   necessitates this conversion is ill-formed. The result of the
+  //   conversion is a pointer to the base class sub-object of the
+  //   derived class object. The null pointer value is converted to
+  //   the null pointer value of the destination type.
+  //
+  // Note that we do not check for ambiguity or inaccessibility
+  // here. That is handled by CheckPointerConversion.
+  if (getLangOptions().CPlusPlus &&
+      FromPointeeType->isRecordType() && ToPointeeType->isRecordType() &&
+      !RequireCompleteType(From->getLocStart(), FromPointeeType, PDiag()) &&
+      IsDerivedFrom(FromPointeeType, ToPointeeType)) {
+    ConvertedType = BuildSimilarlyQualifiedPointerType(FromTypePtr,
+                                                       ToPointeeType,
+                                                       ToType, Context);
+    return true;
+  }
+
+  return false;
+}
+
+/// isObjCPointerConversion - Determines whether this is an
+/// Objective-C pointer conversion. Subroutine of IsPointerConversion,
+/// with the same arguments and return values.
+bool Sema::isObjCPointerConversion(QualType FromType, QualType ToType,
+                                   QualType& ConvertedType,
+                                   bool &IncompatibleObjC) {
+  if (!getLangOptions().ObjC1)
+    return false;
+ 
+  // First, we handle all conversions on ObjC object pointer types.
+  const ObjCObjectPointerType* ToObjCPtr = ToType->getAs<ObjCObjectPointerType>();
+  const ObjCObjectPointerType *FromObjCPtr =
+    FromType->getAs<ObjCObjectPointerType>();
+
+  if (ToObjCPtr && FromObjCPtr) {
+    // Objective C++: We're able to convert between "id" or "Class" and a
+    // pointer to any interface (in both directions).
+    if (ToObjCPtr->isObjCBuiltinType() && FromObjCPtr->isObjCBuiltinType()) {
+      ConvertedType = ToType;
+      return true;
+    }
+    // Conversions with Objective-C's id<...>.
+    if ((FromObjCPtr->isObjCQualifiedIdType() ||
+         ToObjCPtr->isObjCQualifiedIdType()) &&
+        Context.ObjCQualifiedIdTypesAreCompatible(ToType, FromType,
+                                                  /*compare=*/false)) {
+      ConvertedType = ToType;
+      return true;
+    }
+    // Objective C++: We're able to convert from a pointer to an
+    // interface to a pointer to a different interface.
+    if (Context.canAssignObjCInterfaces(ToObjCPtr, FromObjCPtr)) {
+      ConvertedType = ToType;
+      return true;
+    }
+
+    if (Context.canAssignObjCInterfaces(FromObjCPtr, ToObjCPtr)) {
+      // Okay: this is some kind of implicit downcast of Objective-C
+      // interfaces, which is permitted. However, we're going to
+      // complain about it.
+      IncompatibleObjC = true;
+      ConvertedType = FromType;
+      return true;
+    }
+  }
+  // Beyond this point, both types need to be C pointers or block pointers.
+  QualType ToPointeeType;
+  if (const PointerType *ToCPtr = ToType->getAs<PointerType>())
+    ToPointeeType = ToCPtr->getPointeeType();
+  else if (const BlockPointerType *ToBlockPtr = 
+            ToType->getAs<BlockPointerType>()) {
+    // Objective C++: We're able to convert from a pointer to any object
+    // to a block pointer type.
+    if (FromObjCPtr && FromObjCPtr->isObjCBuiltinType()) {
+      ConvertedType = ToType;
+      return true;
+    }
+    ToPointeeType = ToBlockPtr->getPointeeType();
+  }
+  else if (FromType->getAs<BlockPointerType>() && 
+           ToObjCPtr && ToObjCPtr->isObjCBuiltinType()) {
+    // Objective C++: We're able to convert from a block pointer type to a 
+    // pointer to any object.
+    ConvertedType = ToType;
+    return true;
+  }
+  else
+    return false;
+
+  QualType FromPointeeType;
+  if (const PointerType *FromCPtr = FromType->getAs<PointerType>())
+    FromPointeeType = FromCPtr->getPointeeType();
+  else if (const BlockPointerType *FromBlockPtr = FromType->getAs<BlockPointerType>())
+    FromPointeeType = FromBlockPtr->getPointeeType();
+  else
+    return false;
+
+  // If we have pointers to pointers, recursively check whether this
+  // is an Objective-C conversion.
+  if (FromPointeeType->isPointerType() && ToPointeeType->isPointerType() &&
+      isObjCPointerConversion(FromPointeeType, ToPointeeType, ConvertedType,
+                              IncompatibleObjC)) {
+    // We always complain about this conversion.
+    IncompatibleObjC = true;
+    ConvertedType = ToType;
+    return true;
+  }
+  // Allow conversion of pointee being objective-c pointer to another one;
+  // as in I* to id.
+  if (FromPointeeType->getAs<ObjCObjectPointerType>() &&
+      ToPointeeType->getAs<ObjCObjectPointerType>() &&
+      isObjCPointerConversion(FromPointeeType, ToPointeeType, ConvertedType,
+                              IncompatibleObjC)) {
+    ConvertedType = ToType;
+    return true;
+  }
+  
+  // If we have pointers to functions or blocks, check whether the only
+  // differences in the argument and result types are in Objective-C
+  // pointer conversions. If so, we permit the conversion (but
+  // complain about it).
+  const FunctionProtoType *FromFunctionType
+    = FromPointeeType->getAs<FunctionProtoType>();
+  const FunctionProtoType *ToFunctionType
+    = ToPointeeType->getAs<FunctionProtoType>();
+  if (FromFunctionType && ToFunctionType) {
+    // If the function types are exactly the same, this isn't an
+    // Objective-C pointer conversion.
+    if (Context.getCanonicalType(FromPointeeType)
+          == Context.getCanonicalType(ToPointeeType))
+      return false;
+
+    // Perform the quick checks that will tell us whether these
+    // function types are obviously different.
+    if (FromFunctionType->getNumArgs() != ToFunctionType->getNumArgs() ||
+        FromFunctionType->isVariadic() != ToFunctionType->isVariadic() ||
+        FromFunctionType->getTypeQuals() != ToFunctionType->getTypeQuals())
+      return false;
+
+    bool HasObjCConversion = false;
+    if (Context.getCanonicalType(FromFunctionType->getResultType())
+          == Context.getCanonicalType(ToFunctionType->getResultType())) {
+      // Okay, the types match exactly. Nothing to do.
+    } else if (isObjCPointerConversion(FromFunctionType->getResultType(),
+                                       ToFunctionType->getResultType(),
+                                       ConvertedType, IncompatibleObjC)) {
+      // Okay, we have an Objective-C pointer conversion.
+      HasObjCConversion = true;
+    } else {
+      // Function types are too different. Abort.
+      return false;
+    }
+
+    // Check argument types.
+    for (unsigned ArgIdx = 0, NumArgs = FromFunctionType->getNumArgs();
+         ArgIdx != NumArgs; ++ArgIdx) {
+      QualType FromArgType = FromFunctionType->getArgType(ArgIdx);
+      QualType ToArgType = ToFunctionType->getArgType(ArgIdx);
+      if (Context.getCanonicalType(FromArgType)
+            == Context.getCanonicalType(ToArgType)) {
+        // Okay, the types match exactly. Nothing to do.
+      } else if (isObjCPointerConversion(FromArgType, ToArgType,
+                                         ConvertedType, IncompatibleObjC)) {
+        // Okay, we have an Objective-C pointer conversion.
+        HasObjCConversion = true;
+      } else {
+        // Argument types are too different. Abort.
+        return false;
+      }
+    }
+
+    if (HasObjCConversion) {
+      // We had an Objective-C conversion. Allow this pointer
+      // conversion, but complain about it.
+      ConvertedType = ToType;
+      IncompatibleObjC = true;
+      return true;
+    }
+  }
+
+  return false;
+}
+
+/// CheckPointerConversion - Check the pointer conversion from the
+/// expression From to the type ToType. This routine checks for
+/// ambiguous or inaccessible derived-to-base pointer
+/// conversions for which IsPointerConversion has already returned
+/// true. It returns true and produces a diagnostic if there was an
+/// error, or returns false otherwise.
+bool Sema::CheckPointerConversion(Expr *From, QualType ToType,
+                                  CastExpr::CastKind &Kind,
+                                  bool IgnoreBaseAccess) {
+  QualType FromType = From->getType();
+
+  if (const PointerType *FromPtrType = FromType->getAs<PointerType>())
+    if (const PointerType *ToPtrType = ToType->getAs<PointerType>()) {
+      QualType FromPointeeType = FromPtrType->getPointeeType(),
+               ToPointeeType   = ToPtrType->getPointeeType();
+
+      if (FromPointeeType->isRecordType() &&
+          ToPointeeType->isRecordType()) {
+        // We must have a derived-to-base conversion. Check an
+        // ambiguous or inaccessible conversion.
+        if (CheckDerivedToBaseConversion(FromPointeeType, ToPointeeType,
+                                         From->getExprLoc(),
+                                         From->getSourceRange(),
+                                         IgnoreBaseAccess))
+          return true;
+        
+        // The conversion was successful.
+        Kind = CastExpr::CK_DerivedToBase;
+      }
+    }
+  if (const ObjCObjectPointerType *FromPtrType =
+        FromType->getAs<ObjCObjectPointerType>())
+    if (const ObjCObjectPointerType *ToPtrType =
+          ToType->getAs<ObjCObjectPointerType>()) {
+      // Objective-C++ conversions are always okay.
+      // FIXME: We should have a different class of conversions for the
+      // Objective-C++ implicit conversions.
+      if (FromPtrType->isObjCBuiltinType() || ToPtrType->isObjCBuiltinType())
+        return false;
+
+  }
+  return false;
+}
+
+/// IsMemberPointerConversion - Determines whether the conversion of the
+/// expression From, which has the (possibly adjusted) type FromType, can be
+/// converted to the type ToType via a member pointer conversion (C++ 4.11).
+/// If so, returns true and places the converted type (that might differ from
+/// ToType in its cv-qualifiers at some level) into ConvertedType.
+bool Sema::IsMemberPointerConversion(Expr *From, QualType FromType,
+                                     QualType ToType, 
+                                     bool InOverloadResolution,
+                                     QualType &ConvertedType) {
+  const MemberPointerType *ToTypePtr = ToType->getAs<MemberPointerType>();
+  if (!ToTypePtr)
+    return false;
+
+  // A null pointer constant can be converted to a member pointer (C++ 4.11p1)
+  if (From->isNullPointerConstant(Context,
+                    InOverloadResolution? Expr::NPC_ValueDependentIsNotNull
+                                        : Expr::NPC_ValueDependentIsNull)) {
+    ConvertedType = ToType;
+    return true;
+  }
+
+  // Otherwise, both types have to be member pointers.
+  const MemberPointerType *FromTypePtr = FromType->getAs<MemberPointerType>();
+  if (!FromTypePtr)
+    return false;
+
+  // A pointer to member of B can be converted to a pointer to member of D,
+  // where D is derived from B (C++ 4.11p2).
+  QualType FromClass(FromTypePtr->getClass(), 0);
+  QualType ToClass(ToTypePtr->getClass(), 0);
+  // FIXME: What happens when these are dependent? Is this function even called?
+
+  if (IsDerivedFrom(ToClass, FromClass)) {
+    ConvertedType = Context.getMemberPointerType(FromTypePtr->getPointeeType(),
+                                                 ToClass.getTypePtr());
+    return true;
+  }
+
+  return false;
+}
+  
+/// CheckMemberPointerConversion - Check the member pointer conversion from the
+/// expression From to the type ToType. This routine checks for ambiguous or
+/// virtual or inaccessible base-to-derived member pointer conversions
+/// for which IsMemberPointerConversion has already returned true. It returns
+/// true and produces a diagnostic if there was an error, or returns false
+/// otherwise.
+bool Sema::CheckMemberPointerConversion(Expr *From, QualType ToType,
+                                        CastExpr::CastKind &Kind,
+                                        bool IgnoreBaseAccess) {
+  QualType FromType = From->getType();
+  const MemberPointerType *FromPtrType = FromType->getAs<MemberPointerType>();
+  if (!FromPtrType) {
+    // This must be a null pointer to member pointer conversion
+    assert(From->isNullPointerConstant(Context, 
+                                       Expr::NPC_ValueDependentIsNull) &&
+           "Expr must be null pointer constant!");
+    Kind = CastExpr::CK_NullToMemberPointer;
+    return false;
+  }
+
+  const MemberPointerType *ToPtrType = ToType->getAs<MemberPointerType>();
+  assert(ToPtrType && "No member pointer cast has a target type "
+                      "that is not a member pointer.");
+
+  QualType FromClass = QualType(FromPtrType->getClass(), 0);
+  QualType ToClass   = QualType(ToPtrType->getClass(), 0);
+
+  // FIXME: What about dependent types?
+  assert(FromClass->isRecordType() && "Pointer into non-class.");
+  assert(ToClass->isRecordType() && "Pointer into non-class.");
+
+  CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/ true,
+                     /*DetectVirtual=*/true);
+  bool DerivationOkay = IsDerivedFrom(ToClass, FromClass, Paths);
+  assert(DerivationOkay &&
+         "Should not have been called if derivation isn't OK.");
+  (void)DerivationOkay;
+
+  if (Paths.isAmbiguous(Context.getCanonicalType(FromClass).
+                                  getUnqualifiedType())) {
+    std::string PathDisplayStr = getAmbiguousPathsDisplayString(Paths);
+    Diag(From->getExprLoc(), diag::err_ambiguous_memptr_conv)
+      << 0 << FromClass << ToClass << PathDisplayStr << From->getSourceRange();
+    return true;
+  }
+
+  if (const RecordType *VBase = Paths.getDetectedVirtual()) {
+    Diag(From->getExprLoc(), diag::err_memptr_conv_via_virtual)
+      << FromClass << ToClass << QualType(VBase, 0)
+      << From->getSourceRange();
+    return true;
+  }
+
+  if (!IgnoreBaseAccess)
+    CheckBaseClassAccess(From->getExprLoc(), /*BaseToDerived*/ true,
+                         FromClass, ToClass, Paths.front());
+
+  // Must be a base to derived member conversion.
+  Kind = CastExpr::CK_BaseToDerivedMemberPointer;
+  return false;
+}
+
+/// IsQualificationConversion - Determines whether the conversion from
+/// an rvalue of type FromType to ToType is a qualification conversion
+/// (C++ 4.4).
+bool
+Sema::IsQualificationConversion(QualType FromType, QualType ToType) {
+  FromType = Context.getCanonicalType(FromType);
+  ToType = Context.getCanonicalType(ToType);
+
+  // If FromType and ToType are the same type, this is not a
+  // qualification conversion.
+  if (FromType.getUnqualifiedType() == ToType.getUnqualifiedType())
+    return false;
+
+  // (C++ 4.4p4):
+  //   A conversion can add cv-qualifiers at levels other than the first
+  //   in multi-level pointers, subject to the following rules: [...]
+  bool PreviousToQualsIncludeConst = true;
+  bool UnwrappedAnyPointer = false;
+  while (UnwrapSimilarPointerTypes(FromType, ToType)) {
+    // Within each iteration of the loop, we check the qualifiers to
+    // determine if this still looks like a qualification
+    // conversion. Then, if all is well, we unwrap one more level of
+    // pointers or pointers-to-members and do it all again
+    // until there are no more pointers or pointers-to-members left to
+    // unwrap.
+    UnwrappedAnyPointer = true;
+
+    //   -- for every j > 0, if const is in cv 1,j then const is in cv
+    //      2,j, and similarly for volatile.
+    if (!ToType.isAtLeastAsQualifiedAs(FromType))
+      return false;
+
+    //   -- if the cv 1,j and cv 2,j are different, then const is in
+    //      every cv for 0 < k < j.
+    if (FromType.getCVRQualifiers() != ToType.getCVRQualifiers()
+        && !PreviousToQualsIncludeConst)
+      return false;
+
+    // Keep track of whether all prior cv-qualifiers in the "to" type
+    // include const.
+    PreviousToQualsIncludeConst
+      = PreviousToQualsIncludeConst && ToType.isConstQualified();
+  }
+
+  // We are left with FromType and ToType being the pointee types
+  // after unwrapping the original FromType and ToType the same number
+  // of types. If we unwrapped any pointers, and if FromType and
+  // ToType have the same unqualified type (since we checked
+  // qualifiers above), then this is a qualification conversion.
+  return UnwrappedAnyPointer && Context.hasSameUnqualifiedType(FromType,ToType);
+}
+
+/// Determines whether there is a user-defined conversion sequence
+/// (C++ [over.ics.user]) that converts expression From to the type
+/// ToType. If such a conversion exists, User will contain the
+/// user-defined conversion sequence that performs such a conversion
+/// and this routine will return true. Otherwise, this routine returns
+/// false and User is unspecified.
+///
+/// \param AllowConversionFunctions true if the conversion should
+/// consider conversion functions at all. If false, only constructors
+/// will be considered.
+///
+/// \param AllowExplicit  true if the conversion should consider C++0x
+/// "explicit" conversion functions as well as non-explicit conversion
+/// functions (C++0x [class.conv.fct]p2).
+///
+/// \param ForceRValue  true if the expression should be treated as an rvalue
+/// for overload resolution.
+/// \param UserCast true if looking for user defined conversion for a static
+/// cast.
+OverloadingResult Sema::IsUserDefinedConversion(Expr *From, QualType ToType,
+                                          UserDefinedConversionSequence& User,
+                                            OverloadCandidateSet& CandidateSet,
+                                                bool AllowConversionFunctions,
+                                                bool AllowExplicit, 
+                                                bool ForceRValue,
+                                                bool UserCast) {
+  if (const RecordType *ToRecordType = ToType->getAs<RecordType>()) {
+    if (RequireCompleteType(From->getLocStart(), ToType, PDiag())) {
+      // We're not going to find any constructors.
+    } else if (CXXRecordDecl *ToRecordDecl
+                 = dyn_cast<CXXRecordDecl>(ToRecordType->getDecl())) {
+      // C++ [over.match.ctor]p1:
+      //   When objects of class type are direct-initialized (8.5), or
+      //   copy-initialized from an expression of the same or a
+      //   derived class type (8.5), overload resolution selects the
+      //   constructor. [...] For copy-initialization, the candidate
+      //   functions are all the converting constructors (12.3.1) of
+      //   that class. The argument list is the expression-list within
+      //   the parentheses of the initializer.
+      bool SuppressUserConversions = !UserCast;
+      if (Context.hasSameUnqualifiedType(ToType, From->getType()) ||
+          IsDerivedFrom(From->getType(), ToType)) {
+        SuppressUserConversions = false;
+        AllowConversionFunctions = false;
+      }
+          
+      DeclarationName ConstructorName
+        = Context.DeclarationNames.getCXXConstructorName(
+                          Context.getCanonicalType(ToType).getUnqualifiedType());
+      DeclContext::lookup_iterator Con, ConEnd;
+      for (llvm::tie(Con, ConEnd)
+             = ToRecordDecl->lookup(ConstructorName);
+           Con != ConEnd; ++Con) {
+        // Find the constructor (which may be a template).
+        CXXConstructorDecl *Constructor = 0;
+        FunctionTemplateDecl *ConstructorTmpl
+          = dyn_cast<FunctionTemplateDecl>(*Con);
+        if (ConstructorTmpl)
+          Constructor
+            = cast<CXXConstructorDecl>(ConstructorTmpl->getTemplatedDecl());
+        else
+          Constructor = cast<CXXConstructorDecl>(*Con);
+        
+        if (!Constructor->isInvalidDecl() &&
+            Constructor->isConvertingConstructor(AllowExplicit)) {
+          if (ConstructorTmpl)
+            AddTemplateOverloadCandidate(ConstructorTmpl,
+                                         ConstructorTmpl->getAccess(),
+                                         /*ExplicitArgs*/ 0,
+                                         &From, 1, CandidateSet, 
+                                         SuppressUserConversions, ForceRValue);
+          else
+            // Allow one user-defined conversion when user specifies a
+            // From->ToType conversion via an static cast (c-style, etc).
+            AddOverloadCandidate(Constructor, Constructor->getAccess(),
+                                 &From, 1, CandidateSet,
+                                 SuppressUserConversions, ForceRValue);
+        }
+      }
+    }
+  }
+
+  if (!AllowConversionFunctions) {
+    // Don't allow any conversion functions to enter the overload set.
+  } else if (RequireCompleteType(From->getLocStart(), From->getType(),
+                                 PDiag(0)
+                                   << From->getSourceRange())) {
+    // No conversion functions from incomplete types.
+  } else if (const RecordType *FromRecordType
+               = From->getType()->getAs<RecordType>()) {
+    if (CXXRecordDecl *FromRecordDecl
+         = dyn_cast<CXXRecordDecl>(FromRecordType->getDecl())) {
+      // Add all of the conversion functions as candidates.
+      const UnresolvedSetImpl *Conversions
+        = FromRecordDecl->getVisibleConversionFunctions();
+      for (UnresolvedSetImpl::iterator I = Conversions->begin(),
+             E = Conversions->end(); I != E; ++I) {
+        NamedDecl *D = *I;
+        CXXRecordDecl *ActingContext = cast<CXXRecordDecl>(D->getDeclContext());
+        if (isa<UsingShadowDecl>(D))
+          D = cast<UsingShadowDecl>(D)->getTargetDecl();
+
+        CXXConversionDecl *Conv;
+        FunctionTemplateDecl *ConvTemplate;
+        if ((ConvTemplate = dyn_cast<FunctionTemplateDecl>(*I)))
+          Conv = dyn_cast<CXXConversionDecl>(ConvTemplate->getTemplatedDecl());
+        else
+          Conv = dyn_cast<CXXConversionDecl>(*I);
+
+        if (AllowExplicit || !Conv->isExplicit()) {
+          if (ConvTemplate)
+            AddTemplateConversionCandidate(ConvTemplate, I.getAccess(),
+                                           ActingContext, From, ToType,
+                                           CandidateSet);
+          else
+            AddConversionCandidate(Conv, I.getAccess(), ActingContext,
+                                   From, ToType, CandidateSet);
+        }
+      }
+    }
+  }
+
+  OverloadCandidateSet::iterator Best;
+  switch (BestViableFunction(CandidateSet, From->getLocStart(), Best)) {
+    case OR_Success:
+      // Record the standard conversion we used and the conversion function.
+      if (CXXConstructorDecl *Constructor
+            = dyn_cast<CXXConstructorDecl>(Best->Function)) {
+        // C++ [over.ics.user]p1:
+        //   If the user-defined conversion is specified by a
+        //   constructor (12.3.1), the initial standard conversion
+        //   sequence converts the source type to the type required by
+        //   the argument of the constructor.
+        //
+        QualType ThisType = Constructor->getThisType(Context);
+        if (Best->Conversions[0].isEllipsis())
+          User.EllipsisConversion = true;
+        else {
+          User.Before = Best->Conversions[0].Standard;
+          User.EllipsisConversion = false;
+        }
+        User.ConversionFunction = Constructor;
+        User.After.setAsIdentityConversion();
+        User.After.setFromType(
+          ThisType->getAs<PointerType>()->getPointeeType());
+        User.After.setAllToTypes(ToType);
+        return OR_Success;
+      } else if (CXXConversionDecl *Conversion
+                   = dyn_cast<CXXConversionDecl>(Best->Function)) {
+        // C++ [over.ics.user]p1:
+        //
+        //   [...] If the user-defined conversion is specified by a
+        //   conversion function (12.3.2), the initial standard
+        //   conversion sequence converts the source type to the
+        //   implicit object parameter of the conversion function.
+        User.Before = Best->Conversions[0].Standard;
+        User.ConversionFunction = Conversion;
+        User.EllipsisConversion = false;
+
+        // C++ [over.ics.user]p2:
+        //   The second standard conversion sequence converts the
+        //   result of the user-defined conversion to the target type
+        //   for the sequence. Since an implicit conversion sequence
+        //   is an initialization, the special rules for
+        //   initialization by user-defined conversion apply when
+        //   selecting the best user-defined conversion for a
+        //   user-defined conversion sequence (see 13.3.3 and
+        //   13.3.3.1).
+        User.After = Best->FinalConversion;
+        return OR_Success;
+      } else {
+        assert(false && "Not a constructor or conversion function?");
+        return OR_No_Viable_Function;
+      }
+
+    case OR_No_Viable_Function:
+      return OR_No_Viable_Function;
+    case OR_Deleted:
+      // No conversion here! We're done.
+      return OR_Deleted;
+
+    case OR_Ambiguous:
+      return OR_Ambiguous;
+    }
+
+  return OR_No_Viable_Function;
+}
+  
+bool
+Sema::DiagnoseMultipleUserDefinedConversion(Expr *From, QualType ToType) {
+  ImplicitConversionSequence ICS;
+  OverloadCandidateSet CandidateSet(From->getExprLoc());
+  OverloadingResult OvResult = 
+    IsUserDefinedConversion(From, ToType, ICS.UserDefined,
+                            CandidateSet, true, false, false);
+  if (OvResult == OR_Ambiguous)
+    Diag(From->getSourceRange().getBegin(),
+         diag::err_typecheck_ambiguous_condition)
+          << From->getType() << ToType << From->getSourceRange();
+  else if (OvResult == OR_No_Viable_Function && !CandidateSet.empty())
+    Diag(From->getSourceRange().getBegin(),
+         diag::err_typecheck_nonviable_condition)
+    << From->getType() << ToType << From->getSourceRange();
+  else
+    return false;
+  PrintOverloadCandidates(CandidateSet, OCD_AllCandidates, &From, 1);
+  return true;  
+}
+
+/// CompareImplicitConversionSequences - Compare two implicit
+/// conversion sequences to determine whether one is better than the
+/// other or if they are indistinguishable (C++ 13.3.3.2).
+ImplicitConversionSequence::CompareKind
+Sema::CompareImplicitConversionSequences(const ImplicitConversionSequence& ICS1,
+                                         const ImplicitConversionSequence& ICS2)
+{
+  // (C++ 13.3.3.2p2): When comparing the basic forms of implicit
+  // conversion sequences (as defined in 13.3.3.1)
+  //   -- a standard conversion sequence (13.3.3.1.1) is a better
+  //      conversion sequence than a user-defined conversion sequence or
+  //      an ellipsis conversion sequence, and
+  //   -- a user-defined conversion sequence (13.3.3.1.2) is a better
+  //      conversion sequence than an ellipsis conversion sequence
+  //      (13.3.3.1.3).
+  //
+  // C++0x [over.best.ics]p10:
+  //   For the purpose of ranking implicit conversion sequences as
+  //   described in 13.3.3.2, the ambiguous conversion sequence is
+  //   treated as a user-defined sequence that is indistinguishable
+  //   from any other user-defined conversion sequence.
+  if (ICS1.getKind() < ICS2.getKind()) {
+    if (!(ICS1.isUserDefined() && ICS2.isAmbiguous()))
+      return ImplicitConversionSequence::Better;
+  } else if (ICS2.getKind() < ICS1.getKind()) {
+    if (!(ICS2.isUserDefined() && ICS1.isAmbiguous()))
+      return ImplicitConversionSequence::Worse;
+  }
+
+  if (ICS1.isAmbiguous() || ICS2.isAmbiguous())
+    return ImplicitConversionSequence::Indistinguishable;
+
+  // Two implicit conversion sequences of the same form are
+  // indistinguishable conversion sequences unless one of the
+  // following rules apply: (C++ 13.3.3.2p3):
+  if (ICS1.isStandard())
+    return CompareStandardConversionSequences(ICS1.Standard, ICS2.Standard);
+  else if (ICS1.isUserDefined()) {
+    // User-defined conversion sequence U1 is a better conversion
+    // sequence than another user-defined conversion sequence U2 if
+    // they contain the same user-defined conversion function or
+    // constructor and if the second standard conversion sequence of
+    // U1 is better than the second standard conversion sequence of
+    // U2 (C++ 13.3.3.2p3).
+    if (ICS1.UserDefined.ConversionFunction ==
+          ICS2.UserDefined.ConversionFunction)
+      return CompareStandardConversionSequences(ICS1.UserDefined.After,
+                                                ICS2.UserDefined.After);
+  }
+
+  return ImplicitConversionSequence::Indistinguishable;
+}
+
+// Per 13.3.3.2p3, compare the given standard conversion sequences to
+// determine if one is a proper subset of the other.
+static ImplicitConversionSequence::CompareKind
+compareStandardConversionSubsets(ASTContext &Context,
+                                 const StandardConversionSequence& SCS1,
+                                 const StandardConversionSequence& SCS2) {
+  ImplicitConversionSequence::CompareKind Result
+    = ImplicitConversionSequence::Indistinguishable;
+
+  if (SCS1.Second != SCS2.Second) {
+    if (SCS1.Second == ICK_Identity)
+      Result = ImplicitConversionSequence::Better;
+    else if (SCS2.Second == ICK_Identity)
+      Result = ImplicitConversionSequence::Worse;
+    else
+      return ImplicitConversionSequence::Indistinguishable;
+  } else if (!Context.hasSameType(SCS1.getToType(1), SCS2.getToType(1)))
+    return ImplicitConversionSequence::Indistinguishable;
+
+  if (SCS1.Third == SCS2.Third) {
+    return Context.hasSameType(SCS1.getToType(2), SCS2.getToType(2))? Result
+                             : ImplicitConversionSequence::Indistinguishable;
+  }
+
+  if (SCS1.Third == ICK_Identity)
+    return Result == ImplicitConversionSequence::Worse
+             ? ImplicitConversionSequence::Indistinguishable
+             : ImplicitConversionSequence::Better;
+
+  if (SCS2.Third == ICK_Identity)
+    return Result == ImplicitConversionSequence::Better
+             ? ImplicitConversionSequence::Indistinguishable
+             : ImplicitConversionSequence::Worse;
+       
+  return ImplicitConversionSequence::Indistinguishable;
+}
+
+/// CompareStandardConversionSequences - Compare two standard
+/// conversion sequences to determine whether one is better than the
+/// other or if they are indistinguishable (C++ 13.3.3.2p3).
+ImplicitConversionSequence::CompareKind
+Sema::CompareStandardConversionSequences(const StandardConversionSequence& SCS1,
+                                         const StandardConversionSequence& SCS2)
+{
+  // Standard conversion sequence S1 is a better conversion sequence
+  // than standard conversion sequence S2 if (C++ 13.3.3.2p3):
+
+  //  -- S1 is a proper subsequence of S2 (comparing the conversion
+  //     sequences in the canonical form defined by 13.3.3.1.1,
+  //     excluding any Lvalue Transformation; the identity conversion
+  //     sequence is considered to be a subsequence of any
+  //     non-identity conversion sequence) or, if not that,
+  if (ImplicitConversionSequence::CompareKind CK
+        = compareStandardConversionSubsets(Context, SCS1, SCS2))
+    return CK;
+
+  //  -- the rank of S1 is better than the rank of S2 (by the rules
+  //     defined below), or, if not that,
+  ImplicitConversionRank Rank1 = SCS1.getRank();
+  ImplicitConversionRank Rank2 = SCS2.getRank();
+  if (Rank1 < Rank2)
+    return ImplicitConversionSequence::Better;
+  else if (Rank2 < Rank1)
+    return ImplicitConversionSequence::Worse;
+
+  // (C++ 13.3.3.2p4): Two conversion sequences with the same rank
+  // are indistinguishable unless one of the following rules
+  // applies:
+
+  //   A conversion that is not a conversion of a pointer, or
+  //   pointer to member, to bool is better than another conversion
+  //   that is such a conversion.
+  if (SCS1.isPointerConversionToBool() != SCS2.isPointerConversionToBool())
+    return SCS2.isPointerConversionToBool()
+             ? ImplicitConversionSequence::Better
+             : ImplicitConversionSequence::Worse;
+
+  // C++ [over.ics.rank]p4b2:
+  //
+  //   If class B is derived directly or indirectly from class A,
+  //   conversion of B* to A* is better than conversion of B* to
+  //   void*, and conversion of A* to void* is better than conversion
+  //   of B* to void*.
+  bool SCS1ConvertsToVoid
+    = SCS1.isPointerConversionToVoidPointer(Context);
+  bool SCS2ConvertsToVoid
+    = SCS2.isPointerConversionToVoidPointer(Context);
+  if (SCS1ConvertsToVoid != SCS2ConvertsToVoid) {
+    // Exactly one of the conversion sequences is a conversion to
+    // a void pointer; it's the worse conversion.
+    return SCS2ConvertsToVoid ? ImplicitConversionSequence::Better
+                              : ImplicitConversionSequence::Worse;
+  } else if (!SCS1ConvertsToVoid && !SCS2ConvertsToVoid) {
+    // Neither conversion sequence converts to a void pointer; compare
+    // their derived-to-base conversions.
+    if (ImplicitConversionSequence::CompareKind DerivedCK
+          = CompareDerivedToBaseConversions(SCS1, SCS2))
+      return DerivedCK;
+  } else if (SCS1ConvertsToVoid && SCS2ConvertsToVoid) {
+    // Both conversion sequences are conversions to void
+    // pointers. Compare the source types to determine if there's an
+    // inheritance relationship in their sources.
+    QualType FromType1 = SCS1.getFromType();
+    QualType FromType2 = SCS2.getFromType();
+
+    // Adjust the types we're converting from via the array-to-pointer
+    // conversion, if we need to.
+    if (SCS1.First == ICK_Array_To_Pointer)
+      FromType1 = Context.getArrayDecayedType(FromType1);
+    if (SCS2.First == ICK_Array_To_Pointer)
+      FromType2 = Context.getArrayDecayedType(FromType2);
+
+    QualType FromPointee1
+      = FromType1->getAs<PointerType>()->getPointeeType().getUnqualifiedType();
+    QualType FromPointee2
+      = FromType2->getAs<PointerType>()->getPointeeType().getUnqualifiedType();
+
+    if (IsDerivedFrom(FromPointee2, FromPointee1))
+      return ImplicitConversionSequence::Better;
+    else if (IsDerivedFrom(FromPointee1, FromPointee2))
+      return ImplicitConversionSequence::Worse;
+
+    // Objective-C++: If one interface is more specific than the
+    // other, it is the better one.
+    const ObjCInterfaceType* FromIface1 = FromPointee1->getAs<ObjCInterfaceType>();
+    const ObjCInterfaceType* FromIface2 = FromPointee2->getAs<ObjCInterfaceType>();
+    if (FromIface1 && FromIface1) {
+      if (Context.canAssignObjCInterfaces(FromIface2, FromIface1))
+        return ImplicitConversionSequence::Better;
+      else if (Context.canAssignObjCInterfaces(FromIface1, FromIface2))
+        return ImplicitConversionSequence::Worse;
+    }
+  }
+
+  // Compare based on qualification conversions (C++ 13.3.3.2p3,
+  // bullet 3).
+  if (ImplicitConversionSequence::CompareKind QualCK
+        = CompareQualificationConversions(SCS1, SCS2))
+    return QualCK;
+
+  if (SCS1.ReferenceBinding && SCS2.ReferenceBinding) {
+    // C++0x [over.ics.rank]p3b4:
+    //   -- S1 and S2 are reference bindings (8.5.3) and neither refers to an
+    //      implicit object parameter of a non-static member function declared
+    //      without a ref-qualifier, and S1 binds an rvalue reference to an
+    //      rvalue and S2 binds an lvalue reference.
+    // FIXME: We don't know if we're dealing with the implicit object parameter,
+    // or if the member function in this case has a ref qualifier.
+    // (Of course, we don't have ref qualifiers yet.)
+    if (SCS1.RRefBinding != SCS2.RRefBinding)
+      return SCS1.RRefBinding ? ImplicitConversionSequence::Better
+                              : ImplicitConversionSequence::Worse;
+
+    // C++ [over.ics.rank]p3b4:
+    //   -- S1 and S2 are reference bindings (8.5.3), and the types to
+    //      which the references refer are the same type except for
+    //      top-level cv-qualifiers, and the type to which the reference
+    //      initialized by S2 refers is more cv-qualified than the type
+    //      to which the reference initialized by S1 refers.
+    QualType T1 = SCS1.getToType(2);
+    QualType T2 = SCS2.getToType(2);
+    T1 = Context.getCanonicalType(T1);
+    T2 = Context.getCanonicalType(T2);
+    Qualifiers T1Quals, T2Quals;
+    QualType UnqualT1 = Context.getUnqualifiedArrayType(T1, T1Quals);
+    QualType UnqualT2 = Context.getUnqualifiedArrayType(T2, T2Quals);
+    if (UnqualT1 == UnqualT2) {
+      // If the type is an array type, promote the element qualifiers to the type
+      // for comparison.
+      if (isa<ArrayType>(T1) && T1Quals)
+        T1 = Context.getQualifiedType(UnqualT1, T1Quals);
+      if (isa<ArrayType>(T2) && T2Quals)
+        T2 = Context.getQualifiedType(UnqualT2, T2Quals);
+      if (T2.isMoreQualifiedThan(T1))
+        return ImplicitConversionSequence::Better;
+      else if (T1.isMoreQualifiedThan(T2))
+        return ImplicitConversionSequence::Worse;
+    }
+  }
+
+  return ImplicitConversionSequence::Indistinguishable;
+}
+
+/// CompareQualificationConversions - Compares two standard conversion
+/// sequences to determine whether they can be ranked based on their
+/// qualification conversions (C++ 13.3.3.2p3 bullet 3).
+ImplicitConversionSequence::CompareKind
+Sema::CompareQualificationConversions(const StandardConversionSequence& SCS1,
+                                      const StandardConversionSequence& SCS2) {
+  // C++ 13.3.3.2p3:
+  //  -- S1 and S2 differ only in their qualification conversion and
+  //     yield similar types T1 and T2 (C++ 4.4), respectively, and the
+  //     cv-qualification signature of type T1 is a proper subset of
+  //     the cv-qualification signature of type T2, and S1 is not the
+  //     deprecated string literal array-to-pointer conversion (4.2).
+  if (SCS1.First != SCS2.First || SCS1.Second != SCS2.Second ||
+      SCS1.Third != SCS2.Third || SCS1.Third != ICK_Qualification)
+    return ImplicitConversionSequence::Indistinguishable;
+
+  // FIXME: the example in the standard doesn't use a qualification
+  // conversion (!)
+  QualType T1 = SCS1.getToType(2);
+  QualType T2 = SCS2.getToType(2);
+  T1 = Context.getCanonicalType(T1);
+  T2 = Context.getCanonicalType(T2);
+  Qualifiers T1Quals, T2Quals;
+  QualType UnqualT1 = Context.getUnqualifiedArrayType(T1, T1Quals);
+  QualType UnqualT2 = Context.getUnqualifiedArrayType(T2, T2Quals);
+
+  // If the types are the same, we won't learn anything by unwrapped
+  // them.
+  if (UnqualT1 == UnqualT2)
+    return ImplicitConversionSequence::Indistinguishable;
+
+  // If the type is an array type, promote the element qualifiers to the type
+  // for comparison.
+  if (isa<ArrayType>(T1) && T1Quals)
+    T1 = Context.getQualifiedType(UnqualT1, T1Quals);
+  if (isa<ArrayType>(T2) && T2Quals)
+    T2 = Context.getQualifiedType(UnqualT2, T2Quals);
+
+  ImplicitConversionSequence::CompareKind Result
+    = ImplicitConversionSequence::Indistinguishable;
+  while (UnwrapSimilarPointerTypes(T1, T2)) {
+    // Within each iteration of the loop, we check the qualifiers to
+    // determine if this still looks like a qualification
+    // conversion. Then, if all is well, we unwrap one more level of
+    // pointers or pointers-to-members and do it all again
+    // until there are no more pointers or pointers-to-members left
+    // to unwrap. This essentially mimics what
+    // IsQualificationConversion does, but here we're checking for a
+    // strict subset of qualifiers.
+    if (T1.getCVRQualifiers() == T2.getCVRQualifiers())
+      // The qualifiers are the same, so this doesn't tell us anything
+      // about how the sequences rank.
+      ;
+    else if (T2.isMoreQualifiedThan(T1)) {
+      // T1 has fewer qualifiers, so it could be the better sequence.
+      if (Result == ImplicitConversionSequence::Worse)
+        // Neither has qualifiers that are a subset of the other's
+        // qualifiers.
+        return ImplicitConversionSequence::Indistinguishable;
+
+      Result = ImplicitConversionSequence::Better;
+    } else if (T1.isMoreQualifiedThan(T2)) {
+      // T2 has fewer qualifiers, so it could be the better sequence.
+      if (Result == ImplicitConversionSequence::Better)
+        // Neither has qualifiers that are a subset of the other's
+        // qualifiers.
+        return ImplicitConversionSequence::Indistinguishable;
+
+      Result = ImplicitConversionSequence::Worse;
+    } else {
+      // Qualifiers are disjoint.
+      return ImplicitConversionSequence::Indistinguishable;
+    }
+
+    // If the types after this point are equivalent, we're done.
+    if (Context.hasSameUnqualifiedType(T1, T2))
+      break;
+  }
+
+  // Check that the winning standard conversion sequence isn't using
+  // the deprecated string literal array to pointer conversion.
+  switch (Result) {
+  case ImplicitConversionSequence::Better:
+    if (SCS1.Deprecated)
+      Result = ImplicitConversionSequence::Indistinguishable;
+    break;
+
+  case ImplicitConversionSequence::Indistinguishable:
+    break;
+
+  case ImplicitConversionSequence::Worse:
+    if (SCS2.Deprecated)
+      Result = ImplicitConversionSequence::Indistinguishable;
+    break;
+  }
+
+  return Result;
+}
+
+/// CompareDerivedToBaseConversions - Compares two standard conversion
+/// sequences to determine whether they can be ranked based on their
+/// various kinds of derived-to-base conversions (C++
+/// [over.ics.rank]p4b3).  As part of these checks, we also look at
+/// conversions between Objective-C interface types.
+ImplicitConversionSequence::CompareKind
+Sema::CompareDerivedToBaseConversions(const StandardConversionSequence& SCS1,
+                                      const StandardConversionSequence& SCS2) {
+  QualType FromType1 = SCS1.getFromType();
+  QualType ToType1 = SCS1.getToType(1);
+  QualType FromType2 = SCS2.getFromType();
+  QualType ToType2 = SCS2.getToType(1);
+
+  // Adjust the types we're converting from via the array-to-pointer
+  // conversion, if we need to.
+  if (SCS1.First == ICK_Array_To_Pointer)
+    FromType1 = Context.getArrayDecayedType(FromType1);
+  if (SCS2.First == ICK_Array_To_Pointer)
+    FromType2 = Context.getArrayDecayedType(FromType2);
+
+  // Canonicalize all of the types.
+  FromType1 = Context.getCanonicalType(FromType1);
+  ToType1 = Context.getCanonicalType(ToType1);
+  FromType2 = Context.getCanonicalType(FromType2);
+  ToType2 = Context.getCanonicalType(ToType2);
+
+  // C++ [over.ics.rank]p4b3:
+  //
+  //   If class B is derived directly or indirectly from class A and
+  //   class C is derived directly or indirectly from B,
+  //
+  // For Objective-C, we let A, B, and C also be Objective-C
+  // interfaces.
+
+  // Compare based on pointer conversions.
+  if (SCS1.Second == ICK_Pointer_Conversion &&
+      SCS2.Second == ICK_Pointer_Conversion &&
+      /*FIXME: Remove if Objective-C id conversions get their own rank*/
+      FromType1->isPointerType() && FromType2->isPointerType() &&
+      ToType1->isPointerType() && ToType2->isPointerType()) {
+    QualType FromPointee1
+      = FromType1->getAs<PointerType>()->getPointeeType().getUnqualifiedType();
+    QualType ToPointee1
+      = ToType1->getAs<PointerType>()->getPointeeType().getUnqualifiedType();
+    QualType FromPointee2
+      = FromType2->getAs<PointerType>()->getPointeeType().getUnqualifiedType();
+    QualType ToPointee2
+      = ToType2->getAs<PointerType>()->getPointeeType().getUnqualifiedType();
+
+    const ObjCInterfaceType* FromIface1 = FromPointee1->getAs<ObjCInterfaceType>();
+    const ObjCInterfaceType* FromIface2 = FromPointee2->getAs<ObjCInterfaceType>();
+    const ObjCInterfaceType* ToIface1 = ToPointee1->getAs<ObjCInterfaceType>();
+    const ObjCInterfaceType* ToIface2 = ToPointee2->getAs<ObjCInterfaceType>();
+
+    //   -- conversion of C* to B* is better than conversion of C* to A*,
+    if (FromPointee1 == FromPointee2 && ToPointee1 != ToPointee2) {
+      if (IsDerivedFrom(ToPointee1, ToPointee2))
+        return ImplicitConversionSequence::Better;
+      else if (IsDerivedFrom(ToPointee2, ToPointee1))
+        return ImplicitConversionSequence::Worse;
+
+      if (ToIface1 && ToIface2) {
+        if (Context.canAssignObjCInterfaces(ToIface2, ToIface1))
+          return ImplicitConversionSequence::Better;
+        else if (Context.canAssignObjCInterfaces(ToIface1, ToIface2))
+          return ImplicitConversionSequence::Worse;
+      }
+    }
+
+    //   -- conversion of B* to A* is better than conversion of C* to A*,
+    if (FromPointee1 != FromPointee2 && ToPointee1 == ToPointee2) {
+      if (IsDerivedFrom(FromPointee2, FromPointee1))
+        return ImplicitConversionSequence::Better;
+      else if (IsDerivedFrom(FromPointee1, FromPointee2))
+        return ImplicitConversionSequence::Worse;
+
+      if (FromIface1 && FromIface2) {
+        if (Context.canAssignObjCInterfaces(FromIface1, FromIface2))
+          return ImplicitConversionSequence::Better;
+        else if (Context.canAssignObjCInterfaces(FromIface2, FromIface1))
+          return ImplicitConversionSequence::Worse;
+      }
+    }
+  }
+
+  // Compare based on reference bindings.
+  if (SCS1.ReferenceBinding && SCS2.ReferenceBinding &&
+      SCS1.Second == ICK_Derived_To_Base) {
+    //   -- binding of an expression of type C to a reference of type
+    //      B& is better than binding an expression of type C to a
+    //      reference of type A&,
+    if (Context.hasSameUnqualifiedType(FromType1, FromType2) &&
+        !Context.hasSameUnqualifiedType(ToType1, ToType2)) {
+      if (IsDerivedFrom(ToType1, ToType2))
+        return ImplicitConversionSequence::Better;
+      else if (IsDerivedFrom(ToType2, ToType1))
+        return ImplicitConversionSequence::Worse;
+    }
+
+    //   -- binding of an expression of type B to a reference of type
+    //      A& is better than binding an expression of type C to a
+    //      reference of type A&,
+    if (!Context.hasSameUnqualifiedType(FromType1, FromType2) &&
+        Context.hasSameUnqualifiedType(ToType1, ToType2)) {
+      if (IsDerivedFrom(FromType2, FromType1))
+        return ImplicitConversionSequence::Better;
+      else if (IsDerivedFrom(FromType1, FromType2))
+        return ImplicitConversionSequence::Worse;
+    }
+  }
+  
+  // Ranking of member-pointer types.
+  if (SCS1.Second == ICK_Pointer_Member && SCS2.Second == ICK_Pointer_Member &&
+      FromType1->isMemberPointerType() && FromType2->isMemberPointerType() &&
+      ToType1->isMemberPointerType() && ToType2->isMemberPointerType()) {
+    const MemberPointerType * FromMemPointer1 = 
+                                        FromType1->getAs<MemberPointerType>();
+    const MemberPointerType * ToMemPointer1 = 
+                                          ToType1->getAs<MemberPointerType>();
+    const MemberPointerType * FromMemPointer2 = 
+                                          FromType2->getAs<MemberPointerType>();
+    const MemberPointerType * ToMemPointer2 = 
+                                          ToType2->getAs<MemberPointerType>();
+    const Type *FromPointeeType1 = FromMemPointer1->getClass();
+    const Type *ToPointeeType1 = ToMemPointer1->getClass();
+    const Type *FromPointeeType2 = FromMemPointer2->getClass();
+    const Type *ToPointeeType2 = ToMemPointer2->getClass();
+    QualType FromPointee1 = QualType(FromPointeeType1, 0).getUnqualifiedType();
+    QualType ToPointee1 = QualType(ToPointeeType1, 0).getUnqualifiedType();
+    QualType FromPointee2 = QualType(FromPointeeType2, 0).getUnqualifiedType();
+    QualType ToPointee2 = QualType(ToPointeeType2, 0).getUnqualifiedType();
+    // conversion of A::* to B::* is better than conversion of A::* to C::*,
+    if (FromPointee1 == FromPointee2 && ToPointee1 != ToPointee2) {
+      if (IsDerivedFrom(ToPointee1, ToPointee2))
+        return ImplicitConversionSequence::Worse;
+      else if (IsDerivedFrom(ToPointee2, ToPointee1))
+        return ImplicitConversionSequence::Better;
+    }
+    // conversion of B::* to C::* is better than conversion of A::* to C::*
+    if (ToPointee1 == ToPointee2 && FromPointee1 != FromPointee2) {
+      if (IsDerivedFrom(FromPointee1, FromPointee2))
+        return ImplicitConversionSequence::Better;
+      else if (IsDerivedFrom(FromPointee2, FromPointee1))
+        return ImplicitConversionSequence::Worse;
+    }
+  }
+  
+  if (SCS1.CopyConstructor && SCS2.CopyConstructor &&
+      SCS1.Second == ICK_Derived_To_Base) {
+    //   -- conversion of C to B is better than conversion of C to A,
+    if (Context.hasSameUnqualifiedType(FromType1, FromType2) &&
+        !Context.hasSameUnqualifiedType(ToType1, ToType2)) {
+      if (IsDerivedFrom(ToType1, ToType2))
+        return ImplicitConversionSequence::Better;
+      else if (IsDerivedFrom(ToType2, ToType1))
+        return ImplicitConversionSequence::Worse;
+    }
+
+    //   -- conversion of B to A is better than conversion of C to A.
+    if (!Context.hasSameUnqualifiedType(FromType1, FromType2) &&
+        Context.hasSameUnqualifiedType(ToType1, ToType2)) {
+      if (IsDerivedFrom(FromType2, FromType1))
+        return ImplicitConversionSequence::Better;
+      else if (IsDerivedFrom(FromType1, FromType2))
+        return ImplicitConversionSequence::Worse;
+    }
+  }
+
+  return ImplicitConversionSequence::Indistinguishable;
+}
+
+/// TryCopyInitialization - Try to copy-initialize a value of type
+/// ToType from the expression From. Return the implicit conversion
+/// sequence required to pass this argument, which may be a bad
+/// conversion sequence (meaning that the argument cannot be passed to
+/// a parameter of this type). If @p SuppressUserConversions, then we
+/// do not permit any user-defined conversion sequences. If @p ForceRValue,
+/// then we treat @p From as an rvalue, even if it is an lvalue.
+ImplicitConversionSequence
+Sema::TryCopyInitialization(Expr *From, QualType ToType,
+                            bool SuppressUserConversions, bool ForceRValue,
+                            bool InOverloadResolution) {
+  if (ToType->isReferenceType()) {
+    ImplicitConversionSequence ICS;
+    ICS.Bad.init(BadConversionSequence::no_conversion, From, ToType);
+    CheckReferenceInit(From, ToType,
+                       /*FIXME:*/From->getLocStart(),
+                       SuppressUserConversions,
+                       /*AllowExplicit=*/false,
+                       ForceRValue,
+                       &ICS);
+    return ICS;
+  } else {
+    return TryImplicitConversion(From, ToType,
+                                 SuppressUserConversions,
+                                 /*AllowExplicit=*/false,
+                                 ForceRValue,
+                                 InOverloadResolution);
+  }
+}
+
+/// PerformCopyInitialization - Copy-initialize an object of type @p ToType with
+/// the expression @p From. Returns true (and emits a diagnostic) if there was
+/// an error, returns false if the initialization succeeded. Elidable should
+/// be true when the copy may be elided (C++ 12.8p15). Overload resolution works
+/// differently in C++0x for this case.
+bool Sema::PerformCopyInitialization(Expr *&From, QualType ToType,
+                                     AssignmentAction Action, bool Elidable) {
+  if (!getLangOptions().CPlusPlus) {
+    // In C, argument passing is the same as performing an assignment.
+    QualType FromType = From->getType();
+
+    AssignConvertType ConvTy =
+      CheckSingleAssignmentConstraints(ToType, From);
+    if (ConvTy != Compatible &&
+        CheckTransparentUnionArgumentConstraints(ToType, From) == Compatible)
+      ConvTy = Compatible;
+
+    return DiagnoseAssignmentResult(ConvTy, From->getLocStart(), ToType,
+                                    FromType, From, Action);
+  }
+
+  if (ToType->isReferenceType())
+    return CheckReferenceInit(From, ToType,
+                              /*FIXME:*/From->getLocStart(),
+                              /*SuppressUserConversions=*/false,
+                              /*AllowExplicit=*/false,
+                              /*ForceRValue=*/false);
+
+  if (!PerformImplicitConversion(From, ToType, Action,
+                                 /*AllowExplicit=*/false, Elidable))
+    return false;
+  if (!DiagnoseMultipleUserDefinedConversion(From, ToType))
+    return Diag(From->getSourceRange().getBegin(),
+                diag::err_typecheck_convert_incompatible)
+      << ToType << From->getType() << Action << From->getSourceRange();
+  return true;
+}
+
+/// TryObjectArgumentInitialization - Try to initialize the object
+/// parameter of the given member function (@c Method) from the
+/// expression @p From.
+ImplicitConversionSequence
+Sema::TryObjectArgumentInitialization(QualType OrigFromType,
+                                      CXXMethodDecl *Method,
+                                      CXXRecordDecl *ActingContext) {
+  QualType ClassType = Context.getTypeDeclType(ActingContext);
+  // [class.dtor]p2: A destructor can be invoked for a const, volatile or
+  //                 const volatile object.
+  unsigned Quals = isa<CXXDestructorDecl>(Method) ?
+    Qualifiers::Const | Qualifiers::Volatile : Method->getTypeQualifiers();
+  QualType ImplicitParamType =  Context.getCVRQualifiedType(ClassType, Quals);
+
+  // Set up the conversion sequence as a "bad" conversion, to allow us
+  // to exit early.
+  ImplicitConversionSequence ICS;
+  ICS.Standard.setAsIdentityConversion();
+  ICS.setBad();
+
+  // We need to have an object of class type.
+  QualType FromType = OrigFromType;
+  if (const PointerType *PT = FromType->getAs<PointerType>())
+    FromType = PT->getPointeeType();
+
+  assert(FromType->isRecordType());
+
+  // The implicit object parameter is has the type "reference to cv X",
+  // where X is the class of which the function is a member
+  // (C++ [over.match.funcs]p4). However, when finding an implicit
+  // conversion sequence for the argument, we are not allowed to
+  // create temporaries or perform user-defined conversions
+  // (C++ [over.match.funcs]p5). We perform a simplified version of
+  // reference binding here, that allows class rvalues to bind to
+  // non-constant references.
+
+  // First check the qualifiers. We don't care about lvalue-vs-rvalue
+  // with the implicit object parameter (C++ [over.match.funcs]p5).
+  QualType FromTypeCanon = Context.getCanonicalType(FromType);
+  if (ImplicitParamType.getCVRQualifiers() 
+                                    != FromTypeCanon.getLocalCVRQualifiers() &&
+      !ImplicitParamType.isAtLeastAsQualifiedAs(FromTypeCanon)) {
+    ICS.Bad.init(BadConversionSequence::bad_qualifiers,
+                 OrigFromType, ImplicitParamType);
+    return ICS;
+  }
+
+  // Check that we have either the same type or a derived type. It
+  // affects the conversion rank.
+  QualType ClassTypeCanon = Context.getCanonicalType(ClassType);
+  if (ClassTypeCanon == FromTypeCanon.getLocalUnqualifiedType())
+    ICS.Standard.Second = ICK_Identity;
+  else if (IsDerivedFrom(FromType, ClassType))
+    ICS.Standard.Second = ICK_Derived_To_Base;
+  else {
+    ICS.Bad.init(BadConversionSequence::unrelated_class, FromType, ImplicitParamType);
+    return ICS;
+  }
+
+  // Success. Mark this as a reference binding.
+  ICS.setStandard();
+  ICS.Standard.setFromType(FromType);
+  ICS.Standard.setAllToTypes(ImplicitParamType);
+  ICS.Standard.ReferenceBinding = true;
+  ICS.Standard.DirectBinding = true;
+  ICS.Standard.RRefBinding = false;
+  return ICS;
+}
+
+/// PerformObjectArgumentInitialization - Perform initialization of
+/// the implicit object parameter for the given Method with the given
+/// expression.
+bool
+Sema::PerformObjectArgumentInitialization(Expr *&From, CXXMethodDecl *Method) {
+  QualType FromRecordType, DestType;
+  QualType ImplicitParamRecordType  =
+    Method->getThisType(Context)->getAs<PointerType>()->getPointeeType();
+
+  if (const PointerType *PT = From->getType()->getAs<PointerType>()) {
+    FromRecordType = PT->getPointeeType();
+    DestType = Method->getThisType(Context);
+  } else {
+    FromRecordType = From->getType();
+    DestType = ImplicitParamRecordType;
+  }
+
+  // Note that we always use the true parent context when performing
+  // the actual argument initialization.
+  ImplicitConversionSequence ICS
+    = TryObjectArgumentInitialization(From->getType(), Method,
+                                      Method->getParent());
+  if (ICS.isBad())
+    return Diag(From->getSourceRange().getBegin(),
+                diag::err_implicit_object_parameter_init)
+       << ImplicitParamRecordType << FromRecordType << From->getSourceRange();
+
+  if (ICS.Standard.Second == ICK_Derived_To_Base &&
+      CheckDerivedToBaseConversion(FromRecordType,
+                                   ImplicitParamRecordType,
+                                   From->getSourceRange().getBegin(),
+                                   From->getSourceRange()))
+    return true;
+
+  ImpCastExprToType(From, DestType, CastExpr::CK_DerivedToBase,
+                    /*isLvalue=*/true);
+  return false;
+}
+
+/// TryContextuallyConvertToBool - Attempt to contextually convert the
+/// expression From to bool (C++0x [conv]p3).
+ImplicitConversionSequence Sema::TryContextuallyConvertToBool(Expr *From) {
+  return TryImplicitConversion(From, Context.BoolTy,
+                               // FIXME: Are these flags correct?
+                               /*SuppressUserConversions=*/false,
+                               /*AllowExplicit=*/true,
+                               /*ForceRValue=*/false,
+                               /*InOverloadResolution=*/false);
+}
+
+/// PerformContextuallyConvertToBool - Perform a contextual conversion
+/// of the expression From to bool (C++0x [conv]p3).
+bool Sema::PerformContextuallyConvertToBool(Expr *&From) {
+  ImplicitConversionSequence ICS = TryContextuallyConvertToBool(From);
+  if (!ICS.isBad())
+    return PerformImplicitConversion(From, Context.BoolTy, ICS, AA_Converting);
+  
+  if (!DiagnoseMultipleUserDefinedConversion(From, Context.BoolTy))
+    return  Diag(From->getSourceRange().getBegin(),
+                 diag::err_typecheck_bool_condition)
+                  << From->getType() << From->getSourceRange();
+  return true;
+}
+
+/// AddOverloadCandidate - Adds the given function to the set of
+/// candidate functions, using the given function call arguments.  If
+/// @p SuppressUserConversions, then don't allow user-defined
+/// conversions via constructors or conversion operators.
+/// If @p ForceRValue, treat all arguments as rvalues. This is a slightly
+/// hacky way to implement the overloading rules for elidable copy
+/// initialization in C++0x (C++0x 12.8p15).
+///
+/// \para PartialOverloading true if we are performing "partial" overloading
+/// based on an incomplete set of function arguments. This feature is used by
+/// code completion.
+void
+Sema::AddOverloadCandidate(FunctionDecl *Function,
+                           AccessSpecifier Access,
+                           Expr **Args, unsigned NumArgs,
+                           OverloadCandidateSet& CandidateSet,
+                           bool SuppressUserConversions,
+                           bool ForceRValue,
+                           bool PartialOverloading) {
+  const FunctionProtoType* Proto
+    = dyn_cast<FunctionProtoType>(Function->getType()->getAs<FunctionType>());
+  assert(Proto && "Functions without a prototype cannot be overloaded");
+  assert(!Function->getDescribedFunctionTemplate() &&
+         "Use AddTemplateOverloadCandidate for function templates");
+
+  if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(Function)) {
+    if (!isa<CXXConstructorDecl>(Method)) {
+      // If we get here, it's because we're calling a member function
+      // that is named without a member access expression (e.g.,
+      // "this->f") that was either written explicitly or created
+      // implicitly. This can happen with a qualified call to a member
+      // function, e.g., X::f(). We use an empty type for the implied
+      // object argument (C++ [over.call.func]p3), and the acting context
+      // is irrelevant.
+      AddMethodCandidate(Method, Access, Method->getParent(),
+                         QualType(), Args, NumArgs, CandidateSet,
+                         SuppressUserConversions, ForceRValue);
+      return;
+    }
+    // We treat a constructor like a non-member function, since its object
+    // argument doesn't participate in overload resolution.
+  }
+
+  if (!CandidateSet.isNewCandidate(Function))
+    return;
+
+  // Overload resolution is always an unevaluated context.
+  EnterExpressionEvaluationContext Unevaluated(*this, Action::Unevaluated);
+
+  if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(Function)){
+    // C++ [class.copy]p3:
+    //   A member function template is never instantiated to perform the copy
+    //   of a class object to an object of its class type.
+    QualType ClassType = Context.getTypeDeclType(Constructor->getParent());
+    if (NumArgs == 1 && 
+        Constructor->isCopyConstructorLikeSpecialization() &&
+        Context.hasSameUnqualifiedType(ClassType, Args[0]->getType()))
+      return;
+  }
+  
+  // Add this candidate
+  CandidateSet.push_back(OverloadCandidate());
+  OverloadCandidate& Candidate = CandidateSet.back();
+  Candidate.Function = Function;
+  Candidate.Access = Access;
+  Candidate.Viable = true;
+  Candidate.IsSurrogate = false;
+  Candidate.IgnoreObjectArgument = false;
+
+  unsigned NumArgsInProto = Proto->getNumArgs();
+
+  // (C++ 13.3.2p2): A candidate function having fewer than m
+  // parameters is viable only if it has an ellipsis in its parameter
+  // list (8.3.5).
+  if ((NumArgs + (PartialOverloading && NumArgs)) > NumArgsInProto && 
+      !Proto->isVariadic()) {
+    Candidate.Viable = false;
+    Candidate.FailureKind = ovl_fail_too_many_arguments;
+    return;
+  }
+
+  // (C++ 13.3.2p2): A candidate function having more than m parameters
+  // is viable only if the (m+1)st parameter has a default argument
+  // (8.3.6). For the purposes of overload resolution, the
+  // parameter list is truncated on the right, so that there are
+  // exactly m parameters.
+  unsigned MinRequiredArgs = Function->getMinRequiredArguments();
+  if (NumArgs < MinRequiredArgs && !PartialOverloading) {
+    // Not enough arguments.
+    Candidate.Viable = false;
+    Candidate.FailureKind = ovl_fail_too_few_arguments;
+    return;
+  }
+
+  // Determine the implicit conversion sequences for each of the
+  // arguments.
+  Candidate.Conversions.resize(NumArgs);
+  for (unsigned ArgIdx = 0; ArgIdx < NumArgs; ++ArgIdx) {
+    if (ArgIdx < NumArgsInProto) {
+      // (C++ 13.3.2p3): for F to be a viable function, there shall
+      // exist for each argument an implicit conversion sequence
+      // (13.3.3.1) that converts that argument to the corresponding
+      // parameter of F.
+      QualType ParamType = Proto->getArgType(ArgIdx);
+      Candidate.Conversions[ArgIdx]
+        = TryCopyInitialization(Args[ArgIdx], ParamType,
+                                SuppressUserConversions, ForceRValue,
+                                /*InOverloadResolution=*/true);
+      if (Candidate.Conversions[ArgIdx].isBad()) {
+        Candidate.Viable = false;
+        Candidate.FailureKind = ovl_fail_bad_conversion;
+        break;
+      }
+    } else {
+      // (C++ 13.3.2p2): For the purposes of overload resolution, any
+      // argument for which there is no corresponding parameter is
+      // considered to ""match the ellipsis" (C+ 13.3.3.1.3).
+      Candidate.Conversions[ArgIdx].setEllipsis();
+    }
+  }
+}
+
+/// \brief Add all of the function declarations in the given function set to
+/// the overload canddiate set.
+void Sema::AddFunctionCandidates(const UnresolvedSetImpl &Fns,
+                                 Expr **Args, unsigned NumArgs,
+                                 OverloadCandidateSet& CandidateSet,
+                                 bool SuppressUserConversions) {
+  for (UnresolvedSetIterator F = Fns.begin(), E = Fns.end(); F != E; ++F) {
+    // FIXME: using declarations
+    if (FunctionDecl *FD = dyn_cast<FunctionDecl>(*F)) {
+      if (isa<CXXMethodDecl>(FD) && !cast<CXXMethodDecl>(FD)->isStatic())
+        AddMethodCandidate(cast<CXXMethodDecl>(FD), F.getAccess(),
+                           cast<CXXMethodDecl>(FD)->getParent(),
+                           Args[0]->getType(), Args + 1, NumArgs - 1, 
+                           CandidateSet, SuppressUserConversions);
+      else
+        AddOverloadCandidate(FD, AS_none, Args, NumArgs, CandidateSet,
+                             SuppressUserConversions);
+    } else {
+      FunctionTemplateDecl *FunTmpl = cast<FunctionTemplateDecl>(*F);
+      if (isa<CXXMethodDecl>(FunTmpl->getTemplatedDecl()) &&
+          !cast<CXXMethodDecl>(FunTmpl->getTemplatedDecl())->isStatic())
+        AddMethodTemplateCandidate(FunTmpl, F.getAccess(),
+                              cast<CXXRecordDecl>(FunTmpl->getDeclContext()),
+                                   /*FIXME: explicit args */ 0,
+                                   Args[0]->getType(), Args + 1, NumArgs - 1,
+                                   CandidateSet,
+                                   SuppressUserConversions);
+      else
+        AddTemplateOverloadCandidate(FunTmpl, AS_none,
+                                     /*FIXME: explicit args */ 0,
+                                     Args, NumArgs, CandidateSet,
+                                     SuppressUserConversions);
+    }
+  }
+}
+
+/// AddMethodCandidate - Adds a named decl (which is some kind of
+/// method) as a method candidate to the given overload set.
+void Sema::AddMethodCandidate(NamedDecl *Decl,
+                              AccessSpecifier Access,
+                              QualType ObjectType,
+                              Expr **Args, unsigned NumArgs,
+                              OverloadCandidateSet& CandidateSet,
+                              bool SuppressUserConversions, bool ForceRValue) {
+  CXXRecordDecl *ActingContext = cast<CXXRecordDecl>(Decl->getDeclContext());
+
+  if (isa<UsingShadowDecl>(Decl))
+    Decl = cast<UsingShadowDecl>(Decl)->getTargetDecl();
+  
+  if (FunctionTemplateDecl *TD = dyn_cast<FunctionTemplateDecl>(Decl)) {
+    assert(isa<CXXMethodDecl>(TD->getTemplatedDecl()) &&
+           "Expected a member function template");
+    AddMethodTemplateCandidate(TD, Access, ActingContext, /*ExplicitArgs*/ 0,
+                               ObjectType, Args, NumArgs,
+                               CandidateSet,
+                               SuppressUserConversions,
+                               ForceRValue);
+  } else {
+    AddMethodCandidate(cast<CXXMethodDecl>(Decl), Access, ActingContext,
+                       ObjectType, Args, NumArgs,
+                       CandidateSet, SuppressUserConversions, ForceRValue);
+  }
+}
+
+/// AddMethodCandidate - Adds the given C++ member function to the set
+/// of candidate functions, using the given function call arguments
+/// and the object argument (@c Object). For example, in a call
+/// @c o.f(a1,a2), @c Object will contain @c o and @c Args will contain
+/// both @c a1 and @c a2. If @p SuppressUserConversions, then don't
+/// allow user-defined conversions via constructors or conversion
+/// operators. If @p ForceRValue, treat all arguments as rvalues. This is
+/// a slightly hacky way to implement the overloading rules for elidable copy
+/// initialization in C++0x (C++0x 12.8p15).
+void
+Sema::AddMethodCandidate(CXXMethodDecl *Method, AccessSpecifier Access,
+                         CXXRecordDecl *ActingContext, QualType ObjectType,
+                         Expr **Args, unsigned NumArgs,
+                         OverloadCandidateSet& CandidateSet,
+                         bool SuppressUserConversions, bool ForceRValue) {
+  const FunctionProtoType* Proto
+    = dyn_cast<FunctionProtoType>(Method->getType()->getAs<FunctionType>());
+  assert(Proto && "Methods without a prototype cannot be overloaded");
+  assert(!isa<CXXConstructorDecl>(Method) &&
+         "Use AddOverloadCandidate for constructors");
+
+  if (!CandidateSet.isNewCandidate(Method))
+    return;
+
+  // Overload resolution is always an unevaluated context.
+  EnterExpressionEvaluationContext Unevaluated(*this, Action::Unevaluated);
+
+  // Add this candidate
+  CandidateSet.push_back(OverloadCandidate());
+  OverloadCandidate& Candidate = CandidateSet.back();
+  Candidate.Function = Method;
+  Candidate.Access = Access;
+  Candidate.IsSurrogate = false;
+  Candidate.IgnoreObjectArgument = false;
+
+  unsigned NumArgsInProto = Proto->getNumArgs();
+
+  // (C++ 13.3.2p2): A candidate function having fewer than m
+  // parameters is viable only if it has an ellipsis in its parameter
+  // list (8.3.5).
+  if (NumArgs > NumArgsInProto && !Proto->isVariadic()) {
+    Candidate.Viable = false;
+    Candidate.FailureKind = ovl_fail_too_many_arguments;
+    return;
+  }
+
+  // (C++ 13.3.2p2): A candidate function having more than m parameters
+  // is viable only if the (m+1)st parameter has a default argument
+  // (8.3.6). For the purposes of overload resolution, the
+  // parameter list is truncated on the right, so that there are
+  // exactly m parameters.
+  unsigned MinRequiredArgs = Method->getMinRequiredArguments();
+  if (NumArgs < MinRequiredArgs) {
+    // Not enough arguments.
+    Candidate.Viable = false;
+    Candidate.FailureKind = ovl_fail_too_few_arguments;
+    return;
+  }
+
+  Candidate.Viable = true;
+  Candidate.Conversions.resize(NumArgs + 1);
+
+  if (Method->isStatic() || ObjectType.isNull())
+    // The implicit object argument is ignored.
+    Candidate.IgnoreObjectArgument = true;
+  else {
+    // Determine the implicit conversion sequence for the object
+    // parameter.
+    Candidate.Conversions[0]
+      = TryObjectArgumentInitialization(ObjectType, Method, ActingContext);
+    if (Candidate.Conversions[0].isBad()) {
+      Candidate.Viable = false;
+      Candidate.FailureKind = ovl_fail_bad_conversion;
+      return;
+    }
+  }
+
+  // Determine the implicit conversion sequences for each of the
+  // arguments.
+  for (unsigned ArgIdx = 0; ArgIdx < NumArgs; ++ArgIdx) {
+    if (ArgIdx < NumArgsInProto) {
+      // (C++ 13.3.2p3): for F to be a viable function, there shall
+      // exist for each argument an implicit conversion sequence
+      // (13.3.3.1) that converts that argument to the corresponding
+      // parameter of F.
+      QualType ParamType = Proto->getArgType(ArgIdx);
+      Candidate.Conversions[ArgIdx + 1]
+        = TryCopyInitialization(Args[ArgIdx], ParamType,
+                                SuppressUserConversions, ForceRValue,
+                                /*InOverloadResolution=*/true);
+      if (Candidate.Conversions[ArgIdx + 1].isBad()) {
+        Candidate.Viable = false;
+        Candidate.FailureKind = ovl_fail_bad_conversion;
+        break;
+      }
+    } else {
+      // (C++ 13.3.2p2): For the purposes of overload resolution, any
+      // argument for which there is no corresponding parameter is
+      // considered to ""match the ellipsis" (C+ 13.3.3.1.3).
+      Candidate.Conversions[ArgIdx + 1].setEllipsis();
+    }
+  }
+}
+
+/// \brief Add a C++ member function template as a candidate to the candidate
+/// set, using template argument deduction to produce an appropriate member
+/// function template specialization.
+void
+Sema::AddMethodTemplateCandidate(FunctionTemplateDecl *MethodTmpl,
+                                 AccessSpecifier Access,
+                                 CXXRecordDecl *ActingContext,
+                        const TemplateArgumentListInfo *ExplicitTemplateArgs,
+                                 QualType ObjectType,
+                                 Expr **Args, unsigned NumArgs,
+                                 OverloadCandidateSet& CandidateSet,
+                                 bool SuppressUserConversions,
+                                 bool ForceRValue) {
+  if (!CandidateSet.isNewCandidate(MethodTmpl))
+    return;
+
+  // C++ [over.match.funcs]p7:
+  //   In each case where a candidate is a function template, candidate
+  //   function template specializations are generated using template argument
+  //   deduction (14.8.3, 14.8.2). Those candidates are then handled as
+  //   candidate functions in the usual way.113) A given name can refer to one
+  //   or more function templates and also to a set of overloaded non-template
+  //   functions. In such a case, the candidate functions generated from each
+  //   function template are combined with the set of non-template candidate
+  //   functions.
+  TemplateDeductionInfo Info(Context, CandidateSet.getLocation());
+  FunctionDecl *Specialization = 0;
+  if (TemplateDeductionResult Result
+      = DeduceTemplateArguments(MethodTmpl, ExplicitTemplateArgs,
+                                Args, NumArgs, Specialization, Info)) {
+        // FIXME: Record what happened with template argument deduction, so
+        // that we can give the user a beautiful diagnostic.
+        (void)Result;
+        return;
+      }
+
+  // Add the function template specialization produced by template argument
+  // deduction as a candidate.
+  assert(Specialization && "Missing member function template specialization?");
+  assert(isa<CXXMethodDecl>(Specialization) &&
+         "Specialization is not a member function?");
+  AddMethodCandidate(cast<CXXMethodDecl>(Specialization), Access,
+                     ActingContext, ObjectType, Args, NumArgs,
+                     CandidateSet, SuppressUserConversions, ForceRValue);
+}
+
+/// \brief Add a C++ function template specialization as a candidate
+/// in the candidate set, using template argument deduction to produce
+/// an appropriate function template specialization.
+void
+Sema::AddTemplateOverloadCandidate(FunctionTemplateDecl *FunctionTemplate,
+                                   AccessSpecifier Access,
+                        const TemplateArgumentListInfo *ExplicitTemplateArgs,
+                                   Expr **Args, unsigned NumArgs,
+                                   OverloadCandidateSet& CandidateSet,
+                                   bool SuppressUserConversions,
+                                   bool ForceRValue) {
+  if (!CandidateSet.isNewCandidate(FunctionTemplate))
+    return;
+
+  // C++ [over.match.funcs]p7:
+  //   In each case where a candidate is a function template, candidate
+  //   function template specializations are generated using template argument
+  //   deduction (14.8.3, 14.8.2). Those candidates are then handled as
+  //   candidate functions in the usual way.113) A given name can refer to one
+  //   or more function templates and also to a set of overloaded non-template
+  //   functions. In such a case, the candidate functions generated from each
+  //   function template are combined with the set of non-template candidate
+  //   functions.
+  TemplateDeductionInfo Info(Context, CandidateSet.getLocation());
+  FunctionDecl *Specialization = 0;
+  if (TemplateDeductionResult Result
+        = DeduceTemplateArguments(FunctionTemplate, ExplicitTemplateArgs,
+                                  Args, NumArgs, Specialization, Info)) {
+    CandidateSet.push_back(OverloadCandidate());
+    OverloadCandidate &Candidate = CandidateSet.back();
+    Candidate.Function = FunctionTemplate->getTemplatedDecl();
+    Candidate.Access = Access;
+    Candidate.Viable = false;
+    Candidate.FailureKind = ovl_fail_bad_deduction;
+    Candidate.IsSurrogate = false;
+    Candidate.IgnoreObjectArgument = false;
+
+    // TODO: record more information about failed template arguments
+    Candidate.DeductionFailure.Result = Result;
+    Candidate.DeductionFailure.TemplateParameter = Info.Param.getOpaqueValue();
+    return;
+  }
+
+  // Add the function template specialization produced by template argument
+  // deduction as a candidate.
+  assert(Specialization && "Missing function template specialization?");
+  AddOverloadCandidate(Specialization, Access, Args, NumArgs, CandidateSet,
+                       SuppressUserConversions, ForceRValue);
+}
+
+/// AddConversionCandidate - Add a C++ conversion function as a
+/// candidate in the candidate set (C++ [over.match.conv],
+/// C++ [over.match.copy]). From is the expression we're converting from,
+/// and ToType is the type that we're eventually trying to convert to
+/// (which may or may not be the same type as the type that the
+/// conversion function produces).
+void
+Sema::AddConversionCandidate(CXXConversionDecl *Conversion,
+                             AccessSpecifier Access,
+                             CXXRecordDecl *ActingContext,
+                             Expr *From, QualType ToType,
+                             OverloadCandidateSet& CandidateSet) {
+  assert(!Conversion->getDescribedFunctionTemplate() &&
+         "Conversion function templates use AddTemplateConversionCandidate");
+
+  if (!CandidateSet.isNewCandidate(Conversion))
+    return;
+
+  // Overload resolution is always an unevaluated context.
+  EnterExpressionEvaluationContext Unevaluated(*this, Action::Unevaluated);
+
+  // Add this candidate
+  CandidateSet.push_back(OverloadCandidate());
+  OverloadCandidate& Candidate = CandidateSet.back();
+  Candidate.Function = Conversion;
+  Candidate.Access = Access;
+  Candidate.IsSurrogate = false;
+  Candidate.IgnoreObjectArgument = false;
+  Candidate.FinalConversion.setAsIdentityConversion();
+  Candidate.FinalConversion.setFromType(Conversion->getConversionType());
+  Candidate.FinalConversion.setAllToTypes(ToType);
+
+  // Determine the implicit conversion sequence for the implicit
+  // object parameter.
+  Candidate.Viable = true;
+  Candidate.Conversions.resize(1);
+  Candidate.Conversions[0]
+    = TryObjectArgumentInitialization(From->getType(), Conversion,
+                                      ActingContext);
+  // Conversion functions to a different type in the base class is visible in 
+  // the derived class.  So, a derived to base conversion should not participate
+  // in overload resolution. 
+  if (Candidate.Conversions[0].Standard.Second == ICK_Derived_To_Base)
+    Candidate.Conversions[0].Standard.Second = ICK_Identity;
+  if (Candidate.Conversions[0].isBad()) {
+    Candidate.Viable = false;
+    Candidate.FailureKind = ovl_fail_bad_conversion;
+    return;
+  }
+  
+  // We won't go through a user-define type conversion function to convert a 
+  // derived to base as such conversions are given Conversion Rank. They only
+  // go through a copy constructor. 13.3.3.1.2-p4 [over.ics.user]
+  QualType FromCanon
+    = Context.getCanonicalType(From->getType().getUnqualifiedType());
+  QualType ToCanon = Context.getCanonicalType(ToType).getUnqualifiedType();
+  if (FromCanon == ToCanon || IsDerivedFrom(FromCanon, ToCanon)) {
+    Candidate.Viable = false;
+    Candidate.FailureKind = ovl_fail_trivial_conversion;
+    return;
+  }
+  
+
+  // To determine what the conversion from the result of calling the
+  // conversion function to the type we're eventually trying to
+  // convert to (ToType), we need to synthesize a call to the
+  // conversion function and attempt copy initialization from it. This
+  // makes sure that we get the right semantics with respect to
+  // lvalues/rvalues and the type. Fortunately, we can allocate this
+  // call on the stack and we don't need its arguments to be
+  // well-formed.
+  DeclRefExpr ConversionRef(Conversion, Conversion->getType(),
+                            From->getLocStart());
+  ImplicitCastExpr ConversionFn(Context.getPointerType(Conversion->getType()),
+                                CastExpr::CK_FunctionToPointerDecay,
+                                &ConversionRef, false);
+
+  // Note that it is safe to allocate CallExpr on the stack here because
+  // there are 0 arguments (i.e., nothing is allocated using ASTContext's
+  // allocator).
+  CallExpr Call(Context, &ConversionFn, 0, 0,
+                Conversion->getConversionType().getNonReferenceType(),
+                From->getLocStart());
+  ImplicitConversionSequence ICS =
+    TryCopyInitialization(&Call, ToType,
+                          /*SuppressUserConversions=*/true,
+                          /*ForceRValue=*/false,
+                          /*InOverloadResolution=*/false);
+
+  switch (ICS.getKind()) {
+  case ImplicitConversionSequence::StandardConversion:
+    Candidate.FinalConversion = ICS.Standard;
+    break;
+
+  case ImplicitConversionSequence::BadConversion:
+    Candidate.Viable = false;
+    Candidate.FailureKind = ovl_fail_bad_final_conversion;
+    break;
+
+  default:
+    assert(false &&
+           "Can only end up with a standard conversion sequence or failure");
+  }
+}
+
+/// \brief Adds a conversion function template specialization
+/// candidate to the overload set, using template argument deduction
+/// to deduce the template arguments of the conversion function
+/// template from the type that we are converting to (C++
+/// [temp.deduct.conv]).
+void
+Sema::AddTemplateConversionCandidate(FunctionTemplateDecl *FunctionTemplate,
+                                     AccessSpecifier Access,
+                                     CXXRecordDecl *ActingDC,
+                                     Expr *From, QualType ToType,
+                                     OverloadCandidateSet &CandidateSet) {
+  assert(isa<CXXConversionDecl>(FunctionTemplate->getTemplatedDecl()) &&
+         "Only conversion function templates permitted here");
+
+  if (!CandidateSet.isNewCandidate(FunctionTemplate))
+    return;
+
+  TemplateDeductionInfo Info(Context, CandidateSet.getLocation());
+  CXXConversionDecl *Specialization = 0;
+  if (TemplateDeductionResult Result
+        = DeduceTemplateArguments(FunctionTemplate, ToType,
+                                  Specialization, Info)) {
+    // FIXME: Record what happened with template argument deduction, so
+    // that we can give the user a beautiful diagnostic.
+    (void)Result;
+    return;
+  }
+
+  // Add the conversion function template specialization produced by
+  // template argument deduction as a candidate.
+  assert(Specialization && "Missing function template specialization?");
+  AddConversionCandidate(Specialization, Access, ActingDC, From, ToType,
+                         CandidateSet);
+}
+
+/// AddSurrogateCandidate - Adds a "surrogate" candidate function that
+/// converts the given @c Object to a function pointer via the
+/// conversion function @c Conversion, and then attempts to call it
+/// with the given arguments (C++ [over.call.object]p2-4). Proto is
+/// the type of function that we'll eventually be calling.
+void Sema::AddSurrogateCandidate(CXXConversionDecl *Conversion,
+                                 AccessSpecifier Access,
+                                 CXXRecordDecl *ActingContext,
+                                 const FunctionProtoType *Proto,
+                                 QualType ObjectType,
+                                 Expr **Args, unsigned NumArgs,
+                                 OverloadCandidateSet& CandidateSet) {
+  if (!CandidateSet.isNewCandidate(Conversion))
+    return;
+
+  // Overload resolution is always an unevaluated context.
+  EnterExpressionEvaluationContext Unevaluated(*this, Action::Unevaluated);
+
+  CandidateSet.push_back(OverloadCandidate());
+  OverloadCandidate& Candidate = CandidateSet.back();
+  Candidate.Function = 0;
+  Candidate.Access = Access;
+  Candidate.Surrogate = Conversion;
+  Candidate.Viable = true;
+  Candidate.IsSurrogate = true;
+  Candidate.IgnoreObjectArgument = false;
+  Candidate.Conversions.resize(NumArgs + 1);
+
+  // Determine the implicit conversion sequence for the implicit
+  // object parameter.
+  ImplicitConversionSequence ObjectInit
+    = TryObjectArgumentInitialization(ObjectType, Conversion, ActingContext);
+  if (ObjectInit.isBad()) {
+    Candidate.Viable = false;
+    Candidate.FailureKind = ovl_fail_bad_conversion;
+    Candidate.Conversions[0] = ObjectInit;
+    return;
+  }
+
+  // The first conversion is actually a user-defined conversion whose
+  // first conversion is ObjectInit's standard conversion (which is
+  // effectively a reference binding). Record it as such.
+  Candidate.Conversions[0].setUserDefined();
+  Candidate.Conversions[0].UserDefined.Before = ObjectInit.Standard;
+  Candidate.Conversions[0].UserDefined.EllipsisConversion = false;
+  Candidate.Conversions[0].UserDefined.ConversionFunction = Conversion;
+  Candidate.Conversions[0].UserDefined.After
+    = Candidate.Conversions[0].UserDefined.Before;
+  Candidate.Conversions[0].UserDefined.After.setAsIdentityConversion();
+
+  // Find the
+  unsigned NumArgsInProto = Proto->getNumArgs();
+
+  // (C++ 13.3.2p2): A candidate function having fewer than m
+  // parameters is viable only if it has an ellipsis in its parameter
+  // list (8.3.5).
+  if (NumArgs > NumArgsInProto && !Proto->isVariadic()) {
+    Candidate.Viable = false;
+    Candidate.FailureKind = ovl_fail_too_many_arguments;
+    return;
+  }
+
+  // Function types don't have any default arguments, so just check if
+  // we have enough arguments.
+  if (NumArgs < NumArgsInProto) {
+    // Not enough arguments.
+    Candidate.Viable = false;
+    Candidate.FailureKind = ovl_fail_too_few_arguments;
+    return;
+  }
+
+  // Determine the implicit conversion sequences for each of the
+  // arguments.
+  for (unsigned ArgIdx = 0; ArgIdx < NumArgs; ++ArgIdx) {
+    if (ArgIdx < NumArgsInProto) {
+      // (C++ 13.3.2p3): for F to be a viable function, there shall
+      // exist for each argument an implicit conversion sequence
+      // (13.3.3.1) that converts that argument to the corresponding
+      // parameter of F.
+      QualType ParamType = Proto->getArgType(ArgIdx);
+      Candidate.Conversions[ArgIdx + 1]
+        = TryCopyInitialization(Args[ArgIdx], ParamType,
+                                /*SuppressUserConversions=*/false,
+                                /*ForceRValue=*/false,
+                                /*InOverloadResolution=*/false);
+      if (Candidate.Conversions[ArgIdx + 1].isBad()) {
+        Candidate.Viable = false;
+        Candidate.FailureKind = ovl_fail_bad_conversion;
+        break;
+      }
+    } else {
+      // (C++ 13.3.2p2): For the purposes of overload resolution, any
+      // argument for which there is no corresponding parameter is
+      // considered to ""match the ellipsis" (C+ 13.3.3.1.3).
+      Candidate.Conversions[ArgIdx + 1].setEllipsis();
+    }
+  }
+}
+
+// FIXME: This will eventually be removed, once we've migrated all of the
+// operator overloading logic over to the scheme used by binary operators, which
+// works for template instantiation.
+void Sema::AddOperatorCandidates(OverloadedOperatorKind Op, Scope *S,
+                                 SourceLocation OpLoc,
+                                 Expr **Args, unsigned NumArgs,
+                                 OverloadCandidateSet& CandidateSet,
+                                 SourceRange OpRange) {
+  UnresolvedSet<16> Fns;
+
+  QualType T1 = Args[0]->getType();
+  QualType T2;
+  if (NumArgs > 1)
+    T2 = Args[1]->getType();
+
+  DeclarationName OpName = Context.DeclarationNames.getCXXOperatorName(Op);
+  if (S)
+    LookupOverloadedOperatorName(Op, S, T1, T2, Fns);
+  AddFunctionCandidates(Fns, Args, NumArgs, CandidateSet, false);
+  AddArgumentDependentLookupCandidates(OpName, false, Args, NumArgs, 0,
+                                       CandidateSet);
+  AddMemberOperatorCandidates(Op, OpLoc, Args, NumArgs, CandidateSet, OpRange);
+  AddBuiltinOperatorCandidates(Op, OpLoc, Args, NumArgs, CandidateSet);
+}
+
+/// \brief Add overload candidates for overloaded operators that are
+/// member functions.
+///
+/// Add the overloaded operator candidates that are member functions
+/// for the operator Op that was used in an operator expression such
+/// as "x Op y". , Args/NumArgs provides the operator arguments, and
+/// CandidateSet will store the added overload candidates. (C++
+/// [over.match.oper]).
+void Sema::AddMemberOperatorCandidates(OverloadedOperatorKind Op,
+                                       SourceLocation OpLoc,
+                                       Expr **Args, unsigned NumArgs,
+                                       OverloadCandidateSet& CandidateSet,
+                                       SourceRange OpRange) {
+  DeclarationName OpName = Context.DeclarationNames.getCXXOperatorName(Op);
+
+  // C++ [over.match.oper]p3:
+  //   For a unary operator @ with an operand of a type whose
+  //   cv-unqualified version is T1, and for a binary operator @ with
+  //   a left operand of a type whose cv-unqualified version is T1 and
+  //   a right operand of a type whose cv-unqualified version is T2,
+  //   three sets of candidate functions, designated member
+  //   candidates, non-member candidates and built-in candidates, are
+  //   constructed as follows:
+  QualType T1 = Args[0]->getType();
+  QualType T2;
+  if (NumArgs > 1)
+    T2 = Args[1]->getType();
+
+  //     -- If T1 is a class type, the set of member candidates is the
+  //        result of the qualified lookup of T1::operator@
+  //        (13.3.1.1.1); otherwise, the set of member candidates is
+  //        empty.
+  if (const RecordType *T1Rec = T1->getAs<RecordType>()) {
+    // Complete the type if it can be completed. Otherwise, we're done.
+    if (RequireCompleteType(OpLoc, T1, PDiag()))
+      return;
+
+    LookupResult Operators(*this, OpName, OpLoc, LookupOrdinaryName);
+    LookupQualifiedName(Operators, T1Rec->getDecl());
+    Operators.suppressDiagnostics();
+
+    for (LookupResult::iterator Oper = Operators.begin(),
+                             OperEnd = Operators.end();
+         Oper != OperEnd;
+         ++Oper)
+      AddMethodCandidate(*Oper, Oper.getAccess(), Args[0]->getType(),
+                         Args + 1, NumArgs - 1, CandidateSet,
+                         /* SuppressUserConversions = */ false);
+  }
+}
+
+/// AddBuiltinCandidate - Add a candidate for a built-in
+/// operator. ResultTy and ParamTys are the result and parameter types
+/// of the built-in candidate, respectively. Args and NumArgs are the
+/// arguments being passed to the candidate. IsAssignmentOperator
+/// should be true when this built-in candidate is an assignment
+/// operator. NumContextualBoolArguments is the number of arguments
+/// (at the beginning of the argument list) that will be contextually
+/// converted to bool.
+void Sema::AddBuiltinCandidate(QualType ResultTy, QualType *ParamTys,
+                               Expr **Args, unsigned NumArgs,
+                               OverloadCandidateSet& CandidateSet,
+                               bool IsAssignmentOperator,
+                               unsigned NumContextualBoolArguments) {
+  // Overload resolution is always an unevaluated context.
+  EnterExpressionEvaluationContext Unevaluated(*this, Action::Unevaluated);
+
+  // Add this candidate
+  CandidateSet.push_back(OverloadCandidate());
+  OverloadCandidate& Candidate = CandidateSet.back();
+  Candidate.Function = 0;
+  Candidate.Access = AS_none;
+  Candidate.IsSurrogate = false;
+  Candidate.IgnoreObjectArgument = false;
+  Candidate.BuiltinTypes.ResultTy = ResultTy;
+  for (unsigned ArgIdx = 0; ArgIdx < NumArgs; ++ArgIdx)
+    Candidate.BuiltinTypes.ParamTypes[ArgIdx] = ParamTys[ArgIdx];
+
+  // Determine the implicit conversion sequences for each of the
+  // arguments.
+  Candidate.Viable = true;
+  Candidate.Conversions.resize(NumArgs);
+  for (unsigned ArgIdx = 0; ArgIdx < NumArgs; ++ArgIdx) {
+    // C++ [over.match.oper]p4:
+    //   For the built-in assignment operators, conversions of the
+    //   left operand are restricted as follows:
+    //     -- no temporaries are introduced to hold the left operand, and
+    //     -- no user-defined conversions are applied to the left
+    //        operand to achieve a type match with the left-most
+    //        parameter of a built-in candidate.
+    //
+    // We block these conversions by turning off user-defined
+    // conversions, since that is the only way that initialization of
+    // a reference to a non-class type can occur from something that
+    // is not of the same type.
+    if (ArgIdx < NumContextualBoolArguments) {
+      assert(ParamTys[ArgIdx] == Context.BoolTy &&
+             "Contextual conversion to bool requires bool type");
+      Candidate.Conversions[ArgIdx] = TryContextuallyConvertToBool(Args[ArgIdx]);
+    } else {
+      Candidate.Conversions[ArgIdx]
+        = TryCopyInitialization(Args[ArgIdx], ParamTys[ArgIdx],
+                                ArgIdx == 0 && IsAssignmentOperator,
+                                /*ForceRValue=*/false,
+                                /*InOverloadResolution=*/false);
+    }
+    if (Candidate.Conversions[ArgIdx].isBad()) {
+      Candidate.Viable = false;
+      Candidate.FailureKind = ovl_fail_bad_conversion;
+      break;
+    }
+  }
+}
+
+/// BuiltinCandidateTypeSet - A set of types that will be used for the
+/// candidate operator functions for built-in operators (C++
+/// [over.built]). The types are separated into pointer types and
+/// enumeration types.
+class BuiltinCandidateTypeSet  {
+  /// TypeSet - A set of types.
+  typedef llvm::SmallPtrSet<QualType, 8> TypeSet;
+
+  /// PointerTypes - The set of pointer types that will be used in the
+  /// built-in candidates.
+  TypeSet PointerTypes;
+
+  /// MemberPointerTypes - The set of member pointer types that will be
+  /// used in the built-in candidates.
+  TypeSet MemberPointerTypes;
+
+  /// EnumerationTypes - The set of enumeration types that will be
+  /// used in the built-in candidates.
+  TypeSet EnumerationTypes;
+
+  /// Sema - The semantic analysis instance where we are building the
+  /// candidate type set.
+  Sema &SemaRef;
+
+  /// Context - The AST context in which we will build the type sets.
+  ASTContext &Context;
+
+  bool AddPointerWithMoreQualifiedTypeVariants(QualType Ty,
+                                               const Qualifiers &VisibleQuals);
+  bool AddMemberPointerWithMoreQualifiedTypeVariants(QualType Ty);
+
+public:
+  /// iterator - Iterates through the types that are part of the set.
+  typedef TypeSet::iterator iterator;
+
+  BuiltinCandidateTypeSet(Sema &SemaRef)
+    : SemaRef(SemaRef), Context(SemaRef.Context) { }
+
+  void AddTypesConvertedFrom(QualType Ty, 
+                             SourceLocation Loc,
+                             bool AllowUserConversions,
+                             bool AllowExplicitConversions,
+                             const Qualifiers &VisibleTypeConversionsQuals);
+
+  /// pointer_begin - First pointer type found;
+  iterator pointer_begin() { return PointerTypes.begin(); }
+
+  /// pointer_end - Past the last pointer type found;
+  iterator pointer_end() { return PointerTypes.end(); }
+
+  /// member_pointer_begin - First member pointer type found;
+  iterator member_pointer_begin() { return MemberPointerTypes.begin(); }
+
+  /// member_pointer_end - Past the last member pointer type found;
+  iterator member_pointer_end() { return MemberPointerTypes.end(); }
+
+  /// enumeration_begin - First enumeration type found;
+  iterator enumeration_begin() { return EnumerationTypes.begin(); }
+
+  /// enumeration_end - Past the last enumeration type found;
+  iterator enumeration_end() { return EnumerationTypes.end(); }
+};
+
+/// AddPointerWithMoreQualifiedTypeVariants - Add the pointer type @p Ty to
+/// the set of pointer types along with any more-qualified variants of
+/// that type. For example, if @p Ty is "int const *", this routine
+/// will add "int const *", "int const volatile *", "int const
+/// restrict *", and "int const volatile restrict *" to the set of
+/// pointer types. Returns true if the add of @p Ty itself succeeded,
+/// false otherwise.
+///
+/// FIXME: what to do about extended qualifiers?
+bool
+BuiltinCandidateTypeSet::AddPointerWithMoreQualifiedTypeVariants(QualType Ty,
+                                             const Qualifiers &VisibleQuals) {
+
+  // Insert this type.
+  if (!PointerTypes.insert(Ty))
+    return false;
+
+  const PointerType *PointerTy = Ty->getAs<PointerType>();
+  assert(PointerTy && "type was not a pointer type!");
+
+  QualType PointeeTy = PointerTy->getPointeeType();
+  // Don't add qualified variants of arrays. For one, they're not allowed
+  // (the qualifier would sink to the element type), and for another, the
+  // only overload situation where it matters is subscript or pointer +- int,
+  // and those shouldn't have qualifier variants anyway.
+  if (PointeeTy->isArrayType())
+    return true;
+  unsigned BaseCVR = PointeeTy.getCVRQualifiers();
+  if (const ConstantArrayType *Array =Context.getAsConstantArrayType(PointeeTy))
+    BaseCVR = Array->getElementType().getCVRQualifiers();
+  bool hasVolatile = VisibleQuals.hasVolatile();
+  bool hasRestrict = VisibleQuals.hasRestrict();
+  
+  // Iterate through all strict supersets of BaseCVR.
+  for (unsigned CVR = BaseCVR+1; CVR <= Qualifiers::CVRMask; ++CVR) {
+    if ((CVR | BaseCVR) != CVR) continue;
+    // Skip over Volatile/Restrict if no Volatile/Restrict found anywhere
+    // in the types.
+    if ((CVR & Qualifiers::Volatile) && !hasVolatile) continue;
+    if ((CVR & Qualifiers::Restrict) && !hasRestrict) continue;
+    QualType QPointeeTy = Context.getCVRQualifiedType(PointeeTy, CVR);
+    PointerTypes.insert(Context.getPointerType(QPointeeTy));
+  }
+
+  return true;
+}
+
+/// AddMemberPointerWithMoreQualifiedTypeVariants - Add the pointer type @p Ty
+/// to the set of pointer types along with any more-qualified variants of
+/// that type. For example, if @p Ty is "int const *", this routine
+/// will add "int const *", "int const volatile *", "int const
+/// restrict *", and "int const volatile restrict *" to the set of
+/// pointer types. Returns true if the add of @p Ty itself succeeded,
+/// false otherwise.
+///
+/// FIXME: what to do about extended qualifiers?
+bool
+BuiltinCandidateTypeSet::AddMemberPointerWithMoreQualifiedTypeVariants(
+    QualType Ty) {
+  // Insert this type.
+  if (!MemberPointerTypes.insert(Ty))
+    return false;
+
+  const MemberPointerType *PointerTy = Ty->getAs<MemberPointerType>();
+  assert(PointerTy && "type was not a member pointer type!");
+
+  QualType PointeeTy = PointerTy->getPointeeType();
+  // Don't add qualified variants of arrays. For one, they're not allowed
+  // (the qualifier would sink to the element type), and for another, the
+  // only overload situation where it matters is subscript or pointer +- int,
+  // and those shouldn't have qualifier variants anyway.
+  if (PointeeTy->isArrayType())
+    return true;
+  const Type *ClassTy = PointerTy->getClass();
+
+  // Iterate through all strict supersets of the pointee type's CVR
+  // qualifiers.
+  unsigned BaseCVR = PointeeTy.getCVRQualifiers();
+  for (unsigned CVR = BaseCVR+1; CVR <= Qualifiers::CVRMask; ++CVR) {
+    if ((CVR | BaseCVR) != CVR) continue;
+    
+    QualType QPointeeTy = Context.getCVRQualifiedType(PointeeTy, CVR);
+    MemberPointerTypes.insert(Context.getMemberPointerType(QPointeeTy, ClassTy));
+  }
+
+  return true;
+}
+
+/// AddTypesConvertedFrom - Add each of the types to which the type @p
+/// Ty can be implicit converted to the given set of @p Types. We're
+/// primarily interested in pointer types and enumeration types. We also
+/// take member pointer types, for the conditional operator.
+/// AllowUserConversions is true if we should look at the conversion
+/// functions of a class type, and AllowExplicitConversions if we
+/// should also include the explicit conversion functions of a class
+/// type.
+void
+BuiltinCandidateTypeSet::AddTypesConvertedFrom(QualType Ty,
+                                               SourceLocation Loc,
+                                               bool AllowUserConversions,
+                                               bool AllowExplicitConversions,
+                                               const Qualifiers &VisibleQuals) {
+  // Only deal with canonical types.
+  Ty = Context.getCanonicalType(Ty);
+
+  // Look through reference types; they aren't part of the type of an
+  // expression for the purposes of conversions.
+  if (const ReferenceType *RefTy = Ty->getAs<ReferenceType>())
+    Ty = RefTy->getPointeeType();
+
+  // We don't care about qualifiers on the type.
+  Ty = Ty.getLocalUnqualifiedType();
+
+  // If we're dealing with an array type, decay to the pointer.
+  if (Ty->isArrayType())
+    Ty = SemaRef.Context.getArrayDecayedType(Ty);
+
+  if (const PointerType *PointerTy = Ty->getAs<PointerType>()) {
+    QualType PointeeTy = PointerTy->getPointeeType();
+
+    // Insert our type, and its more-qualified variants, into the set
+    // of types.
+    if (!AddPointerWithMoreQualifiedTypeVariants(Ty, VisibleQuals))
+      return;
+  } else if (Ty->isMemberPointerType()) {
+    // Member pointers are far easier, since the pointee can't be converted.
+    if (!AddMemberPointerWithMoreQualifiedTypeVariants(Ty))
+      return;
+  } else if (Ty->isEnumeralType()) {
+    EnumerationTypes.insert(Ty);
+  } else if (AllowUserConversions) {
+    if (const RecordType *TyRec = Ty->getAs<RecordType>()) {
+      if (SemaRef.RequireCompleteType(Loc, Ty, 0)) {
+        // No conversion functions in incomplete types.
+        return;
+      }
+
+      CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(TyRec->getDecl());
+      const UnresolvedSetImpl *Conversions
+        = ClassDecl->getVisibleConversionFunctions();
+      for (UnresolvedSetImpl::iterator I = Conversions->begin(),
+             E = Conversions->end(); I != E; ++I) {
+
+        // Skip conversion function templates; they don't tell us anything
+        // about which builtin types we can convert to.
+        if (isa<FunctionTemplateDecl>(*I))
+          continue;
+
+        CXXConversionDecl *Conv = cast<CXXConversionDecl>(*I);
+        if (AllowExplicitConversions || !Conv->isExplicit()) {
+          AddTypesConvertedFrom(Conv->getConversionType(), Loc, false, false, 
+                                VisibleQuals);
+        }
+      }
+    }
+  }
+}
+
+/// \brief Helper function for AddBuiltinOperatorCandidates() that adds
+/// the volatile- and non-volatile-qualified assignment operators for the
+/// given type to the candidate set.
+static void AddBuiltinAssignmentOperatorCandidates(Sema &S,
+                                                   QualType T,
+                                                   Expr **Args,
+                                                   unsigned NumArgs,
+                                    OverloadCandidateSet &CandidateSet) {
+  QualType ParamTypes[2];
+
+  // T& operator=(T&, T)
+  ParamTypes[0] = S.Context.getLValueReferenceType(T);
+  ParamTypes[1] = T;
+  S.AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 2, CandidateSet,
+                        /*IsAssignmentOperator=*/true);
+
+  if (!S.Context.getCanonicalType(T).isVolatileQualified()) {
+    // volatile T& operator=(volatile T&, T)
+    ParamTypes[0]
+      = S.Context.getLValueReferenceType(S.Context.getVolatileType(T));
+    ParamTypes[1] = T;
+    S.AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 2, CandidateSet,
+                          /*IsAssignmentOperator=*/true);
+  }
+}
+
+/// CollectVRQualifiers - This routine returns Volatile/Restrict qualifiers,
+/// if any, found in visible type conversion functions found in ArgExpr's type.
+static  Qualifiers CollectVRQualifiers(ASTContext &Context, Expr* ArgExpr) {
+    Qualifiers VRQuals;
+    const RecordType *TyRec;
+    if (const MemberPointerType *RHSMPType =
+        ArgExpr->getType()->getAs<MemberPointerType>())
+      TyRec = cast<RecordType>(RHSMPType->getClass());
+    else
+      TyRec = ArgExpr->getType()->getAs<RecordType>();
+    if (!TyRec) {
+      // Just to be safe, assume the worst case.
+      VRQuals.addVolatile();
+      VRQuals.addRestrict();
+      return VRQuals;
+    }
+    
+    CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(TyRec->getDecl());
+    if (!ClassDecl->hasDefinition())
+      return VRQuals;
+
+    const UnresolvedSetImpl *Conversions =
+      ClassDecl->getVisibleConversionFunctions();
+    
+    for (UnresolvedSetImpl::iterator I = Conversions->begin(),
+           E = Conversions->end(); I != E; ++I) {
+      if (CXXConversionDecl *Conv = dyn_cast<CXXConversionDecl>(*I)) {
+        QualType CanTy = Context.getCanonicalType(Conv->getConversionType());
+        if (const ReferenceType *ResTypeRef = CanTy->getAs<ReferenceType>())
+          CanTy = ResTypeRef->getPointeeType();
+        // Need to go down the pointer/mempointer chain and add qualifiers
+        // as see them.
+        bool done = false;
+        while (!done) {
+          if (const PointerType *ResTypePtr = CanTy->getAs<PointerType>())
+            CanTy = ResTypePtr->getPointeeType();
+          else if (const MemberPointerType *ResTypeMPtr = 
+                CanTy->getAs<MemberPointerType>())
+            CanTy = ResTypeMPtr->getPointeeType();
+          else
+            done = true;
+          if (CanTy.isVolatileQualified())
+            VRQuals.addVolatile();
+          if (CanTy.isRestrictQualified())
+            VRQuals.addRestrict();
+          if (VRQuals.hasRestrict() && VRQuals.hasVolatile())
+            return VRQuals;
+        }
+      }
+    }
+    return VRQuals;
+}
+  
+/// AddBuiltinOperatorCandidates - Add the appropriate built-in
+/// operator overloads to the candidate set (C++ [over.built]), based
+/// on the operator @p Op and the arguments given. For example, if the
+/// operator is a binary '+', this routine might add "int
+/// operator+(int, int)" to cover integer addition.
+void
+Sema::AddBuiltinOperatorCandidates(OverloadedOperatorKind Op,
+                                   SourceLocation OpLoc,
+                                   Expr **Args, unsigned NumArgs,
+                                   OverloadCandidateSet& CandidateSet) {
+  // The set of "promoted arithmetic types", which are the arithmetic
+  // types are that preserved by promotion (C++ [over.built]p2). Note
+  // that the first few of these types are the promoted integral
+  // types; these types need to be first.
+  // FIXME: What about complex?
+  const unsigned FirstIntegralType = 0;
+  const unsigned LastIntegralType = 13;
+  const unsigned FirstPromotedIntegralType = 7,
+                 LastPromotedIntegralType = 13;
+  const unsigned FirstPromotedArithmeticType = 7,
+                 LastPromotedArithmeticType = 16;
+  const unsigned NumArithmeticTypes = 16;
+  QualType ArithmeticTypes[NumArithmeticTypes] = {
+    Context.BoolTy, Context.CharTy, Context.WCharTy,
+// FIXME:   Context.Char16Ty, Context.Char32Ty,
+    Context.SignedCharTy, Context.ShortTy,
+    Context.UnsignedCharTy, Context.UnsignedShortTy,
+    Context.IntTy, Context.LongTy, Context.LongLongTy,
+    Context.UnsignedIntTy, Context.UnsignedLongTy, Context.UnsignedLongLongTy,
+    Context.FloatTy, Context.DoubleTy, Context.LongDoubleTy
+  };
+  assert(ArithmeticTypes[FirstPromotedIntegralType] == Context.IntTy &&
+         "Invalid first promoted integral type");
+  assert(ArithmeticTypes[LastPromotedIntegralType - 1] 
+           == Context.UnsignedLongLongTy &&
+         "Invalid last promoted integral type");
+  assert(ArithmeticTypes[FirstPromotedArithmeticType] == Context.IntTy &&
+         "Invalid first promoted arithmetic type");
+  assert(ArithmeticTypes[LastPromotedArithmeticType - 1] 
+            == Context.LongDoubleTy &&
+         "Invalid last promoted arithmetic type");
+         
+  // Find all of the types that the arguments can convert to, but only
+  // if the operator we're looking at has built-in operator candidates
+  // that make use of these types.
+  Qualifiers VisibleTypeConversionsQuals;
+  VisibleTypeConversionsQuals.addConst();
+  for (unsigned ArgIdx = 0; ArgIdx < NumArgs; ++ArgIdx)
+    VisibleTypeConversionsQuals += CollectVRQualifiers(Context, Args[ArgIdx]);
+  
+  BuiltinCandidateTypeSet CandidateTypes(*this);
+  if (Op == OO_Less || Op == OO_Greater || Op == OO_LessEqual ||
+      Op == OO_GreaterEqual || Op == OO_EqualEqual || Op == OO_ExclaimEqual ||
+      Op == OO_Plus || (Op == OO_Minus && NumArgs == 2) || Op == OO_Equal ||
+      Op == OO_PlusEqual || Op == OO_MinusEqual || Op == OO_Subscript ||
+      Op == OO_ArrowStar || Op == OO_PlusPlus || Op == OO_MinusMinus ||
+      (Op == OO_Star && NumArgs == 1) || Op == OO_Conditional) {
+    for (unsigned ArgIdx = 0; ArgIdx < NumArgs; ++ArgIdx)
+      CandidateTypes.AddTypesConvertedFrom(Args[ArgIdx]->getType(),
+                                           OpLoc,
+                                           true,
+                                           (Op == OO_Exclaim ||
+                                            Op == OO_AmpAmp ||
+                                            Op == OO_PipePipe),
+                                           VisibleTypeConversionsQuals);
+  }
+
+  bool isComparison = false;
+  switch (Op) {
+  case OO_None:
+  case NUM_OVERLOADED_OPERATORS:
+    assert(false && "Expected an overloaded operator");
+    break;
+
+  case OO_Star: // '*' is either unary or binary
+    if (NumArgs == 1)
+      goto UnaryStar;
+    else
+      goto BinaryStar;
+    break;
+
+  case OO_Plus: // '+' is either unary or binary
+    if (NumArgs == 1)
+      goto UnaryPlus;
+    else
+      goto BinaryPlus;
+    break;
+
+  case OO_Minus: // '-' is either unary or binary
+    if (NumArgs == 1)
+      goto UnaryMinus;
+    else
+      goto BinaryMinus;
+    break;
+
+  case OO_Amp: // '&' is either unary or binary
+    if (NumArgs == 1)
+      goto UnaryAmp;
+    else
+      goto BinaryAmp;
+
+  case OO_PlusPlus:
+  case OO_MinusMinus:
+    // C++ [over.built]p3:
+    //
+    //   For every pair (T, VQ), where T is an arithmetic type, and VQ
+    //   is either volatile or empty, there exist candidate operator
+    //   functions of the form
+    //
+    //       VQ T&      operator++(VQ T&);
+    //       T          operator++(VQ T&, int);
+    //
+    // C++ [over.built]p4:
+    //
+    //   For every pair (T, VQ), where T is an arithmetic type other
+    //   than bool, and VQ is either volatile or empty, there exist
+    //   candidate operator functions of the form
+    //
+    //       VQ T&      operator--(VQ T&);
+    //       T          operator--(VQ T&, int);
+    for (unsigned Arith = (Op == OO_PlusPlus? 0 : 1);
+         Arith < NumArithmeticTypes; ++Arith) {
+      QualType ArithTy = ArithmeticTypes[Arith];
+      QualType ParamTypes[2]
+        = { Context.getLValueReferenceType(ArithTy), Context.IntTy };
+
+      // Non-volatile version.
+      if (NumArgs == 1)
+        AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 1, CandidateSet);
+      else
+        AddBuiltinCandidate(ArithTy, ParamTypes, Args, 2, CandidateSet);
+      // heuristic to reduce number of builtin candidates in the set.
+      // Add volatile version only if there are conversions to a volatile type.
+      if (VisibleTypeConversionsQuals.hasVolatile()) {
+        // Volatile version
+        ParamTypes[0]
+          = Context.getLValueReferenceType(Context.getVolatileType(ArithTy));
+        if (NumArgs == 1)
+          AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 1, CandidateSet);
+        else
+          AddBuiltinCandidate(ArithTy, ParamTypes, Args, 2, CandidateSet);
+      }
+    }
+
+    // C++ [over.built]p5:
+    //
+    //   For every pair (T, VQ), where T is a cv-qualified or
+    //   cv-unqualified object type, and VQ is either volatile or
+    //   empty, there exist candidate operator functions of the form
+    //
+    //       T*VQ&      operator++(T*VQ&);
+    //       T*VQ&      operator--(T*VQ&);
+    //       T*         operator++(T*VQ&, int);
+    //       T*         operator--(T*VQ&, int);
+    for (BuiltinCandidateTypeSet::iterator Ptr = CandidateTypes.pointer_begin();
+         Ptr != CandidateTypes.pointer_end(); ++Ptr) {
+      // Skip pointer types that aren't pointers to object types.
+      if (!(*Ptr)->getAs<PointerType>()->getPointeeType()->isObjectType())
+        continue;
+
+      QualType ParamTypes[2] = {
+        Context.getLValueReferenceType(*Ptr), Context.IntTy
+      };
+
+      // Without volatile
+      if (NumArgs == 1)
+        AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 1, CandidateSet);
+      else
+        AddBuiltinCandidate(*Ptr, ParamTypes, Args, 2, CandidateSet);
+
+      if (!Context.getCanonicalType(*Ptr).isVolatileQualified() &&
+          VisibleTypeConversionsQuals.hasVolatile()) {
+        // With volatile
+        ParamTypes[0]
+          = Context.getLValueReferenceType(Context.getVolatileType(*Ptr));
+        if (NumArgs == 1)
+          AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 1, CandidateSet);
+        else
+          AddBuiltinCandidate(*Ptr, ParamTypes, Args, 2, CandidateSet);
+      }
+    }
+    break;
+
+  UnaryStar:
+    // C++ [over.built]p6:
+    //   For every cv-qualified or cv-unqualified object type T, there
+    //   exist candidate operator functions of the form
+    //
+    //       T&         operator*(T*);
+    //
+    // C++ [over.built]p7:
+    //   For every function type T, there exist candidate operator
+    //   functions of the form
+    //       T&         operator*(T*);
+    for (BuiltinCandidateTypeSet::iterator Ptr = CandidateTypes.pointer_begin();
+         Ptr != CandidateTypes.pointer_end(); ++Ptr) {
+      QualType ParamTy = *Ptr;
+      QualType PointeeTy = ParamTy->getAs<PointerType>()->getPointeeType();
+      AddBuiltinCandidate(Context.getLValueReferenceType(PointeeTy),
+                          &ParamTy, Args, 1, CandidateSet);
+    }
+    break;
+
+  UnaryPlus:
+    // C++ [over.built]p8:
+    //   For every type T, there exist candidate operator functions of
+    //   the form
+    //
+    //       T*         operator+(T*);
+    for (BuiltinCandidateTypeSet::iterator Ptr = CandidateTypes.pointer_begin();
+         Ptr != CandidateTypes.pointer_end(); ++Ptr) {
+      QualType ParamTy = *Ptr;
+      AddBuiltinCandidate(ParamTy, &ParamTy, Args, 1, CandidateSet);
+    }
+
+    // Fall through
+
+  UnaryMinus:
+    // C++ [over.built]p9:
+    //  For every promoted arithmetic type T, there exist candidate
+    //  operator functions of the form
+    //
+    //       T         operator+(T);
+    //       T         operator-(T);
+    for (unsigned Arith = FirstPromotedArithmeticType;
+         Arith < LastPromotedArithmeticType; ++Arith) {
+      QualType ArithTy = ArithmeticTypes[Arith];
+      AddBuiltinCandidate(ArithTy, &ArithTy, Args, 1, CandidateSet);
+    }
+    break;
+
+  case OO_Tilde:
+    // C++ [over.built]p10:
+    //   For every promoted integral type T, there exist candidate
+    //   operator functions of the form
+    //
+    //        T         operator~(T);
+    for (unsigned Int = FirstPromotedIntegralType;
+         Int < LastPromotedIntegralType; ++Int) {
+      QualType IntTy = ArithmeticTypes[Int];
+      AddBuiltinCandidate(IntTy, &IntTy, Args, 1, CandidateSet);
+    }
+    break;
+
+  case OO_New:
+  case OO_Delete:
+  case OO_Array_New:
+  case OO_Array_Delete:
+  case OO_Call:
+    assert(false && "Special operators don't use AddBuiltinOperatorCandidates");
+    break;
+
+  case OO_Comma:
+  UnaryAmp:
+  case OO_Arrow:
+    // C++ [over.match.oper]p3:
+    //   -- For the operator ',', the unary operator '&', or the
+    //      operator '->', the built-in candidates set is empty.
+    break;
+
+  case OO_EqualEqual:
+  case OO_ExclaimEqual:
+    // C++ [over.match.oper]p16:
+    //   For every pointer to member type T, there exist candidate operator
+    //   functions of the form
+    //
+    //        bool operator==(T,T);
+    //        bool operator!=(T,T);
+    for (BuiltinCandidateTypeSet::iterator
+           MemPtr = CandidateTypes.member_pointer_begin(),
+           MemPtrEnd = CandidateTypes.member_pointer_end();
+         MemPtr != MemPtrEnd;
+         ++MemPtr) {
+      QualType ParamTypes[2] = { *MemPtr, *MemPtr };
+      AddBuiltinCandidate(Context.BoolTy, ParamTypes, Args, 2, CandidateSet);
+    }
+
+    // Fall through
+
+  case OO_Less:
+  case OO_Greater:
+  case OO_LessEqual:
+  case OO_GreaterEqual:
+    // C++ [over.built]p15:
+    //
+    //   For every pointer or enumeration type T, there exist
+    //   candidate operator functions of the form
+    //
+    //        bool       operator<(T, T);
+    //        bool       operator>(T, T);
+    //        bool       operator<=(T, T);
+    //        bool       operator>=(T, T);
+    //        bool       operator==(T, T);
+    //        bool       operator!=(T, T);
+    for (BuiltinCandidateTypeSet::iterator Ptr = CandidateTypes.pointer_begin();
+         Ptr != CandidateTypes.pointer_end(); ++Ptr) {
+      QualType ParamTypes[2] = { *Ptr, *Ptr };
+      AddBuiltinCandidate(Context.BoolTy, ParamTypes, Args, 2, CandidateSet);
+    }
+    for (BuiltinCandidateTypeSet::iterator Enum
+           = CandidateTypes.enumeration_begin();
+         Enum != CandidateTypes.enumeration_end(); ++Enum) {
+      QualType ParamTypes[2] = { *Enum, *Enum };
+      AddBuiltinCandidate(Context.BoolTy, ParamTypes, Args, 2, CandidateSet);
+    }
+
+    // Fall through.
+    isComparison = true;
+
+  BinaryPlus:
+  BinaryMinus:
+    if (!isComparison) {
+      // We didn't fall through, so we must have OO_Plus or OO_Minus.
+
+      // C++ [over.built]p13:
+      //
+      //   For every cv-qualified or cv-unqualified object type T
+      //   there exist candidate operator functions of the form
+      //
+      //      T*         operator+(T*, ptrdiff_t);
+      //      T&         operator[](T*, ptrdiff_t);    [BELOW]
+      //      T*         operator-(T*, ptrdiff_t);
+      //      T*         operator+(ptrdiff_t, T*);
+      //      T&         operator[](ptrdiff_t, T*);    [BELOW]
+      //
+      // C++ [over.built]p14:
+      //
+      //   For every T, where T is a pointer to object type, there
+      //   exist candidate operator functions of the form
+      //
+      //      ptrdiff_t  operator-(T, T);
+      for (BuiltinCandidateTypeSet::iterator Ptr
+             = CandidateTypes.pointer_begin();
+           Ptr != CandidateTypes.pointer_end(); ++Ptr) {
+        QualType ParamTypes[2] = { *Ptr, Context.getPointerDiffType() };
+
+        // operator+(T*, ptrdiff_t) or operator-(T*, ptrdiff_t)
+        AddBuiltinCandidate(*Ptr, ParamTypes, Args, 2, CandidateSet);
+
+        if (Op == OO_Plus) {
+          // T* operator+(ptrdiff_t, T*);
+          ParamTypes[0] = ParamTypes[1];
+          ParamTypes[1] = *Ptr;
+          AddBuiltinCandidate(*Ptr, ParamTypes, Args, 2, CandidateSet);
+        } else {
+          // ptrdiff_t operator-(T, T);
+          ParamTypes[1] = *Ptr;
+          AddBuiltinCandidate(Context.getPointerDiffType(), ParamTypes,
+                              Args, 2, CandidateSet);
+        }
+      }
+    }
+    // Fall through
+
+  case OO_Slash:
+  BinaryStar:
+  Conditional:
+    // C++ [over.built]p12:
+    //
+    //   For every pair of promoted arithmetic types L and R, there
+    //   exist candidate operator functions of the form
+    //
+    //        LR         operator*(L, R);
+    //        LR         operator/(L, R);
+    //        LR         operator+(L, R);
+    //        LR         operator-(L, R);
+    //        bool       operator<(L, R);
+    //        bool       operator>(L, R);
+    //        bool       operator<=(L, R);
+    //        bool       operator>=(L, R);
+    //        bool       operator==(L, R);
+    //        bool       operator!=(L, R);
+    //
+    //   where LR is the result of the usual arithmetic conversions
+    //   between types L and R.
+    //
+    // C++ [over.built]p24:
+    //
+    //   For every pair of promoted arithmetic types L and R, there exist
+    //   candidate operator functions of the form
+    //
+    //        LR       operator?(bool, L, R);
+    //
+    //   where LR is the result of the usual arithmetic conversions
+    //   between types L and R.
+    // Our candidates ignore the first parameter.
+    for (unsigned Left = FirstPromotedArithmeticType;
+         Left < LastPromotedArithmeticType; ++Left) {
+      for (unsigned Right = FirstPromotedArithmeticType;
+           Right < LastPromotedArithmeticType; ++Right) {
+        QualType LandR[2] = { ArithmeticTypes[Left], ArithmeticTypes[Right] };
+        QualType Result
+          = isComparison
+          ? Context.BoolTy
+          : Context.UsualArithmeticConversionsType(LandR[0], LandR[1]);
+        AddBuiltinCandidate(Result, LandR, Args, 2, CandidateSet);
+      }
+    }
+    break;
+
+  case OO_Percent:
+  BinaryAmp:
+  case OO_Caret:
+  case OO_Pipe:
+  case OO_LessLess:
+  case OO_GreaterGreater:
+    // C++ [over.built]p17:
+    //
+    //   For every pair of promoted integral types L and R, there
+    //   exist candidate operator functions of the form
+    //
+    //      LR         operator%(L, R);
+    //      LR         operator&(L, R);
+    //      LR         operator^(L, R);
+    //      LR         operator|(L, R);
+    //      L          operator<<(L, R);
+    //      L          operator>>(L, R);
+    //
+    //   where LR is the result of the usual arithmetic conversions
+    //   between types L and R.
+    for (unsigned Left = FirstPromotedIntegralType;
+         Left < LastPromotedIntegralType; ++Left) {
+      for (unsigned Right = FirstPromotedIntegralType;
+           Right < LastPromotedIntegralType; ++Right) {
+        QualType LandR[2] = { ArithmeticTypes[Left], ArithmeticTypes[Right] };
+        QualType Result = (Op == OO_LessLess || Op == OO_GreaterGreater)
+            ? LandR[0]
+            : Context.UsualArithmeticConversionsType(LandR[0], LandR[1]);
+        AddBuiltinCandidate(Result, LandR, Args, 2, CandidateSet);
+      }
+    }
+    break;
+
+  case OO_Equal:
+    // C++ [over.built]p20:
+    //
+    //   For every pair (T, VQ), where T is an enumeration or
+    //   pointer to member type and VQ is either volatile or
+    //   empty, there exist candidate operator functions of the form
+    //
+    //        VQ T&      operator=(VQ T&, T);
+    for (BuiltinCandidateTypeSet::iterator
+           Enum = CandidateTypes.enumeration_begin(),
+           EnumEnd = CandidateTypes.enumeration_end();
+         Enum != EnumEnd; ++Enum)
+      AddBuiltinAssignmentOperatorCandidates(*this, *Enum, Args, 2,
+                                             CandidateSet);
+    for (BuiltinCandidateTypeSet::iterator
+           MemPtr = CandidateTypes.member_pointer_begin(),
+         MemPtrEnd = CandidateTypes.member_pointer_end();
+         MemPtr != MemPtrEnd; ++MemPtr)
+      AddBuiltinAssignmentOperatorCandidates(*this, *MemPtr, Args, 2,
+                                             CandidateSet);
+      // Fall through.
+
+  case OO_PlusEqual:
+  case OO_MinusEqual:
+    // C++ [over.built]p19:
+    //
+    //   For every pair (T, VQ), where T is any type and VQ is either
+    //   volatile or empty, there exist candidate operator functions
+    //   of the form
+    //
+    //        T*VQ&      operator=(T*VQ&, T*);
+    //
+    // C++ [over.built]p21:
+    //
+    //   For every pair (T, VQ), where T is a cv-qualified or
+    //   cv-unqualified object type and VQ is either volatile or
+    //   empty, there exist candidate operator functions of the form
+    //
+    //        T*VQ&      operator+=(T*VQ&, ptrdiff_t);
+    //        T*VQ&      operator-=(T*VQ&, ptrdiff_t);
+    for (BuiltinCandidateTypeSet::iterator Ptr = CandidateTypes.pointer_begin();
+         Ptr != CandidateTypes.pointer_end(); ++Ptr) {
+      QualType ParamTypes[2];
+      ParamTypes[1] = (Op == OO_Equal)? *Ptr : Context.getPointerDiffType();
+
+      // non-volatile version
+      ParamTypes[0] = Context.getLValueReferenceType(*Ptr);
+      AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 2, CandidateSet,
+                          /*IsAssigmentOperator=*/Op == OO_Equal);
+
+      if (!Context.getCanonicalType(*Ptr).isVolatileQualified() &&
+          VisibleTypeConversionsQuals.hasVolatile()) {
+        // volatile version
+        ParamTypes[0]
+          = Context.getLValueReferenceType(Context.getVolatileType(*Ptr));
+        AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 2, CandidateSet,
+                            /*IsAssigmentOperator=*/Op == OO_Equal);
+      }
+    }
+    // Fall through.
+
+  case OO_StarEqual:
+  case OO_SlashEqual:
+    // C++ [over.built]p18:
+    //
+    //   For every triple (L, VQ, R), where L is an arithmetic type,
+    //   VQ is either volatile or empty, and R is a promoted
+    //   arithmetic type, there exist candidate operator functions of
+    //   the form
+    //
+    //        VQ L&      operator=(VQ L&, R);
+    //        VQ L&      operator*=(VQ L&, R);
+    //        VQ L&      operator/=(VQ L&, R);
+    //        VQ L&      operator+=(VQ L&, R);
+    //        VQ L&      operator-=(VQ L&, R);
+    for (unsigned Left = 0; Left < NumArithmeticTypes; ++Left) {
+      for (unsigned Right = FirstPromotedArithmeticType;
+           Right < LastPromotedArithmeticType; ++Right) {
+        QualType ParamTypes[2];
+        ParamTypes[1] = ArithmeticTypes[Right];
+
+        // Add this built-in operator as a candidate (VQ is empty).
+        ParamTypes[0] = Context.getLValueReferenceType(ArithmeticTypes[Left]);
+        AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 2, CandidateSet,
+                            /*IsAssigmentOperator=*/Op == OO_Equal);
+
+        // Add this built-in operator as a candidate (VQ is 'volatile').
+        if (VisibleTypeConversionsQuals.hasVolatile()) {
+          ParamTypes[0] = Context.getVolatileType(ArithmeticTypes[Left]);
+          ParamTypes[0] = Context.getLValueReferenceType(ParamTypes[0]);
+          AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 2, CandidateSet,
+                              /*IsAssigmentOperator=*/Op == OO_Equal);
+        }
+      }
+    }
+    break;
+
+  case OO_PercentEqual:
+  case OO_LessLessEqual:
+  case OO_GreaterGreaterEqual:
+  case OO_AmpEqual:
+  case OO_CaretEqual:
+  case OO_PipeEqual:
+    // C++ [over.built]p22:
+    //
+    //   For every triple (L, VQ, R), where L is an integral type, VQ
+    //   is either volatile or empty, and R is a promoted integral
+    //   type, there exist candidate operator functions of the form
+    //
+    //        VQ L&       operator%=(VQ L&, R);
+    //        VQ L&       operator<<=(VQ L&, R);
+    //        VQ L&       operator>>=(VQ L&, R);
+    //        VQ L&       operator&=(VQ L&, R);
+    //        VQ L&       operator^=(VQ L&, R);
+    //        VQ L&       operator|=(VQ L&, R);
+    for (unsigned Left = FirstIntegralType; Left < LastIntegralType; ++Left) {
+      for (unsigned Right = FirstPromotedIntegralType;
+           Right < LastPromotedIntegralType; ++Right) {
+        QualType ParamTypes[2];
+        ParamTypes[1] = ArithmeticTypes[Right];
+
+        // Add this built-in operator as a candidate (VQ is empty).
+        ParamTypes[0] = Context.getLValueReferenceType(ArithmeticTypes[Left]);
+        AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 2, CandidateSet);
+        if (VisibleTypeConversionsQuals.hasVolatile()) {
+          // Add this built-in operator as a candidate (VQ is 'volatile').
+          ParamTypes[0] = ArithmeticTypes[Left];
+          ParamTypes[0] = Context.getVolatileType(ParamTypes[0]);
+          ParamTypes[0] = Context.getLValueReferenceType(ParamTypes[0]);
+          AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 2, CandidateSet);
+        }
+      }
+    }
+    break;
+
+  case OO_Exclaim: {
+    // C++ [over.operator]p23:
+    //
+    //   There also exist candidate operator functions of the form
+    //
+    //        bool        operator!(bool);
+    //        bool        operator&&(bool, bool);     [BELOW]
+    //        bool        operator||(bool, bool);     [BELOW]
+    QualType ParamTy = Context.BoolTy;
+    AddBuiltinCandidate(ParamTy, &ParamTy, Args, 1, CandidateSet,
+                        /*IsAssignmentOperator=*/false,
+                        /*NumContextualBoolArguments=*/1);
+    break;
+  }
+
+  case OO_AmpAmp:
+  case OO_PipePipe: {
+    // C++ [over.operator]p23:
+    //
+    //   There also exist candidate operator functions of the form
+    //
+    //        bool        operator!(bool);            [ABOVE]
+    //        bool        operator&&(bool, bool);
+    //        bool        operator||(bool, bool);
+    QualType ParamTypes[2] = { Context.BoolTy, Context.BoolTy };
+    AddBuiltinCandidate(Context.BoolTy, ParamTypes, Args, 2, CandidateSet,
+                        /*IsAssignmentOperator=*/false,
+                        /*NumContextualBoolArguments=*/2);
+    break;
+  }
+
+  case OO_Subscript:
+    // C++ [over.built]p13:
+    //
+    //   For every cv-qualified or cv-unqualified object type T there
+    //   exist candidate operator functions of the form
+    //
+    //        T*         operator+(T*, ptrdiff_t);     [ABOVE]
+    //        T&         operator[](T*, ptrdiff_t);
+    //        T*         operator-(T*, ptrdiff_t);     [ABOVE]
+    //        T*         operator+(ptrdiff_t, T*);     [ABOVE]
+    //        T&         operator[](ptrdiff_t, T*);
+    for (BuiltinCandidateTypeSet::iterator Ptr = CandidateTypes.pointer_begin();
+         Ptr != CandidateTypes.pointer_end(); ++Ptr) {
+      QualType ParamTypes[2] = { *Ptr, Context.getPointerDiffType() };
+      QualType PointeeType = (*Ptr)->getAs<PointerType>()->getPointeeType();
+      QualType ResultTy = Context.getLValueReferenceType(PointeeType);
+
+      // T& operator[](T*, ptrdiff_t)
+      AddBuiltinCandidate(ResultTy, ParamTypes, Args, 2, CandidateSet);
+
+      // T& operator[](ptrdiff_t, T*);
+      ParamTypes[0] = ParamTypes[1];
+      ParamTypes[1] = *Ptr;
+      AddBuiltinCandidate(ResultTy, ParamTypes, Args, 2, CandidateSet);
+    }
+    break;
+
+  case OO_ArrowStar:
+    // C++ [over.built]p11:
+    //    For every quintuple (C1, C2, T, CV1, CV2), where C2 is a class type, 
+    //    C1 is the same type as C2 or is a derived class of C2, T is an object 
+    //    type or a function type, and CV1 and CV2 are cv-qualifier-seqs, 
+    //    there exist candidate operator functions of the form 
+    //    CV12 T& operator->*(CV1 C1*, CV2 T C2::*); 
+    //    where CV12 is the union of CV1 and CV2.
+    {
+      for (BuiltinCandidateTypeSet::iterator Ptr = 
+             CandidateTypes.pointer_begin();
+           Ptr != CandidateTypes.pointer_end(); ++Ptr) {
+        QualType C1Ty = (*Ptr);
+        QualType C1;
+        QualifierCollector Q1;
+        if (const PointerType *PointerTy = C1Ty->getAs<PointerType>()) {
+          C1 = QualType(Q1.strip(PointerTy->getPointeeType()), 0);
+          if (!isa<RecordType>(C1))
+            continue;
+          // heuristic to reduce number of builtin candidates in the set.
+          // Add volatile/restrict version only if there are conversions to a
+          // volatile/restrict type.
+          if (!VisibleTypeConversionsQuals.hasVolatile() && Q1.hasVolatile())
+            continue;
+          if (!VisibleTypeConversionsQuals.hasRestrict() && Q1.hasRestrict())
+            continue;
+        }
+        for (BuiltinCandidateTypeSet::iterator
+             MemPtr = CandidateTypes.member_pointer_begin(),
+             MemPtrEnd = CandidateTypes.member_pointer_end();
+             MemPtr != MemPtrEnd; ++MemPtr) {
+          const MemberPointerType *mptr = cast<MemberPointerType>(*MemPtr);
+          QualType C2 = QualType(mptr->getClass(), 0);
+          C2 = C2.getUnqualifiedType();
+          if (C1 != C2 && !IsDerivedFrom(C1, C2))
+            break;
+          QualType ParamTypes[2] = { *Ptr, *MemPtr };
+          // build CV12 T&
+          QualType T = mptr->getPointeeType();
+          if (!VisibleTypeConversionsQuals.hasVolatile() && 
+              T.isVolatileQualified())
+            continue;
+          if (!VisibleTypeConversionsQuals.hasRestrict() && 
+              T.isRestrictQualified())
+            continue;
+          T = Q1.apply(T);
+          QualType ResultTy = Context.getLValueReferenceType(T);
+          AddBuiltinCandidate(ResultTy, ParamTypes, Args, 2, CandidateSet);
+        }
+      }
+    }
+    break;
+
+  case OO_Conditional:
+    // Note that we don't consider the first argument, since it has been
+    // contextually converted to bool long ago. The candidates below are
+    // therefore added as binary.
+    //
+    // C++ [over.built]p24:
+    //   For every type T, where T is a pointer or pointer-to-member type,
+    //   there exist candidate operator functions of the form
+    //
+    //        T        operator?(bool, T, T);
+    //
+    for (BuiltinCandidateTypeSet::iterator Ptr = CandidateTypes.pointer_begin(),
+         E = CandidateTypes.pointer_end(); Ptr != E; ++Ptr) {
+      QualType ParamTypes[2] = { *Ptr, *Ptr };
+      AddBuiltinCandidate(*Ptr, ParamTypes, Args, 2, CandidateSet);
+    }
+    for (BuiltinCandidateTypeSet::iterator Ptr =
+           CandidateTypes.member_pointer_begin(),
+         E = CandidateTypes.member_pointer_end(); Ptr != E; ++Ptr) {
+      QualType ParamTypes[2] = { *Ptr, *Ptr };
+      AddBuiltinCandidate(*Ptr, ParamTypes, Args, 2, CandidateSet);
+    }
+    goto Conditional;
+  }
+}
+
+/// \brief Add function candidates found via argument-dependent lookup
+/// to the set of overloading candidates.
+///
+/// This routine performs argument-dependent name lookup based on the
+/// given function name (which may also be an operator name) and adds
+/// all of the overload candidates found by ADL to the overload
+/// candidate set (C++ [basic.lookup.argdep]).
+void
+Sema::AddArgumentDependentLookupCandidates(DeclarationName Name,
+                                           bool Operator,
+                                           Expr **Args, unsigned NumArgs,
+                       const TemplateArgumentListInfo *ExplicitTemplateArgs,
+                                           OverloadCandidateSet& CandidateSet,
+                                           bool PartialOverloading) {
+  ADLResult Fns;
+
+  // FIXME: This approach for uniquing ADL results (and removing
+  // redundant candidates from the set) relies on pointer-equality,
+  // which means we need to key off the canonical decl.  However,
+  // always going back to the canonical decl might not get us the
+  // right set of default arguments.  What default arguments are
+  // we supposed to consider on ADL candidates, anyway?
+
+  // FIXME: Pass in the explicit template arguments?
+  ArgumentDependentLookup(Name, Operator, Args, NumArgs, Fns);
+
+  // Erase all of the candidates we already knew about.
+  for (OverloadCandidateSet::iterator Cand = CandidateSet.begin(),
+                                   CandEnd = CandidateSet.end();
+       Cand != CandEnd; ++Cand)
+    if (Cand->Function) {
+      Fns.erase(Cand->Function);
+      if (FunctionTemplateDecl *FunTmpl = Cand->Function->getPrimaryTemplate())
+        Fns.erase(FunTmpl);
+    }
+
+  // For each of the ADL candidates we found, add it to the overload
+  // set.
+  for (ADLResult::iterator I = Fns.begin(), E = Fns.end(); I != E; ++I) {
+    if (FunctionDecl *FD = dyn_cast<FunctionDecl>(*I)) {
+      if (ExplicitTemplateArgs)
+        continue;
+      
+      AddOverloadCandidate(FD, AS_none, Args, NumArgs, CandidateSet,
+                           false, false, PartialOverloading);
+    } else
+      AddTemplateOverloadCandidate(cast<FunctionTemplateDecl>(*I),
+                                   AS_none, ExplicitTemplateArgs,
+                                   Args, NumArgs, CandidateSet);
+  }
+}
+
+/// isBetterOverloadCandidate - Determines whether the first overload
+/// candidate is a better candidate than the second (C++ 13.3.3p1).
+bool
+Sema::isBetterOverloadCandidate(const OverloadCandidate& Cand1,
+                                const OverloadCandidate& Cand2,
+                                SourceLocation Loc) {
+  // Define viable functions to be better candidates than non-viable
+  // functions.
+  if (!Cand2.Viable)
+    return Cand1.Viable;
+  else if (!Cand1.Viable)
+    return false;
+
+  // C++ [over.match.best]p1:
+  //
+  //   -- if F is a static member function, ICS1(F) is defined such
+  //      that ICS1(F) is neither better nor worse than ICS1(G) for
+  //      any function G, and, symmetrically, ICS1(G) is neither
+  //      better nor worse than ICS1(F).
+  unsigned StartArg = 0;
+  if (Cand1.IgnoreObjectArgument || Cand2.IgnoreObjectArgument)
+    StartArg = 1;
+
+  // C++ [over.match.best]p1:
+  //   A viable function F1 is defined to be a better function than another
+  //   viable function F2 if for all arguments i, ICSi(F1) is not a worse
+  //   conversion sequence than ICSi(F2), and then...
+  unsigned NumArgs = Cand1.Conversions.size();
+  assert(Cand2.Conversions.size() == NumArgs && "Overload candidate mismatch");
+  bool HasBetterConversion = false;
+  for (unsigned ArgIdx = StartArg; ArgIdx < NumArgs; ++ArgIdx) {
+    switch (CompareImplicitConversionSequences(Cand1.Conversions[ArgIdx],
+                                               Cand2.Conversions[ArgIdx])) {
+    case ImplicitConversionSequence::Better:
+      // Cand1 has a better conversion sequence.
+      HasBetterConversion = true;
+      break;
+
+    case ImplicitConversionSequence::Worse:
+      // Cand1 can't be better than Cand2.
+      return false;
+
+    case ImplicitConversionSequence::Indistinguishable:
+      // Do nothing.
+      break;
+    }
+  }
+
+  //    -- for some argument j, ICSj(F1) is a better conversion sequence than
+  //       ICSj(F2), or, if not that,
+  if (HasBetterConversion)
+    return true;
+
+  //     - F1 is a non-template function and F2 is a function template
+  //       specialization, or, if not that,
+  if (Cand1.Function && !Cand1.Function->getPrimaryTemplate() &&
+      Cand2.Function && Cand2.Function->getPrimaryTemplate())
+    return true;
+
+  //   -- F1 and F2 are function template specializations, and the function
+  //      template for F1 is more specialized than the template for F2
+  //      according to the partial ordering rules described in 14.5.5.2, or,
+  //      if not that,
+  if (Cand1.Function && Cand1.Function->getPrimaryTemplate() &&
+      Cand2.Function && Cand2.Function->getPrimaryTemplate())
+    if (FunctionTemplateDecl *BetterTemplate
+          = getMoreSpecializedTemplate(Cand1.Function->getPrimaryTemplate(),
+                                       Cand2.Function->getPrimaryTemplate(),
+                                       Loc,
+                       isa<CXXConversionDecl>(Cand1.Function)? TPOC_Conversion 
+                                                             : TPOC_Call))
+      return BetterTemplate == Cand1.Function->getPrimaryTemplate();
+
+  //   -- the context is an initialization by user-defined conversion
+  //      (see 8.5, 13.3.1.5) and the standard conversion sequence
+  //      from the return type of F1 to the destination type (i.e.,
+  //      the type of the entity being initialized) is a better
+  //      conversion sequence than the standard conversion sequence
+  //      from the return type of F2 to the destination type.
+  if (Cand1.Function && Cand2.Function &&
+      isa<CXXConversionDecl>(Cand1.Function) &&
+      isa<CXXConversionDecl>(Cand2.Function)) {
+    switch (CompareStandardConversionSequences(Cand1.FinalConversion,
+                                               Cand2.FinalConversion)) {
+    case ImplicitConversionSequence::Better:
+      // Cand1 has a better conversion sequence.
+      return true;
+
+    case ImplicitConversionSequence::Worse:
+      // Cand1 can't be better than Cand2.
+      return false;
+
+    case ImplicitConversionSequence::Indistinguishable:
+      // Do nothing
+      break;
+    }
+  }
+
+  return false;
+}
+
+/// \brief Computes the best viable function (C++ 13.3.3)
+/// within an overload candidate set.
+///
+/// \param CandidateSet the set of candidate functions.
+///
+/// \param Loc the location of the function name (or operator symbol) for
+/// which overload resolution occurs.
+///
+/// \param Best f overload resolution was successful or found a deleted
+/// function, Best points to the candidate function found.
+///
+/// \returns The result of overload resolution.
+OverloadingResult Sema::BestViableFunction(OverloadCandidateSet& CandidateSet,
+                                           SourceLocation Loc,
+                                        OverloadCandidateSet::iterator& Best) {
+  // Find the best viable function.
+  Best = CandidateSet.end();
+  for (OverloadCandidateSet::iterator Cand = CandidateSet.begin();
+       Cand != CandidateSet.end(); ++Cand) {
+    if (Cand->Viable) {
+      if (Best == CandidateSet.end() ||
+          isBetterOverloadCandidate(*Cand, *Best, Loc))
+        Best = Cand;
+    }
+  }
+
+  // If we didn't find any viable functions, abort.
+  if (Best == CandidateSet.end())
+    return OR_No_Viable_Function;
+
+  // Make sure that this function is better than every other viable
+  // function. If not, we have an ambiguity.
+  for (OverloadCandidateSet::iterator Cand = CandidateSet.begin();
+       Cand != CandidateSet.end(); ++Cand) {
+    if (Cand->Viable &&
+        Cand != Best &&
+        !isBetterOverloadCandidate(*Best, *Cand, Loc)) {
+      Best = CandidateSet.end();
+      return OR_Ambiguous;
+    }
+  }
+
+  // Best is the best viable function.
+  if (Best->Function &&
+      (Best->Function->isDeleted() ||
+       Best->Function->getAttr<UnavailableAttr>()))
+    return OR_Deleted;
+
+  // C++ [basic.def.odr]p2:
+  //   An overloaded function is used if it is selected by overload resolution
+  //   when referred to from a potentially-evaluated expression. [Note: this
+  //   covers calls to named functions (5.2.2), operator overloading
+  //   (clause 13), user-defined conversions (12.3.2), allocation function for
+  //   placement new (5.3.4), as well as non-default initialization (8.5).
+  if (Best->Function)
+    MarkDeclarationReferenced(Loc, Best->Function);
+  return OR_Success;
+}
+
+namespace {
+
+enum OverloadCandidateKind {
+  oc_function,
+  oc_method,
+  oc_constructor,
+  oc_function_template,
+  oc_method_template,
+  oc_constructor_template,
+  oc_implicit_default_constructor,
+  oc_implicit_copy_constructor,
+  oc_implicit_copy_assignment
+};
+
+OverloadCandidateKind ClassifyOverloadCandidate(Sema &S,
+                                                FunctionDecl *Fn,
+                                                std::string &Description) {
+  bool isTemplate = false;
+
+  if (FunctionTemplateDecl *FunTmpl = Fn->getPrimaryTemplate()) {
+    isTemplate = true;
+    Description = S.getTemplateArgumentBindingsText(
+      FunTmpl->getTemplateParameters(), *Fn->getTemplateSpecializationArgs());
+  }
+
+  if (CXXConstructorDecl *Ctor = dyn_cast<CXXConstructorDecl>(Fn)) {
+    if (!Ctor->isImplicit())
+      return isTemplate ? oc_constructor_template : oc_constructor;
+
+    return Ctor->isCopyConstructor() ? oc_implicit_copy_constructor
+                                     : oc_implicit_default_constructor;
+  }
+
+  if (CXXMethodDecl *Meth = dyn_cast<CXXMethodDecl>(Fn)) {
+    // This actually gets spelled 'candidate function' for now, but
+    // it doesn't hurt to split it out.
+    if (!Meth->isImplicit())
+      return isTemplate ? oc_method_template : oc_method;
+
+    assert(Meth->isCopyAssignment()
+           && "implicit method is not copy assignment operator?");
+    return oc_implicit_copy_assignment;
+  }
+
+  return isTemplate ? oc_function_template : oc_function;
+}
+
+} // end anonymous namespace
+
+// Notes the location of an overload candidate.
+void Sema::NoteOverloadCandidate(FunctionDecl *Fn) {
+  std::string FnDesc;
+  OverloadCandidateKind K = ClassifyOverloadCandidate(*this, Fn, FnDesc);
+  Diag(Fn->getLocation(), diag::note_ovl_candidate)
+    << (unsigned) K << FnDesc;
+}
+
+/// Diagnoses an ambiguous conversion.  The partial diagnostic is the
+/// "lead" diagnostic; it will be given two arguments, the source and
+/// target types of the conversion.
+void Sema::DiagnoseAmbiguousConversion(const ImplicitConversionSequence &ICS,
+                                       SourceLocation CaretLoc,
+                                       const PartialDiagnostic &PDiag) {
+  Diag(CaretLoc, PDiag)
+    << ICS.Ambiguous.getFromType() << ICS.Ambiguous.getToType();
+  for (AmbiguousConversionSequence::const_iterator
+         I = ICS.Ambiguous.begin(), E = ICS.Ambiguous.end(); I != E; ++I) {
+    NoteOverloadCandidate(*I);
+  }
+}
+
+namespace {
+
+void DiagnoseBadConversion(Sema &S, OverloadCandidate *Cand, unsigned I) {
+  const ImplicitConversionSequence &Conv = Cand->Conversions[I];
+  assert(Conv.isBad());
+  assert(Cand->Function && "for now, candidate must be a function");
+  FunctionDecl *Fn = Cand->Function;
+
+  // There's a conversion slot for the object argument if this is a
+  // non-constructor method.  Note that 'I' corresponds the
+  // conversion-slot index.
+  bool isObjectArgument = false;
+  if (isa<CXXMethodDecl>(Fn) && !isa<CXXConstructorDecl>(Fn)) {
+    if (I == 0)
+      isObjectArgument = true;
+    else
+      I--;
+  }
+
+  std::string FnDesc;
+  OverloadCandidateKind FnKind = ClassifyOverloadCandidate(S, Fn, FnDesc);
+
+  Expr *FromExpr = Conv.Bad.FromExpr;
+  QualType FromTy = Conv.Bad.getFromType();
+  QualType ToTy = Conv.Bad.getToType();
+
+  if (FromTy == S.Context.OverloadTy) {
+    assert(FromExpr);
+    Expr *E = FromExpr->IgnoreParens();
+    if (isa<UnaryOperator>(E))
+      E = cast<UnaryOperator>(E)->getSubExpr()->IgnoreParens();
+    DeclarationName Name = cast<OverloadExpr>(E)->getName();
+
+    S.Diag(Fn->getLocation(), diag::note_ovl_candidate_bad_overload)
+      << (unsigned) FnKind << FnDesc
+      << (FromExpr ? FromExpr->getSourceRange() : SourceRange())
+      << ToTy << Name << I+1;
+    return;
+  }
+
+  // Do some hand-waving analysis to see if the non-viability is due
+  // to a qualifier mismatch.
+  CanQualType CFromTy = S.Context.getCanonicalType(FromTy);
+  CanQualType CToTy = S.Context.getCanonicalType(ToTy);
+  if (CanQual<ReferenceType> RT = CToTy->getAs<ReferenceType>())
+    CToTy = RT->getPointeeType();
+  else {
+    // TODO: detect and diagnose the full richness of const mismatches.
+    if (CanQual<PointerType> FromPT = CFromTy->getAs<PointerType>())
+      if (CanQual<PointerType> ToPT = CToTy->getAs<PointerType>())
+        CFromTy = FromPT->getPointeeType(), CToTy = ToPT->getPointeeType();
+  }
+
+  if (CToTy.getUnqualifiedType() == CFromTy.getUnqualifiedType() &&
+      !CToTy.isAtLeastAsQualifiedAs(CFromTy)) {
+    // It is dumb that we have to do this here.
+    while (isa<ArrayType>(CFromTy))
+      CFromTy = CFromTy->getAs<ArrayType>()->getElementType();
+    while (isa<ArrayType>(CToTy))
+      CToTy = CFromTy->getAs<ArrayType>()->getElementType();
+
+    Qualifiers FromQs = CFromTy.getQualifiers();
+    Qualifiers ToQs = CToTy.getQualifiers();
+
+    if (FromQs.getAddressSpace() != ToQs.getAddressSpace()) {
+      S.Diag(Fn->getLocation(), diag::note_ovl_candidate_bad_addrspace)
+        << (unsigned) FnKind << FnDesc
+        << (FromExpr ? FromExpr->getSourceRange() : SourceRange())
+        << FromTy
+        << FromQs.getAddressSpace() << ToQs.getAddressSpace()
+        << (unsigned) isObjectArgument << I+1;
+      return;
+    }
+
+    unsigned CVR = FromQs.getCVRQualifiers() & ~ToQs.getCVRQualifiers();
+    assert(CVR && "unexpected qualifiers mismatch");
+
+    if (isObjectArgument) {
+      S.Diag(Fn->getLocation(), diag::note_ovl_candidate_bad_cvr_this)
+        << (unsigned) FnKind << FnDesc
+        << (FromExpr ? FromExpr->getSourceRange() : SourceRange())
+        << FromTy << (CVR - 1);
+    } else {
+      S.Diag(Fn->getLocation(), diag::note_ovl_candidate_bad_cvr)
+        << (unsigned) FnKind << FnDesc
+        << (FromExpr ? FromExpr->getSourceRange() : SourceRange())
+        << FromTy << (CVR - 1) << I+1;
+    }
+    return;
+  }
+
+  // Diagnose references or pointers to incomplete types differently,
+  // since it's far from impossible that the incompleteness triggered
+  // the failure.
+  QualType TempFromTy = FromTy.getNonReferenceType();
+  if (const PointerType *PTy = TempFromTy->getAs<PointerType>())
+    TempFromTy = PTy->getPointeeType();
+  if (TempFromTy->isIncompleteType()) {
+    S.Diag(Fn->getLocation(), diag::note_ovl_candidate_bad_conv_incomplete)
+      << (unsigned) FnKind << FnDesc
+      << (FromExpr ? FromExpr->getSourceRange() : SourceRange())
+      << FromTy << ToTy << (unsigned) isObjectArgument << I+1;
+    return;
+  }
+
+  // TODO: specialize more based on the kind of mismatch
+  S.Diag(Fn->getLocation(), diag::note_ovl_candidate_bad_conv)
+    << (unsigned) FnKind << FnDesc
+    << (FromExpr ? FromExpr->getSourceRange() : SourceRange())
+    << FromTy << ToTy << (unsigned) isObjectArgument << I+1;
+}
+
+void DiagnoseArityMismatch(Sema &S, OverloadCandidate *Cand,
+                           unsigned NumFormalArgs) {
+  // TODO: treat calls to a missing default constructor as a special case
+
+  FunctionDecl *Fn = Cand->Function;
+  const FunctionProtoType *FnTy = Fn->getType()->getAs<FunctionProtoType>();
+
+  unsigned MinParams = Fn->getMinRequiredArguments();
+  
+  // at least / at most / exactly
+  unsigned mode, modeCount;
+  if (NumFormalArgs < MinParams) {
+    assert(Cand->FailureKind == ovl_fail_too_few_arguments);
+    if (MinParams != FnTy->getNumArgs() || FnTy->isVariadic())
+      mode = 0; // "at least"
+    else
+      mode = 2; // "exactly"
+    modeCount = MinParams;
+  } else {
+    assert(Cand->FailureKind == ovl_fail_too_many_arguments);
+    if (MinParams != FnTy->getNumArgs())
+      mode = 1; // "at most"
+    else
+      mode = 2; // "exactly"
+    modeCount = FnTy->getNumArgs();
+  }
+
+  std::string Description;
+  OverloadCandidateKind FnKind = ClassifyOverloadCandidate(S, Fn, Description);
+
+  S.Diag(Fn->getLocation(), diag::note_ovl_candidate_arity)
+    << (unsigned) FnKind << Description << mode << modeCount << NumFormalArgs;
+}
+
+/// Diagnose a failed template-argument deduction.
+void DiagnoseBadDeduction(Sema &S, OverloadCandidate *Cand,
+                          Expr **Args, unsigned NumArgs) {
+  FunctionDecl *Fn = Cand->Function; // pattern
+
+  TemplateParameter Param = TemplateParameter::getFromOpaqueValue(
+                                   Cand->DeductionFailure.TemplateParameter);
+
+  switch (Cand->DeductionFailure.Result) {
+  case Sema::TDK_Success:
+    llvm_unreachable("TDK_success while diagnosing bad deduction");
+
+  case Sema::TDK_Incomplete: {
+    NamedDecl *ParamD;
+    (ParamD = Param.dyn_cast<TemplateTypeParmDecl*>()) ||
+    (ParamD = Param.dyn_cast<NonTypeTemplateParmDecl*>()) ||
+    (ParamD = Param.dyn_cast<TemplateTemplateParmDecl*>());
+    assert(ParamD && "no parameter found for incomplete deduction result");
+    S.Diag(Fn->getLocation(), diag::note_ovl_candidate_incomplete_deduction)
+      << ParamD->getDeclName();
+    return;
+  }
+
+  // TODO: diagnose these individually, then kill off
+  // note_ovl_candidate_bad_deduction, which is uselessly vague.
+  case Sema::TDK_InstantiationDepth:
+  case Sema::TDK_Inconsistent:
+  case Sema::TDK_InconsistentQuals:
+  case Sema::TDK_SubstitutionFailure:
+  case Sema::TDK_NonDeducedMismatch:
+  case Sema::TDK_TooManyArguments:
+  case Sema::TDK_TooFewArguments:
+  case Sema::TDK_InvalidExplicitArguments:
+  case Sema::TDK_FailedOverloadResolution:
+    S.Diag(Fn->getLocation(), diag::note_ovl_candidate_bad_deduction);
+    return;
+  }
+}
+
+/// Generates a 'note' diagnostic for an overload candidate.  We've
+/// already generated a primary error at the call site.
+///
+/// It really does need to be a single diagnostic with its caret
+/// pointed at the candidate declaration.  Yes, this creates some
+/// major challenges of technical writing.  Yes, this makes pointing
+/// out problems with specific arguments quite awkward.  It's still
+/// better than generating twenty screens of text for every failed
+/// overload.
+///
+/// It would be great to be able to express per-candidate problems
+/// more richly for those diagnostic clients that cared, but we'd
+/// still have to be just as careful with the default diagnostics.
+void NoteFunctionCandidate(Sema &S, OverloadCandidate *Cand,
+                           Expr **Args, unsigned NumArgs) {
+  FunctionDecl *Fn = Cand->Function;
+
+  // Note deleted candidates, but only if they're viable.
+  if (Cand->Viable && (Fn->isDeleted() || Fn->hasAttr<UnavailableAttr>())) {
+    std::string FnDesc;
+    OverloadCandidateKind FnKind = ClassifyOverloadCandidate(S, Fn, FnDesc);
+
+    S.Diag(Fn->getLocation(), diag::note_ovl_candidate_deleted)
+      << FnKind << FnDesc << Fn->isDeleted();
+    return;
+  }
+
+  // We don't really have anything else to say about viable candidates.
+  if (Cand->Viable) {
+    S.NoteOverloadCandidate(Fn);
+    return;
+  }
+
+  switch (Cand->FailureKind) {
+  case ovl_fail_too_many_arguments:
+  case ovl_fail_too_few_arguments:
+    return DiagnoseArityMismatch(S, Cand, NumArgs);
+
+  case ovl_fail_bad_deduction:
+    return DiagnoseBadDeduction(S, Cand, Args, NumArgs);
+
+  case ovl_fail_trivial_conversion:
+  case ovl_fail_bad_final_conversion:
+    return S.NoteOverloadCandidate(Fn);
+
+  case ovl_fail_bad_conversion:
+    for (unsigned I = 0, N = Cand->Conversions.size(); I != N; ++I)
+      if (Cand->Conversions[I].isBad())
+        return DiagnoseBadConversion(S, Cand, I);
+    
+    // FIXME: this currently happens when we're called from SemaInit
+    // when user-conversion overload fails.  Figure out how to handle
+    // those conditions and diagnose them well.
+    return S.NoteOverloadCandidate(Fn);
+  }
+}
+
+void NoteSurrogateCandidate(Sema &S, OverloadCandidate *Cand) {
+  // Desugar the type of the surrogate down to a function type,
+  // retaining as many typedefs as possible while still showing
+  // the function type (and, therefore, its parameter types).
+  QualType FnType = Cand->Surrogate->getConversionType();
+  bool isLValueReference = false;
+  bool isRValueReference = false;
+  bool isPointer = false;
+  if (const LValueReferenceType *FnTypeRef =
+        FnType->getAs<LValueReferenceType>()) {
+    FnType = FnTypeRef->getPointeeType();
+    isLValueReference = true;
+  } else if (const RValueReferenceType *FnTypeRef =
+               FnType->getAs<RValueReferenceType>()) {
+    FnType = FnTypeRef->getPointeeType();
+    isRValueReference = true;
+  }
+  if (const PointerType *FnTypePtr = FnType->getAs<PointerType>()) {
+    FnType = FnTypePtr->getPointeeType();
+    isPointer = true;
+  }
+  // Desugar down to a function type.
+  FnType = QualType(FnType->getAs<FunctionType>(), 0);
+  // Reconstruct the pointer/reference as appropriate.
+  if (isPointer) FnType = S.Context.getPointerType(FnType);
+  if (isRValueReference) FnType = S.Context.getRValueReferenceType(FnType);
+  if (isLValueReference) FnType = S.Context.getLValueReferenceType(FnType);
+
+  S.Diag(Cand->Surrogate->getLocation(), diag::note_ovl_surrogate_cand)
+    << FnType;
+}
+
+void NoteBuiltinOperatorCandidate(Sema &S,
+                                  const char *Opc,
+                                  SourceLocation OpLoc,
+                                  OverloadCandidate *Cand) {
+  assert(Cand->Conversions.size() <= 2 && "builtin operator is not binary");
+  std::string TypeStr("operator");
+  TypeStr += Opc;
+  TypeStr += "(";
+  TypeStr += Cand->BuiltinTypes.ParamTypes[0].getAsString();
+  if (Cand->Conversions.size() == 1) {
+    TypeStr += ")";
+    S.Diag(OpLoc, diag::note_ovl_builtin_unary_candidate) << TypeStr;
+  } else {
+    TypeStr += ", ";
+    TypeStr += Cand->BuiltinTypes.ParamTypes[1].getAsString();
+    TypeStr += ")";
+    S.Diag(OpLoc, diag::note_ovl_builtin_binary_candidate) << TypeStr;
+  }
+}
+
+void NoteAmbiguousUserConversions(Sema &S, SourceLocation OpLoc,
+                                  OverloadCandidate *Cand) {
+  unsigned NoOperands = Cand->Conversions.size();
+  for (unsigned ArgIdx = 0; ArgIdx < NoOperands; ++ArgIdx) {
+    const ImplicitConversionSequence &ICS = Cand->Conversions[ArgIdx];
+    if (ICS.isBad()) break; // all meaningless after first invalid
+    if (!ICS.isAmbiguous()) continue;
+
+    S.DiagnoseAmbiguousConversion(ICS, OpLoc,
+                              PDiag(diag::note_ambiguous_type_conversion));
+  }
+}
+
+SourceLocation GetLocationForCandidate(const OverloadCandidate *Cand) {
+  if (Cand->Function)
+    return Cand->Function->getLocation();
+  if (Cand->IsSurrogate)
+    return Cand->Surrogate->getLocation();
+  return SourceLocation();
+}
+
+struct CompareOverloadCandidatesForDisplay {
+  Sema &S;
+  CompareOverloadCandidatesForDisplay(Sema &S) : S(S) {}
+
+  bool operator()(const OverloadCandidate *L,
+                  const OverloadCandidate *R) {
+    // Fast-path this check.
+    if (L == R) return false;
+
+    // Order first by viability.
+    if (L->Viable) {
+      if (!R->Viable) return true;
+
+      // TODO: introduce a tri-valued comparison for overload
+      // candidates.  Would be more worthwhile if we had a sort
+      // that could exploit it.
+      if (S.isBetterOverloadCandidate(*L, *R, SourceLocation())) return true;
+      if (S.isBetterOverloadCandidate(*R, *L, SourceLocation())) return false;
+    } else if (R->Viable)
+      return false;
+
+    assert(L->Viable == R->Viable);
+
+    // Criteria by which we can sort non-viable candidates:
+    if (!L->Viable) {
+      // 1. Arity mismatches come after other candidates.
+      if (L->FailureKind == ovl_fail_too_many_arguments ||
+          L->FailureKind == ovl_fail_too_few_arguments)
+        return false;
+      if (R->FailureKind == ovl_fail_too_many_arguments ||
+          R->FailureKind == ovl_fail_too_few_arguments)
+        return true;
+
+      // 2. Bad conversions come first and are ordered by the number
+      // of bad conversions and quality of good conversions.
+      if (L->FailureKind == ovl_fail_bad_conversion) {
+        if (R->FailureKind != ovl_fail_bad_conversion)
+          return true;
+
+        // If there's any ordering between the defined conversions...
+        // FIXME: this might not be transitive.
+        assert(L->Conversions.size() == R->Conversions.size());
+
+        int leftBetter = 0;
+        for (unsigned I = 0, E = L->Conversions.size(); I != E; ++I) {
+          switch (S.CompareImplicitConversionSequences(L->Conversions[I],
+                                                       R->Conversions[I])) {
+          case ImplicitConversionSequence::Better:
+            leftBetter++;
+            break;
+
+          case ImplicitConversionSequence::Worse:
+            leftBetter--;
+            break;
+
+          case ImplicitConversionSequence::Indistinguishable:
+            break;
+          }
+        }
+        if (leftBetter > 0) return true;
+        if (leftBetter < 0) return false;
+
+      } else if (R->FailureKind == ovl_fail_bad_conversion)
+        return false;
+
+      // TODO: others?
+    }
+
+    // Sort everything else by location.
+    SourceLocation LLoc = GetLocationForCandidate(L);
+    SourceLocation RLoc = GetLocationForCandidate(R);
+
+    // Put candidates without locations (e.g. builtins) at the end.
+    if (LLoc.isInvalid()) return false;
+    if (RLoc.isInvalid()) return true;
+
+    return S.SourceMgr.isBeforeInTranslationUnit(LLoc, RLoc);
+  }
+};
+
+/// CompleteNonViableCandidate - Normally, overload resolution only
+/// computes up to the first
+void CompleteNonViableCandidate(Sema &S, OverloadCandidate *Cand,
+                                Expr **Args, unsigned NumArgs) {
+  assert(!Cand->Viable);
+
+  // Don't do anything on failures other than bad conversion.
+  if (Cand->FailureKind != ovl_fail_bad_conversion) return;
+
+  // Skip forward to the first bad conversion.
+  unsigned ConvIdx = 0;
+  unsigned ConvCount = Cand->Conversions.size();
+  while (true) {
+    assert(ConvIdx != ConvCount && "no bad conversion in candidate");
+    ConvIdx++;
+    if (Cand->Conversions[ConvIdx - 1].isBad())
+      break;
+  }
+
+  if (ConvIdx == ConvCount)
+    return;
+
+  // FIXME: these should probably be preserved from the overload
+  // operation somehow.
+  bool SuppressUserConversions = false;
+  bool ForceRValue = false;
+
+  const FunctionProtoType* Proto;
+  unsigned ArgIdx = ConvIdx;
+
+  if (Cand->IsSurrogate) {
+    QualType ConvType
+      = Cand->Surrogate->getConversionType().getNonReferenceType();
+    if (const PointerType *ConvPtrType = ConvType->getAs<PointerType>())
+      ConvType = ConvPtrType->getPointeeType();
+    Proto = ConvType->getAs<FunctionProtoType>();
+    ArgIdx--;
+  } else if (Cand->Function) {
+    Proto = Cand->Function->getType()->getAs<FunctionProtoType>();
+    if (isa<CXXMethodDecl>(Cand->Function) &&
+        !isa<CXXConstructorDecl>(Cand->Function))
+      ArgIdx--;
+  } else {
+    // Builtin binary operator with a bad first conversion.
+    assert(ConvCount <= 3);
+    for (; ConvIdx != ConvCount; ++ConvIdx)
+      Cand->Conversions[ConvIdx]
+        = S.TryCopyInitialization(Args[ConvIdx],
+                                  Cand->BuiltinTypes.ParamTypes[ConvIdx],
+                                  SuppressUserConversions, ForceRValue,
+                                  /*InOverloadResolution*/ true);
+    return;
+  }
+
+  // Fill in the rest of the conversions.
+  unsigned NumArgsInProto = Proto->getNumArgs();
+  for (; ConvIdx != ConvCount; ++ConvIdx, ++ArgIdx) {
+    if (ArgIdx < NumArgsInProto)
+      Cand->Conversions[ConvIdx]
+        = S.TryCopyInitialization(Args[ArgIdx], Proto->getArgType(ArgIdx),
+                                  SuppressUserConversions, ForceRValue,
+                                  /*InOverloadResolution=*/true);
+    else
+      Cand->Conversions[ConvIdx].setEllipsis();
+  }
+}
+
+} // end anonymous namespace
+
+/// PrintOverloadCandidates - When overload resolution fails, prints
+/// diagnostic messages containing the candidates in the candidate
+/// set.
+void
+Sema::PrintOverloadCandidates(OverloadCandidateSet& CandidateSet,
+                              OverloadCandidateDisplayKind OCD,
+                              Expr **Args, unsigned NumArgs,
+                              const char *Opc,
+                              SourceLocation OpLoc) {
+  // Sort the candidates by viability and position.  Sorting directly would
+  // be prohibitive, so we make a set of pointers and sort those.
+  llvm::SmallVector<OverloadCandidate*, 32> Cands;
+  if (OCD == OCD_AllCandidates) Cands.reserve(CandidateSet.size());
+  for (OverloadCandidateSet::iterator Cand = CandidateSet.begin(),
+                                  LastCand = CandidateSet.end();
+       Cand != LastCand; ++Cand) {
+    if (Cand->Viable)
+      Cands.push_back(Cand);
+    else if (OCD == OCD_AllCandidates) {
+      CompleteNonViableCandidate(*this, Cand, Args, NumArgs);
+      Cands.push_back(Cand);
+    }
+  }
+
+  std::sort(Cands.begin(), Cands.end(),
+            CompareOverloadCandidatesForDisplay(*this));
+  
+  bool ReportedAmbiguousConversions = false;
+
+  llvm::SmallVectorImpl<OverloadCandidate*>::iterator I, E;
+  for (I = Cands.begin(), E = Cands.end(); I != E; ++I) {
+    OverloadCandidate *Cand = *I;
+
+    if (Cand->Function)
+      NoteFunctionCandidate(*this, Cand, Args, NumArgs);
+    else if (Cand->IsSurrogate)
+      NoteSurrogateCandidate(*this, Cand);
+
+    // This a builtin candidate.  We do not, in general, want to list
+    // every possible builtin candidate.
+    else if (Cand->Viable) {
+      // Generally we only see ambiguities including viable builtin
+      // operators if overload resolution got screwed up by an
+      // ambiguous user-defined conversion.
+      //
+      // FIXME: It's quite possible for different conversions to see
+      // different ambiguities, though.
+      if (!ReportedAmbiguousConversions) {
+        NoteAmbiguousUserConversions(*this, OpLoc, Cand);
+        ReportedAmbiguousConversions = true;
+      }
+
+      // If this is a viable builtin, print it.
+      NoteBuiltinOperatorCandidate(*this, Opc, OpLoc, Cand);
+    }
+  }
+}
+
+static bool CheckUnresolvedAccess(Sema &S, OverloadExpr *E, NamedDecl *D,
+                                  AccessSpecifier AS) {
+  if (isa<UnresolvedLookupExpr>(E))
+    return S.CheckUnresolvedLookupAccess(cast<UnresolvedLookupExpr>(E), D, AS);
+
+  return S.CheckUnresolvedMemberAccess(cast<UnresolvedMemberExpr>(E), D, AS);
+}
+
+/// ResolveAddressOfOverloadedFunction - Try to resolve the address of
+/// an overloaded function (C++ [over.over]), where @p From is an
+/// expression with overloaded function type and @p ToType is the type
+/// we're trying to resolve to. For example:
+///
+/// @code
+/// int f(double);
+/// int f(int);
+///
+/// int (*pfd)(double) = f; // selects f(double)
+/// @endcode
+///
+/// This routine returns the resulting FunctionDecl if it could be
+/// resolved, and NULL otherwise. When @p Complain is true, this
+/// routine will emit diagnostics if there is an error.
+FunctionDecl *
+Sema::ResolveAddressOfOverloadedFunction(Expr *From, QualType ToType,
+                                         bool Complain) {
+  QualType FunctionType = ToType;
+  bool IsMember = false;
+  if (const PointerType *ToTypePtr = ToType->getAs<PointerType>())
+    FunctionType = ToTypePtr->getPointeeType();
+  else if (const ReferenceType *ToTypeRef = ToType->getAs<ReferenceType>())
+    FunctionType = ToTypeRef->getPointeeType();
+  else if (const MemberPointerType *MemTypePtr =
+                    ToType->getAs<MemberPointerType>()) {
+    FunctionType = MemTypePtr->getPointeeType();
+    IsMember = true;
+  }
+
+  // We only look at pointers or references to functions.
+  FunctionType = Context.getCanonicalType(FunctionType).getUnqualifiedType();
+  if (!FunctionType->isFunctionType())
+    return 0;
+
+  // Find the actual overloaded function declaration.
+  if (From->getType() != Context.OverloadTy)
+    return 0;
+
+  // C++ [over.over]p1:
+  //   [...] [Note: any redundant set of parentheses surrounding the
+  //   overloaded function name is ignored (5.1). ]
+  // C++ [over.over]p1:
+  //   [...] The overloaded function name can be preceded by the &
+  //   operator.
+  OverloadExpr *OvlExpr = OverloadExpr::find(From).getPointer();
+  TemplateArgumentListInfo ETABuffer, *ExplicitTemplateArgs = 0;
+  if (OvlExpr->hasExplicitTemplateArgs()) {
+    OvlExpr->getExplicitTemplateArgs().copyInto(ETABuffer);
+    ExplicitTemplateArgs = &ETABuffer;
+  }
+
+  // Look through all of the overloaded functions, searching for one
+  // whose type matches exactly.
+  UnresolvedSet<4> Matches;  // contains only FunctionDecls
+  bool FoundNonTemplateFunction = false;
+  for (UnresolvedSetIterator I = OvlExpr->decls_begin(),
+         E = OvlExpr->decls_end(); I != E; ++I) {
+    // Look through any using declarations to find the underlying function.
+    NamedDecl *Fn = (*I)->getUnderlyingDecl();
+
+    // C++ [over.over]p3:
+    //   Non-member functions and static member functions match
+    //   targets of type "pointer-to-function" or "reference-to-function."
+    //   Nonstatic member functions match targets of
+    //   type "pointer-to-member-function."
+    // Note that according to DR 247, the containing class does not matter.
+
+    if (FunctionTemplateDecl *FunctionTemplate
+          = dyn_cast<FunctionTemplateDecl>(Fn)) {
+      if (CXXMethodDecl *Method
+            = dyn_cast<CXXMethodDecl>(FunctionTemplate->getTemplatedDecl())) {
+        // Skip non-static function templates when converting to pointer, and
+        // static when converting to member pointer.
+        if (Method->isStatic() == IsMember)
+          continue;
+      } else if (IsMember)
+        continue;
+
+      // C++ [over.over]p2:
+      //   If the name is a function template, template argument deduction is
+      //   done (14.8.2.2), and if the argument deduction succeeds, the
+      //   resulting template argument list is used to generate a single
+      //   function template specialization, which is added to the set of
+      //   overloaded functions considered.
+      // FIXME: We don't really want to build the specialization here, do we?
+      FunctionDecl *Specialization = 0;
+      TemplateDeductionInfo Info(Context, OvlExpr->getNameLoc());
+      if (TemplateDeductionResult Result
+            = DeduceTemplateArguments(FunctionTemplate, ExplicitTemplateArgs,
+                                      FunctionType, Specialization, Info)) {
+        // FIXME: make a note of the failed deduction for diagnostics.
+        (void)Result;
+      } else {
+        // FIXME: If the match isn't exact, shouldn't we just drop this as
+        // a candidate? Find a testcase before changing the code.
+        assert(FunctionType
+                 == Context.getCanonicalType(Specialization->getType()));
+        Matches.addDecl(cast<FunctionDecl>(Specialization->getCanonicalDecl()),
+                        I.getAccess());
+      }
+
+      continue;
+    }
+
+    if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(Fn)) {
+      // Skip non-static functions when converting to pointer, and static
+      // when converting to member pointer.
+      if (Method->isStatic() == IsMember)
+        continue;
+      
+      // If we have explicit template arguments, skip non-templates.
+      if (OvlExpr->hasExplicitTemplateArgs())
+        continue;
+    } else if (IsMember)
+      continue;
+
+    if (FunctionDecl *FunDecl = dyn_cast<FunctionDecl>(Fn)) {
+      QualType ResultTy;
+      if (Context.hasSameUnqualifiedType(FunctionType, FunDecl->getType()) ||
+          IsNoReturnConversion(Context, FunDecl->getType(), FunctionType, 
+                               ResultTy)) {
+        Matches.addDecl(cast<FunctionDecl>(FunDecl->getCanonicalDecl()),
+                        I.getAccess());
+        FoundNonTemplateFunction = true;
+      }
+    }
+  }
+
+  // If there were 0 or 1 matches, we're done.
+  if (Matches.empty())
+    return 0;
+  else if (Matches.size() == 1) {
+    FunctionDecl *Result = cast<FunctionDecl>(*Matches.begin());
+    MarkDeclarationReferenced(From->getLocStart(), Result);
+    if (Complain)
+      CheckUnresolvedAccess(*this, OvlExpr, Result, Matches.begin().getAccess());
+    return Result;
+  }
+
+  // C++ [over.over]p4:
+  //   If more than one function is selected, [...]
+  if (!FoundNonTemplateFunction) {
+    //   [...] and any given function template specialization F1 is
+    //   eliminated if the set contains a second function template
+    //   specialization whose function template is more specialized
+    //   than the function template of F1 according to the partial
+    //   ordering rules of 14.5.5.2.
+
+    // The algorithm specified above is quadratic. We instead use a
+    // two-pass algorithm (similar to the one used to identify the
+    // best viable function in an overload set) that identifies the
+    // best function template (if it exists).
+    
+    UnresolvedSetIterator Result =
+        getMostSpecialized(Matches.begin(), Matches.end(),
+                           TPOC_Other, From->getLocStart(),
+                           PDiag(),
+                           PDiag(diag::err_addr_ovl_ambiguous)
+                               << Matches[0]->getDeclName(),
+                           PDiag(diag::note_ovl_candidate)
+                               << (unsigned) oc_function_template);
+    assert(Result != Matches.end() && "no most-specialized template");
+    MarkDeclarationReferenced(From->getLocStart(), *Result);
+    if (Complain)
+      CheckUnresolvedAccess(*this, OvlExpr, *Result, Result.getAccess());
+    return cast<FunctionDecl>(*Result);
+  }
+
+  //   [...] any function template specializations in the set are
+  //   eliminated if the set also contains a non-template function, [...]
+  for (unsigned I = 0, N = Matches.size(); I != N; ) {
+    if (cast<FunctionDecl>(Matches[I].getDecl())->getPrimaryTemplate() == 0)
+      ++I;
+    else {
+      Matches.erase(I);
+      --N;
+    }
+  }
+  
+  // [...] After such eliminations, if any, there shall remain exactly one
+  // selected function.
+  if (Matches.size() == 1) {
+    UnresolvedSetIterator Match = Matches.begin();
+    MarkDeclarationReferenced(From->getLocStart(), *Match);
+    if (Complain)
+      CheckUnresolvedAccess(*this, OvlExpr, *Match, Match.getAccess());
+    return cast<FunctionDecl>(*Match);
+  }
+
+  // FIXME: We should probably return the same thing that BestViableFunction
+  // returns (even if we issue the diagnostics here).
+  Diag(From->getLocStart(), diag::err_addr_ovl_ambiguous)
+    << Matches[0]->getDeclName();
+  for (UnresolvedSetIterator I = Matches.begin(),
+         E = Matches.end(); I != E; ++I)
+    NoteOverloadCandidate(cast<FunctionDecl>(*I));
+  return 0;
+}
+
+/// \brief Given an expression that refers to an overloaded function, try to 
+/// resolve that overloaded function expression down to a single function.
+///
+/// This routine can only resolve template-ids that refer to a single function
+/// template, where that template-id refers to a single template whose template
+/// arguments are either provided by the template-id or have defaults, 
+/// as described in C++0x [temp.arg.explicit]p3.
+FunctionDecl *Sema::ResolveSingleFunctionTemplateSpecialization(Expr *From) {
+  // C++ [over.over]p1:
+  //   [...] [Note: any redundant set of parentheses surrounding the
+  //   overloaded function name is ignored (5.1). ]
+  // C++ [over.over]p1:
+  //   [...] The overloaded function name can be preceded by the &
+  //   operator.
+
+  if (From->getType() != Context.OverloadTy)
+    return 0;
+
+  OverloadExpr *OvlExpr = OverloadExpr::find(From).getPointer();
+  
+  // If we didn't actually find any template-ids, we're done.
+  if (!OvlExpr->hasExplicitTemplateArgs())
+    return 0;
+
+  TemplateArgumentListInfo ExplicitTemplateArgs;
+  OvlExpr->getExplicitTemplateArgs().copyInto(ExplicitTemplateArgs);
+  
+  // Look through all of the overloaded functions, searching for one
+  // whose type matches exactly.
+  FunctionDecl *Matched = 0;
+  for (UnresolvedSetIterator I = OvlExpr->decls_begin(),
+         E = OvlExpr->decls_end(); I != E; ++I) {
+    // C++0x [temp.arg.explicit]p3:
+    //   [...] In contexts where deduction is done and fails, or in contexts
+    //   where deduction is not done, if a template argument list is 
+    //   specified and it, along with any default template arguments, 
+    //   identifies a single function template specialization, then the 
+    //   template-id is an lvalue for the function template specialization.
+    FunctionTemplateDecl *FunctionTemplate = cast<FunctionTemplateDecl>(*I);
+    
+    // C++ [over.over]p2:
+    //   If the name is a function template, template argument deduction is
+    //   done (14.8.2.2), and if the argument deduction succeeds, the
+    //   resulting template argument list is used to generate a single
+    //   function template specialization, which is added to the set of
+    //   overloaded functions considered.
+    FunctionDecl *Specialization = 0;
+    TemplateDeductionInfo Info(Context, OvlExpr->getNameLoc());
+    if (TemplateDeductionResult Result
+          = DeduceTemplateArguments(FunctionTemplate, &ExplicitTemplateArgs,
+                                    Specialization, Info)) {
+      // FIXME: make a note of the failed deduction for diagnostics.
+      (void)Result;
+      continue;
+    } 
+    
+    // Multiple matches; we can't resolve to a single declaration.
+    if (Matched)
+      return 0;
+
+    Matched = Specialization;
+  }
+
+  return Matched;
+}
+    
+/// \brief Add a single candidate to the overload set.
+static void AddOverloadedCallCandidate(Sema &S,
+                                       NamedDecl *Callee,
+                                       AccessSpecifier Access,
+                       const TemplateArgumentListInfo *ExplicitTemplateArgs,
+                                       Expr **Args, unsigned NumArgs,
+                                       OverloadCandidateSet &CandidateSet,
+                                       bool PartialOverloading) {
+  if (isa<UsingShadowDecl>(Callee))
+    Callee = cast<UsingShadowDecl>(Callee)->getTargetDecl();
+
+  if (FunctionDecl *Func = dyn_cast<FunctionDecl>(Callee)) {
+    assert(!ExplicitTemplateArgs && "Explicit template arguments?");
+    S.AddOverloadCandidate(Func, Access, Args, NumArgs, CandidateSet,
+                           false, false, PartialOverloading);
+    return;
+  }
+
+  if (FunctionTemplateDecl *FuncTemplate
+      = dyn_cast<FunctionTemplateDecl>(Callee)) {
+    S.AddTemplateOverloadCandidate(FuncTemplate, Access, ExplicitTemplateArgs,
+                                   Args, NumArgs, CandidateSet);
+    return;
+  }
+
+  assert(false && "unhandled case in overloaded call candidate");
+
+  // do nothing?
+}
+  
+/// \brief Add the overload candidates named by callee and/or found by argument
+/// dependent lookup to the given overload set.
+void Sema::AddOverloadedCallCandidates(UnresolvedLookupExpr *ULE,
+                                       Expr **Args, unsigned NumArgs,
+                                       OverloadCandidateSet &CandidateSet,
+                                       bool PartialOverloading) {
+
+#ifndef NDEBUG
+  // Verify that ArgumentDependentLookup is consistent with the rules
+  // in C++0x [basic.lookup.argdep]p3:
+  //
+  //   Let X be the lookup set produced by unqualified lookup (3.4.1)
+  //   and let Y be the lookup set produced by argument dependent
+  //   lookup (defined as follows). If X contains
+  //
+  //     -- a declaration of a class member, or
+  //
+  //     -- a block-scope function declaration that is not a
+  //        using-declaration, or
+  //
+  //     -- a declaration that is neither a function or a function
+  //        template
+  //
+  //   then Y is empty.
+
+  if (ULE->requiresADL()) {
+    for (UnresolvedLookupExpr::decls_iterator I = ULE->decls_begin(),
+           E = ULE->decls_end(); I != E; ++I) {
+      assert(!(*I)->getDeclContext()->isRecord());
+      assert(isa<UsingShadowDecl>(*I) ||
+             !(*I)->getDeclContext()->isFunctionOrMethod());
+      assert((*I)->getUnderlyingDecl()->isFunctionOrFunctionTemplate());
+    }
+  }
+#endif
+
+  // It would be nice to avoid this copy.
+  TemplateArgumentListInfo TABuffer;
+  const TemplateArgumentListInfo *ExplicitTemplateArgs = 0;
+  if (ULE->hasExplicitTemplateArgs()) {
+    ULE->copyTemplateArgumentsInto(TABuffer);
+    ExplicitTemplateArgs = &TABuffer;
+  }
+
+  for (UnresolvedLookupExpr::decls_iterator I = ULE->decls_begin(),
+         E = ULE->decls_end(); I != E; ++I)
+    AddOverloadedCallCandidate(*this, *I, I.getAccess(), ExplicitTemplateArgs,
+                               Args, NumArgs, CandidateSet, 
+                               PartialOverloading);
+
+  if (ULE->requiresADL())
+    AddArgumentDependentLookupCandidates(ULE->getName(), /*Operator*/ false,
+                                         Args, NumArgs,
+                                         ExplicitTemplateArgs,
+                                         CandidateSet,
+                                         PartialOverloading);  
+}
+
+static Sema::OwningExprResult Destroy(Sema &SemaRef, Expr *Fn,
+                                      Expr **Args, unsigned NumArgs) {
+  Fn->Destroy(SemaRef.Context);
+  for (unsigned Arg = 0; Arg < NumArgs; ++Arg)
+    Args[Arg]->Destroy(SemaRef.Context);
+  return SemaRef.ExprError();
+}
+
+/// Attempts to recover from a call where no functions were found.
+///
+/// Returns true if new candidates were found.
+static Sema::OwningExprResult
+BuildRecoveryCallExpr(Sema &SemaRef, Expr *Fn,
+                      UnresolvedLookupExpr *ULE,
+                      SourceLocation LParenLoc,
+                      Expr **Args, unsigned NumArgs,
+                      SourceLocation *CommaLocs,
+                      SourceLocation RParenLoc) {
+
+  CXXScopeSpec SS;
+  if (ULE->getQualifier()) {
+    SS.setScopeRep(ULE->getQualifier());
+    SS.setRange(ULE->getQualifierRange());
+  }
+
+  TemplateArgumentListInfo TABuffer;
+  const TemplateArgumentListInfo *ExplicitTemplateArgs = 0;
+  if (ULE->hasExplicitTemplateArgs()) {
+    ULE->copyTemplateArgumentsInto(TABuffer);
+    ExplicitTemplateArgs = &TABuffer;
+  }
+
+  LookupResult R(SemaRef, ULE->getName(), ULE->getNameLoc(),
+                 Sema::LookupOrdinaryName);
+  if (SemaRef.DiagnoseEmptyLookup(/*Scope=*/0, SS, R))
+    return Destroy(SemaRef, Fn, Args, NumArgs);
+
+  assert(!R.empty() && "lookup results empty despite recovery");
+
+  // Build an implicit member call if appropriate.  Just drop the
+  // casts and such from the call, we don't really care.
+  Sema::OwningExprResult NewFn = SemaRef.ExprError();
+  if ((*R.begin())->isCXXClassMember())
+    NewFn = SemaRef.BuildPossibleImplicitMemberExpr(SS, R, ExplicitTemplateArgs);
+  else if (ExplicitTemplateArgs)
+    NewFn = SemaRef.BuildTemplateIdExpr(SS, R, false, *ExplicitTemplateArgs);
+  else
+    NewFn = SemaRef.BuildDeclarationNameExpr(SS, R, false);
+
+  if (NewFn.isInvalid())
+    return Destroy(SemaRef, Fn, Args, NumArgs);
+
+  Fn->Destroy(SemaRef.Context);
+
+  // This shouldn't cause an infinite loop because we're giving it
+  // an expression with non-empty lookup results, which should never
+  // end up here.
+  return SemaRef.ActOnCallExpr(/*Scope*/ 0, move(NewFn), LParenLoc,
+                         Sema::MultiExprArg(SemaRef, (void**) Args, NumArgs),
+                               CommaLocs, RParenLoc);
+}
+  
+/// ResolveOverloadedCallFn - Given the call expression that calls Fn
+/// (which eventually refers to the declaration Func) and the call
+/// arguments Args/NumArgs, attempt to resolve the function call down
+/// to a specific function. If overload resolution succeeds, returns
+/// the function declaration produced by overload
+/// resolution. Otherwise, emits diagnostics, deletes all of the
+/// arguments and Fn, and returns NULL.
+Sema::OwningExprResult
+Sema::BuildOverloadedCallExpr(Expr *Fn, UnresolvedLookupExpr *ULE,
+                              SourceLocation LParenLoc,
+                              Expr **Args, unsigned NumArgs,
+                              SourceLocation *CommaLocs,
+                              SourceLocation RParenLoc) {
+#ifndef NDEBUG
+  if (ULE->requiresADL()) {
+    // To do ADL, we must have found an unqualified name.
+    assert(!ULE->getQualifier() && "qualified name with ADL");
+
+    // We don't perform ADL for implicit declarations of builtins.
+    // Verify that this was correctly set up.
+    FunctionDecl *F;
+    if (ULE->decls_begin() + 1 == ULE->decls_end() &&
+        (F = dyn_cast<FunctionDecl>(*ULE->decls_begin())) &&
+        F->getBuiltinID() && F->isImplicit())
+      assert(0 && "performing ADL for builtin");
+      
+    // We don't perform ADL in C.
+    assert(getLangOptions().CPlusPlus && "ADL enabled in C");
+  }
+#endif
+
+  OverloadCandidateSet CandidateSet(Fn->getExprLoc());
+
+  // Add the functions denoted by the callee to the set of candidate
+  // functions, including those from argument-dependent lookup.
+  AddOverloadedCallCandidates(ULE, Args, NumArgs, CandidateSet);
+
+  // If we found nothing, try to recover.
+  // AddRecoveryCallCandidates diagnoses the error itself, so we just
+  // bailout out if it fails.
+  if (CandidateSet.empty())
+    return BuildRecoveryCallExpr(*this, Fn, ULE, LParenLoc, Args, NumArgs,
+                                 CommaLocs, RParenLoc);
+
+  OverloadCandidateSet::iterator Best;
+  switch (BestViableFunction(CandidateSet, Fn->getLocStart(), Best)) {
+  case OR_Success: {
+    FunctionDecl *FDecl = Best->Function;
+    CheckUnresolvedLookupAccess(ULE, FDecl, Best->getAccess());
+    Fn = FixOverloadedFunctionReference(Fn, FDecl);
+    return BuildResolvedCallExpr(Fn, FDecl, LParenLoc, Args, NumArgs, RParenLoc);
+  }
+
+  case OR_No_Viable_Function:
+    Diag(Fn->getSourceRange().getBegin(),
+         diag::err_ovl_no_viable_function_in_call)
+      << ULE->getName() << Fn->getSourceRange();
+    PrintOverloadCandidates(CandidateSet, OCD_AllCandidates, Args, NumArgs);
+    break;
+
+  case OR_Ambiguous:
+    Diag(Fn->getSourceRange().getBegin(), diag::err_ovl_ambiguous_call)
+      << ULE->getName() << Fn->getSourceRange();
+    PrintOverloadCandidates(CandidateSet, OCD_ViableCandidates, Args, NumArgs);
+    break;
+
+  case OR_Deleted:
+    Diag(Fn->getSourceRange().getBegin(), diag::err_ovl_deleted_call)
+      << Best->Function->isDeleted()
+      << ULE->getName()
+      << Fn->getSourceRange();
+    PrintOverloadCandidates(CandidateSet, OCD_AllCandidates, Args, NumArgs);
+    break;
+  }
+
+  // Overload resolution failed. Destroy all of the subexpressions and
+  // return NULL.
+  Fn->Destroy(Context);
+  for (unsigned Arg = 0; Arg < NumArgs; ++Arg)
+    Args[Arg]->Destroy(Context);
+  return ExprError();
+}
+
+static bool IsOverloaded(const UnresolvedSetImpl &Functions) {
+  return Functions.size() > 1 ||
+    (Functions.size() == 1 && isa<FunctionTemplateDecl>(*Functions.begin()));
+}
+
+/// \brief Create a unary operation that may resolve to an overloaded
+/// operator.
+///
+/// \param OpLoc The location of the operator itself (e.g., '*').
+///
+/// \param OpcIn The UnaryOperator::Opcode that describes this
+/// operator.
+///
+/// \param Functions The set of non-member functions that will be
+/// considered by overload resolution. The caller needs to build this
+/// set based on the context using, e.g.,
+/// LookupOverloadedOperatorName() and ArgumentDependentLookup(). This
+/// set should not contain any member functions; those will be added
+/// by CreateOverloadedUnaryOp().
+///
+/// \param input The input argument.
+Sema::OwningExprResult
+Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, unsigned OpcIn,
+                              const UnresolvedSetImpl &Fns,
+                              ExprArg input) {
+  UnaryOperator::Opcode Opc = static_cast<UnaryOperator::Opcode>(OpcIn);
+  Expr *Input = (Expr *)input.get();
+
+  OverloadedOperatorKind Op = UnaryOperator::getOverloadedOperator(Opc);
+  assert(Op != OO_None && "Invalid opcode for overloaded unary operator");
+  DeclarationName OpName = Context.DeclarationNames.getCXXOperatorName(Op);
+
+  Expr *Args[2] = { Input, 0 };
+  unsigned NumArgs = 1;
+
+  // For post-increment and post-decrement, add the implicit '0' as
+  // the second argument, so that we know this is a post-increment or
+  // post-decrement.
+  if (Opc == UnaryOperator::PostInc || Opc == UnaryOperator::PostDec) {
+    llvm::APSInt Zero(Context.getTypeSize(Context.IntTy), false);
+    Args[1] = new (Context) IntegerLiteral(Zero, Context.IntTy,
+                                           SourceLocation());
+    NumArgs = 2;
+  }
+
+  if (Input->isTypeDependent()) {
+    CXXRecordDecl *NamingClass = 0; // because lookup ignores member operators
+    UnresolvedLookupExpr *Fn
+      = UnresolvedLookupExpr::Create(Context, /*Dependent*/ true, NamingClass,
+                                     0, SourceRange(), OpName, OpLoc,
+                                     /*ADL*/ true, IsOverloaded(Fns));
+    Fn->addDecls(Fns.begin(), Fns.end());
+
+    input.release();
+    return Owned(new (Context) CXXOperatorCallExpr(Context, Op, Fn,
+                                                   &Args[0], NumArgs,
+                                                   Context.DependentTy,
+                                                   OpLoc));
+  }
+
+  // Build an empty overload set.
+  OverloadCandidateSet CandidateSet(OpLoc);
+
+  // Add the candidates from the given function set.
+  AddFunctionCandidates(Fns, &Args[0], NumArgs, CandidateSet, false);
+
+  // Add operator candidates that are member functions.
+  AddMemberOperatorCandidates(Op, OpLoc, &Args[0], NumArgs, CandidateSet);
+
+  // Add candidates from ADL.
+  AddArgumentDependentLookupCandidates(OpName, /*Operator*/ true,
+                                       Args, NumArgs,
+                                       /*ExplicitTemplateArgs*/ 0,
+                                       CandidateSet);
+
+  // Add builtin operator candidates.
+  AddBuiltinOperatorCandidates(Op, OpLoc, &Args[0], NumArgs, CandidateSet);
+
+  // Perform overload resolution.
+  OverloadCandidateSet::iterator Best;
+  switch (BestViableFunction(CandidateSet, OpLoc, Best)) {
+  case OR_Success: {
+    // We found a built-in operator or an overloaded operator.
+    FunctionDecl *FnDecl = Best->Function;
+
+    if (FnDecl) {
+      // We matched an overloaded operator. Build a call to that
+      // operator.
+
+      // Convert the arguments.
+      if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(FnDecl)) {
+        CheckMemberOperatorAccess(OpLoc, Args[0], Method, Best->getAccess());
+
+        if (PerformObjectArgumentInitialization(Input, Method))
+          return ExprError();
+      } else {
+        // Convert the arguments.
+        OwningExprResult InputInit
+          = PerformCopyInitialization(InitializedEntity::InitializeParameter(
+                                                      FnDecl->getParamDecl(0)),
+                                      SourceLocation(), 
+                                      move(input));
+        if (InputInit.isInvalid())
+          return ExprError();
+        
+        input = move(InputInit);
+        Input = (Expr *)input.get();
+      }
+
+      // Determine the result type
+      QualType ResultTy = FnDecl->getResultType().getNonReferenceType();
+
+      // Build the actual expression node.
+      Expr *FnExpr = new (Context) DeclRefExpr(FnDecl, FnDecl->getType(),
+                                               SourceLocation());
+      UsualUnaryConversions(FnExpr);
+
+      input.release();
+      Args[0] = Input;
+      ExprOwningPtr<CallExpr> TheCall(this,
+        new (Context) CXXOperatorCallExpr(Context, Op, FnExpr,
+                                          Args, NumArgs, ResultTy, OpLoc));
+      
+      if (CheckCallReturnType(FnDecl->getResultType(), OpLoc, TheCall.get(), 
+                              FnDecl))
+        return ExprError();
+
+      return MaybeBindToTemporary(TheCall.release());
+    } else {
+      // We matched a built-in operator. Convert the arguments, then
+      // break out so that we will build the appropriate built-in
+      // operator node.
+        if (PerformImplicitConversion(Input, Best->BuiltinTypes.ParamTypes[0],
+                                      Best->Conversions[0], AA_Passing))
+          return ExprError();
+
+        break;
+      }
+    }
+
+    case OR_No_Viable_Function:
+      // No viable function; fall through to handling this as a
+      // built-in operator, which will produce an error message for us.
+      break;
+
+    case OR_Ambiguous:
+      Diag(OpLoc,  diag::err_ovl_ambiguous_oper)
+          << UnaryOperator::getOpcodeStr(Opc)
+          << Input->getSourceRange();
+      PrintOverloadCandidates(CandidateSet, OCD_ViableCandidates, Args, NumArgs,
+                              UnaryOperator::getOpcodeStr(Opc), OpLoc);
+      return ExprError();
+
+    case OR_Deleted:
+      Diag(OpLoc, diag::err_ovl_deleted_oper)
+        << Best->Function->isDeleted()
+        << UnaryOperator::getOpcodeStr(Opc)
+        << Input->getSourceRange();
+      PrintOverloadCandidates(CandidateSet, OCD_AllCandidates, Args, NumArgs);
+      return ExprError();
+    }
+
+  // Either we found no viable overloaded operator or we matched a
+  // built-in operator. In either case, fall through to trying to
+  // build a built-in operation.
+  input.release();
+  return CreateBuiltinUnaryOp(OpLoc, Opc, Owned(Input));
+}
+
+/// \brief Create a binary operation that may resolve to an overloaded
+/// operator.
+///
+/// \param OpLoc The location of the operator itself (e.g., '+').
+///
+/// \param OpcIn The BinaryOperator::Opcode that describes this
+/// operator.
+///
+/// \param Functions The set of non-member functions that will be
+/// considered by overload resolution. The caller needs to build this
+/// set based on the context using, e.g.,
+/// LookupOverloadedOperatorName() and ArgumentDependentLookup(). This
+/// set should not contain any member functions; those will be added
+/// by CreateOverloadedBinOp().
+///
+/// \param LHS Left-hand argument.
+/// \param RHS Right-hand argument.
+Sema::OwningExprResult
+Sema::CreateOverloadedBinOp(SourceLocation OpLoc,
+                            unsigned OpcIn,
+                            const UnresolvedSetImpl &Fns,
+                            Expr *LHS, Expr *RHS) {
+  Expr *Args[2] = { LHS, RHS };
+  LHS=RHS=0; //Please use only Args instead of LHS/RHS couple
+
+  BinaryOperator::Opcode Opc = static_cast<BinaryOperator::Opcode>(OpcIn);
+  OverloadedOperatorKind Op = BinaryOperator::getOverloadedOperator(Opc);
+  DeclarationName OpName = Context.DeclarationNames.getCXXOperatorName(Op);
+
+  // If either side is type-dependent, create an appropriate dependent
+  // expression.
+  if (Args[0]->isTypeDependent() || Args[1]->isTypeDependent()) {
+    if (Fns.empty()) {
+      // If there are no functions to store, just build a dependent 
+      // BinaryOperator or CompoundAssignment.
+      if (Opc <= BinaryOperator::Assign || Opc > BinaryOperator::OrAssign)
+        return Owned(new (Context) BinaryOperator(Args[0], Args[1], Opc,
+                                                  Context.DependentTy, OpLoc));
+      
+      return Owned(new (Context) CompoundAssignOperator(Args[0], Args[1], Opc,
+                                                        Context.DependentTy,
+                                                        Context.DependentTy,
+                                                        Context.DependentTy,
+                                                        OpLoc));
+    }
+
+    // FIXME: save results of ADL from here?
+    CXXRecordDecl *NamingClass = 0; // because lookup ignores member operators
+    UnresolvedLookupExpr *Fn
+      = UnresolvedLookupExpr::Create(Context, /*Dependent*/ true, NamingClass,
+                                     0, SourceRange(), OpName, OpLoc,
+                                     /*ADL*/ true, IsOverloaded(Fns));
+
+    Fn->addDecls(Fns.begin(), Fns.end());
+    return Owned(new (Context) CXXOperatorCallExpr(Context, Op, Fn,
+                                                   Args, 2,
+                                                   Context.DependentTy,
+                                                   OpLoc));
+  }
+
+  // If this is the .* operator, which is not overloadable, just
+  // create a built-in binary operator.
+  if (Opc == BinaryOperator::PtrMemD)
+    return CreateBuiltinBinOp(OpLoc, Opc, Args[0], Args[1]);
+
+  // If this is the assignment operator, we only perform overload resolution
+  // if the left-hand side is a class or enumeration type. This is actually
+  // a hack. The standard requires that we do overload resolution between the
+  // various built-in candidates, but as DR507 points out, this can lead to
+  // problems. So we do it this way, which pretty much follows what GCC does.
+  // Note that we go the traditional code path for compound assignment forms.
+  if (Opc==BinaryOperator::Assign && !Args[0]->getType()->isOverloadableType())
+    return CreateBuiltinBinOp(OpLoc, Opc, Args[0], Args[1]);
+
+  // Build an empty overload set.
+  OverloadCandidateSet CandidateSet(OpLoc);
+
+  // Add the candidates from the given function set.
+  AddFunctionCandidates(Fns, Args, 2, CandidateSet, false);
+
+  // Add operator candidates that are member functions.
+  AddMemberOperatorCandidates(Op, OpLoc, Args, 2, CandidateSet);
+
+  // Add candidates from ADL.
+  AddArgumentDependentLookupCandidates(OpName, /*Operator*/ true,
+                                       Args, 2,
+                                       /*ExplicitTemplateArgs*/ 0,
+                                       CandidateSet);
+
+  // Add builtin operator candidates.
+  AddBuiltinOperatorCandidates(Op, OpLoc, Args, 2, CandidateSet);
+
+  // Perform overload resolution.
+  OverloadCandidateSet::iterator Best;
+  switch (BestViableFunction(CandidateSet, OpLoc, Best)) {
+    case OR_Success: {
+      // We found a built-in operator or an overloaded operator.
+      FunctionDecl *FnDecl = Best->Function;
+
+      if (FnDecl) {
+        // We matched an overloaded operator. Build a call to that
+        // operator.
+
+        // Convert the arguments.
+        if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(FnDecl)) {
+          // Best->Access is only meaningful for class members.
+          CheckMemberOperatorAccess(OpLoc, Args[0], Method, Best->getAccess());
+
+          OwningExprResult Arg1
+            = PerformCopyInitialization(
+                                        InitializedEntity::InitializeParameter(
+                                                        FnDecl->getParamDecl(0)),
+                                        SourceLocation(),
+                                        Owned(Args[1]));
+          if (Arg1.isInvalid())
+            return ExprError();
+
+          if (PerformObjectArgumentInitialization(Args[0], Method))
+            return ExprError();
+
+          Args[1] = RHS = Arg1.takeAs<Expr>();
+        } else {
+          // Convert the arguments.
+          OwningExprResult Arg0
+            = PerformCopyInitialization(
+                                        InitializedEntity::InitializeParameter(
+                                                        FnDecl->getParamDecl(0)),
+                                        SourceLocation(),
+                                        Owned(Args[0]));
+          if (Arg0.isInvalid())
+            return ExprError();
+
+          OwningExprResult Arg1
+            = PerformCopyInitialization(
+                                        InitializedEntity::InitializeParameter(
+                                                        FnDecl->getParamDecl(1)),
+                                        SourceLocation(),
+                                        Owned(Args[1]));
+          if (Arg1.isInvalid())
+            return ExprError();
+          Args[0] = LHS = Arg0.takeAs<Expr>();
+          Args[1] = RHS = Arg1.takeAs<Expr>();
+        }
+
+        // Determine the result type
+        QualType ResultTy
+          = FnDecl->getType()->getAs<FunctionType>()->getResultType();
+        ResultTy = ResultTy.getNonReferenceType();
+
+        // Build the actual expression node.
+        Expr *FnExpr = new (Context) DeclRefExpr(FnDecl, FnDecl->getType(),
+                                                 OpLoc);
+        UsualUnaryConversions(FnExpr);
+
+        ExprOwningPtr<CXXOperatorCallExpr> 
+          TheCall(this, new (Context) CXXOperatorCallExpr(Context, Op, FnExpr,
+                                                          Args, 2, ResultTy, 
+                                                          OpLoc));
+        
+        if (CheckCallReturnType(FnDecl->getResultType(), OpLoc, TheCall.get(), 
+                                FnDecl))
+          return ExprError();
+
+        return MaybeBindToTemporary(TheCall.release());
+      } else {
+        // We matched a built-in operator. Convert the arguments, then
+        // break out so that we will build the appropriate built-in
+        // operator node.
+        if (PerformImplicitConversion(Args[0], Best->BuiltinTypes.ParamTypes[0],
+                                      Best->Conversions[0], AA_Passing) ||
+            PerformImplicitConversion(Args[1], Best->BuiltinTypes.ParamTypes[1],
+                                      Best->Conversions[1], AA_Passing))
+          return ExprError();
+
+        break;
+      }
+    }
+
+    case OR_No_Viable_Function: {
+      // C++ [over.match.oper]p9:
+      //   If the operator is the operator , [...] and there are no
+      //   viable functions, then the operator is assumed to be the
+      //   built-in operator and interpreted according to clause 5.
+      if (Opc == BinaryOperator::Comma)
+        break;
+
+      // For class as left operand for assignment or compound assigment operator
+      // do not fall through to handling in built-in, but report that no overloaded
+      // assignment operator found
+      OwningExprResult Result = ExprError();
+      if (Args[0]->getType()->isRecordType() && 
+          Opc >= BinaryOperator::Assign && Opc <= BinaryOperator::OrAssign) {
+        Diag(OpLoc,  diag::err_ovl_no_viable_oper)
+             << BinaryOperator::getOpcodeStr(Opc)
+             << Args[0]->getSourceRange() << Args[1]->getSourceRange();
+      } else {
+        // No viable function; try to create a built-in operation, which will
+        // produce an error. Then, show the non-viable candidates.
+        Result = CreateBuiltinBinOp(OpLoc, Opc, Args[0], Args[1]);
+      }
+      assert(Result.isInvalid() && 
+             "C++ binary operator overloading is missing candidates!");
+      if (Result.isInvalid())
+        PrintOverloadCandidates(CandidateSet, OCD_AllCandidates, Args, 2,
+                                BinaryOperator::getOpcodeStr(Opc), OpLoc);
+      return move(Result);
+    }
+
+    case OR_Ambiguous:
+      Diag(OpLoc,  diag::err_ovl_ambiguous_oper)
+          << BinaryOperator::getOpcodeStr(Opc)
+          << Args[0]->getSourceRange() << Args[1]->getSourceRange();
+      PrintOverloadCandidates(CandidateSet, OCD_ViableCandidates, Args, 2,
+                              BinaryOperator::getOpcodeStr(Opc), OpLoc);
+      return ExprError();
+
+    case OR_Deleted:
+      Diag(OpLoc, diag::err_ovl_deleted_oper)
+        << Best->Function->isDeleted()
+        << BinaryOperator::getOpcodeStr(Opc)
+        << Args[0]->getSourceRange() << Args[1]->getSourceRange();
+      PrintOverloadCandidates(CandidateSet, OCD_AllCandidates, Args, 2);
+      return ExprError();
+  }
+
+  // We matched a built-in operator; build it.
+  return CreateBuiltinBinOp(OpLoc, Opc, Args[0], Args[1]);
+}
+
+Action::OwningExprResult
+Sema::CreateOverloadedArraySubscriptExpr(SourceLocation LLoc,
+                                         SourceLocation RLoc,
+                                         ExprArg Base, ExprArg Idx) {
+  Expr *Args[2] = { static_cast<Expr*>(Base.get()),
+                    static_cast<Expr*>(Idx.get()) };
+  DeclarationName OpName =
+      Context.DeclarationNames.getCXXOperatorName(OO_Subscript);
+
+  // If either side is type-dependent, create an appropriate dependent
+  // expression.
+  if (Args[0]->isTypeDependent() || Args[1]->isTypeDependent()) {
+
+    CXXRecordDecl *NamingClass = 0; // because lookup ignores member operators
+    UnresolvedLookupExpr *Fn
+      = UnresolvedLookupExpr::Create(Context, /*Dependent*/ true, NamingClass,
+                                     0, SourceRange(), OpName, LLoc,
+                                     /*ADL*/ true, /*Overloaded*/ false);
+    // Can't add any actual overloads yet
+
+    Base.release();
+    Idx.release();
+    return Owned(new (Context) CXXOperatorCallExpr(Context, OO_Subscript, Fn,
+                                                   Args, 2,
+                                                   Context.DependentTy,
+                                                   RLoc));
+  }
+
+  // Build an empty overload set.
+  OverloadCandidateSet CandidateSet(LLoc);
+
+  // Subscript can only be overloaded as a member function.
+
+  // Add operator candidates that are member functions.
+  AddMemberOperatorCandidates(OO_Subscript, LLoc, Args, 2, CandidateSet);
+
+  // Add builtin operator candidates.
+  AddBuiltinOperatorCandidates(OO_Subscript, LLoc, Args, 2, CandidateSet);
+
+  // Perform overload resolution.
+  OverloadCandidateSet::iterator Best;
+  switch (BestViableFunction(CandidateSet, LLoc, Best)) {
+    case OR_Success: {
+      // We found a built-in operator or an overloaded operator.
+      FunctionDecl *FnDecl = Best->Function;
+
+      if (FnDecl) {
+        // We matched an overloaded operator. Build a call to that
+        // operator.
+
+        CheckMemberOperatorAccess(LLoc, Args[0], FnDecl, Best->getAccess());
+
+        // Convert the arguments.
+        CXXMethodDecl *Method = cast<CXXMethodDecl>(FnDecl);
+        if (PerformObjectArgumentInitialization(Args[0], Method))
+          return ExprError();
+
+        // Convert the arguments.
+        OwningExprResult InputInit
+          = PerformCopyInitialization(InitializedEntity::InitializeParameter(
+                                                      FnDecl->getParamDecl(0)),
+                                      SourceLocation(), 
+                                      Owned(Args[1]));
+        if (InputInit.isInvalid())
+          return ExprError();
+
+        Args[1] = InputInit.takeAs<Expr>();
+
+        // Determine the result type
+        QualType ResultTy
+          = FnDecl->getType()->getAs<FunctionType>()->getResultType();
+        ResultTy = ResultTy.getNonReferenceType();
+
+        // Build the actual expression node.
+        Expr *FnExpr = new (Context) DeclRefExpr(FnDecl, FnDecl->getType(),
+                                                 LLoc);
+        UsualUnaryConversions(FnExpr);
+
+        Base.release();
+        Idx.release();
+        ExprOwningPtr<CXXOperatorCallExpr>
+          TheCall(this, new (Context) CXXOperatorCallExpr(Context, OO_Subscript,
+                                                          FnExpr, Args, 2,
+                                                          ResultTy, RLoc));
+
+        if (CheckCallReturnType(FnDecl->getResultType(), LLoc, TheCall.get(),
+                                FnDecl))
+          return ExprError();
+
+        return MaybeBindToTemporary(TheCall.release());
+      } else {
+        // We matched a built-in operator. Convert the arguments, then
+        // break out so that we will build the appropriate built-in
+        // operator node.
+        if (PerformImplicitConversion(Args[0], Best->BuiltinTypes.ParamTypes[0],
+                                      Best->Conversions[0], AA_Passing) ||
+            PerformImplicitConversion(Args[1], Best->BuiltinTypes.ParamTypes[1],
+                                      Best->Conversions[1], AA_Passing))
+          return ExprError();
+
+        break;
+      }
+    }
+
+    case OR_No_Viable_Function: {
+      if (CandidateSet.empty())
+        Diag(LLoc, diag::err_ovl_no_oper)
+          << Args[0]->getType() << /*subscript*/ 0
+          << Args[0]->getSourceRange() << Args[1]->getSourceRange();
+      else
+        Diag(LLoc, diag::err_ovl_no_viable_subscript)
+          << Args[0]->getType()
+          << Args[0]->getSourceRange() << Args[1]->getSourceRange();
+      PrintOverloadCandidates(CandidateSet, OCD_AllCandidates, Args, 2,
+                              "[]", LLoc);
+      return ExprError();
+    }
+
+    case OR_Ambiguous:
+      Diag(LLoc,  diag::err_ovl_ambiguous_oper)
+          << "[]" << Args[0]->getSourceRange() << Args[1]->getSourceRange();
+      PrintOverloadCandidates(CandidateSet, OCD_ViableCandidates, Args, 2,
+                              "[]", LLoc);
+      return ExprError();
+
+    case OR_Deleted:
+      Diag(LLoc, diag::err_ovl_deleted_oper)
+        << Best->Function->isDeleted() << "[]"
+        << Args[0]->getSourceRange() << Args[1]->getSourceRange();
+      PrintOverloadCandidates(CandidateSet, OCD_AllCandidates, Args, 2,
+                              "[]", LLoc);
+      return ExprError();
+    }
+
+  // We matched a built-in operator; build it.
+  Base.release();
+  Idx.release();
+  return CreateBuiltinArraySubscriptExpr(Owned(Args[0]), LLoc,
+                                         Owned(Args[1]), RLoc);
+}
+
+/// BuildCallToMemberFunction - Build a call to a member
+/// function. MemExpr is the expression that refers to the member
+/// function (and includes the object parameter), Args/NumArgs are the
+/// arguments to the function call (not including the object
+/// parameter). The caller needs to validate that the member
+/// expression refers to a member function or an overloaded member
+/// function.
+Sema::OwningExprResult
+Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE,
+                                SourceLocation LParenLoc, Expr **Args,
+                                unsigned NumArgs, SourceLocation *CommaLocs,
+                                SourceLocation RParenLoc) {
+  // Dig out the member expression. This holds both the object
+  // argument and the member function we're referring to.
+  Expr *NakedMemExpr = MemExprE->IgnoreParens();
+  
+  MemberExpr *MemExpr;
+  CXXMethodDecl *Method = 0;
+  if (isa<MemberExpr>(NakedMemExpr)) {
+    MemExpr = cast<MemberExpr>(NakedMemExpr);
+    Method = cast<CXXMethodDecl>(MemExpr->getMemberDecl());
+  } else {
+    UnresolvedMemberExpr *UnresExpr = cast<UnresolvedMemberExpr>(NakedMemExpr);
+
+    QualType ObjectType = UnresExpr->getBaseType();
+
+    // Add overload candidates
+    OverloadCandidateSet CandidateSet(UnresExpr->getMemberLoc());
+
+    // FIXME: avoid copy.
+    TemplateArgumentListInfo TemplateArgsBuffer, *TemplateArgs = 0;
+    if (UnresExpr->hasExplicitTemplateArgs()) {
+      UnresExpr->copyTemplateArgumentsInto(TemplateArgsBuffer);
+      TemplateArgs = &TemplateArgsBuffer;
+    }
+
+    for (UnresolvedMemberExpr::decls_iterator I = UnresExpr->decls_begin(),
+           E = UnresExpr->decls_end(); I != E; ++I) {
+
+      NamedDecl *Func = *I;
+      CXXRecordDecl *ActingDC = cast<CXXRecordDecl>(Func->getDeclContext());
+      if (isa<UsingShadowDecl>(Func))
+        Func = cast<UsingShadowDecl>(Func)->getTargetDecl();
+
+      if ((Method = dyn_cast<CXXMethodDecl>(Func))) {
+        // If explicit template arguments were provided, we can't call a
+        // non-template member function.
+        if (TemplateArgs)
+          continue;
+        
+        AddMethodCandidate(Method, I.getAccess(), ActingDC, ObjectType,
+                           Args, NumArgs,
+                           CandidateSet, /*SuppressUserConversions=*/false);
+      } else {
+        AddMethodTemplateCandidate(cast<FunctionTemplateDecl>(Func),
+                                   I.getAccess(), ActingDC, TemplateArgs,
+                                   ObjectType, Args, NumArgs,
+                                   CandidateSet,
+                                   /*SuppressUsedConversions=*/false);
+      }
+    }
+
+    DeclarationName DeclName = UnresExpr->getMemberName();
+
+    OverloadCandidateSet::iterator Best;
+    switch (BestViableFunction(CandidateSet, UnresExpr->getLocStart(), Best)) {
+    case OR_Success:
+      Method = cast<CXXMethodDecl>(Best->Function);
+      CheckUnresolvedMemberAccess(UnresExpr, Method, Best->getAccess());
+      break;
+
+    case OR_No_Viable_Function:
+      Diag(UnresExpr->getMemberLoc(),
+           diag::err_ovl_no_viable_member_function_in_call)
+        << DeclName << MemExprE->getSourceRange();
+      PrintOverloadCandidates(CandidateSet, OCD_AllCandidates, Args, NumArgs);
+      // FIXME: Leaking incoming expressions!
+      return ExprError();
+
+    case OR_Ambiguous:
+      Diag(UnresExpr->getMemberLoc(), diag::err_ovl_ambiguous_member_call)
+        << DeclName << MemExprE->getSourceRange();
+      PrintOverloadCandidates(CandidateSet, OCD_AllCandidates, Args, NumArgs);
+      // FIXME: Leaking incoming expressions!
+      return ExprError();
+
+    case OR_Deleted:
+      Diag(UnresExpr->getMemberLoc(), diag::err_ovl_deleted_member_call)
+        << Best->Function->isDeleted()
+        << DeclName << MemExprE->getSourceRange();
+      PrintOverloadCandidates(CandidateSet, OCD_AllCandidates, Args, NumArgs);
+      // FIXME: Leaking incoming expressions!
+      return ExprError();
+    }
+
+    MemExprE = FixOverloadedFunctionReference(MemExprE, Method);
+
+    // If overload resolution picked a static member, build a
+    // non-member call based on that function.
+    if (Method->isStatic()) {
+      return BuildResolvedCallExpr(MemExprE, Method, LParenLoc,
+                                   Args, NumArgs, RParenLoc);
+    }
+
+    MemExpr = cast<MemberExpr>(MemExprE->IgnoreParens());
+  }
+
+  assert(Method && "Member call to something that isn't a method?");
+  ExprOwningPtr<CXXMemberCallExpr>
+    TheCall(this, new (Context) CXXMemberCallExpr(Context, MemExprE, Args,
+                                                  NumArgs,
+                                  Method->getResultType().getNonReferenceType(),
+                                  RParenLoc));
+
+  // Check for a valid return type.
+  if (CheckCallReturnType(Method->getResultType(), MemExpr->getMemberLoc(), 
+                          TheCall.get(), Method))
+    return ExprError();
+  
+  // Convert the object argument (for a non-static member function call).
+  Expr *ObjectArg = MemExpr->getBase();
+  if (!Method->isStatic() &&
+      PerformObjectArgumentInitialization(ObjectArg, Method))
+    return ExprError();
+  MemExpr->setBase(ObjectArg);
+
+  // Convert the rest of the arguments
+  const FunctionProtoType *Proto = cast<FunctionProtoType>(Method->getType());
+  if (ConvertArgumentsForCall(&*TheCall, MemExpr, Method, Proto, Args, NumArgs,
+                              RParenLoc))
+    return ExprError();
+
+  if (CheckFunctionCall(Method, TheCall.get()))
+    return ExprError();
+
+  return MaybeBindToTemporary(TheCall.release());
+}
+
+/// BuildCallToObjectOfClassType - Build a call to an object of class
+/// type (C++ [over.call.object]), which can end up invoking an
+/// overloaded function call operator (@c operator()) or performing a
+/// user-defined conversion on the object argument.
+Sema::ExprResult
+Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Object,
+                                   SourceLocation LParenLoc,
+                                   Expr **Args, unsigned NumArgs,
+                                   SourceLocation *CommaLocs,
+                                   SourceLocation RParenLoc) {
+  assert(Object->getType()->isRecordType() && "Requires object type argument");
+  const RecordType *Record = Object->getType()->getAs<RecordType>();
+
+  // C++ [over.call.object]p1:
+  //  If the primary-expression E in the function call syntax
+  //  evaluates to a class object of type "cv T", then the set of
+  //  candidate functions includes at least the function call
+  //  operators of T. The function call operators of T are obtained by
+  //  ordinary lookup of the name operator() in the context of
+  //  (E).operator().
+  OverloadCandidateSet CandidateSet(LParenLoc);
+  DeclarationName OpName = Context.DeclarationNames.getCXXOperatorName(OO_Call);
+
+  if (RequireCompleteType(LParenLoc, Object->getType(), 
+                          PartialDiagnostic(diag::err_incomplete_object_call)
+                          << Object->getSourceRange()))
+    return true;
+  
+  LookupResult R(*this, OpName, LParenLoc, LookupOrdinaryName);
+  LookupQualifiedName(R, Record->getDecl());
+  R.suppressDiagnostics();
+
+  for (LookupResult::iterator Oper = R.begin(), OperEnd = R.end();
+       Oper != OperEnd; ++Oper) {
+    AddMethodCandidate(*Oper, Oper.getAccess(), Object->getType(),
+                       Args, NumArgs, CandidateSet,
+                       /*SuppressUserConversions=*/ false);
+  }
+  
+  // C++ [over.call.object]p2:
+  //   In addition, for each conversion function declared in T of the
+  //   form
+  //
+  //        operator conversion-type-id () cv-qualifier;
+  //
+  //   where cv-qualifier is the same cv-qualification as, or a
+  //   greater cv-qualification than, cv, and where conversion-type-id
+  //   denotes the type "pointer to function of (P1,...,Pn) returning
+  //   R", or the type "reference to pointer to function of
+  //   (P1,...,Pn) returning R", or the type "reference to function
+  //   of (P1,...,Pn) returning R", a surrogate call function [...]
+  //   is also considered as a candidate function. Similarly,
+  //   surrogate call functions are added to the set of candidate
+  //   functions for each conversion function declared in an
+  //   accessible base class provided the function is not hidden
+  //   within T by another intervening declaration.
+  const UnresolvedSetImpl *Conversions
+    = cast<CXXRecordDecl>(Record->getDecl())->getVisibleConversionFunctions();
+  for (UnresolvedSetImpl::iterator I = Conversions->begin(),
+         E = Conversions->end(); I != E; ++I) {
+    NamedDecl *D = *I;
+    CXXRecordDecl *ActingContext = cast<CXXRecordDecl>(D->getDeclContext());
+    if (isa<UsingShadowDecl>(D))
+      D = cast<UsingShadowDecl>(D)->getTargetDecl();
+    
+    // Skip over templated conversion functions; they aren't
+    // surrogates.
+    if (isa<FunctionTemplateDecl>(D))
+      continue;
+
+    CXXConversionDecl *Conv = cast<CXXConversionDecl>(D);
+
+    // Strip the reference type (if any) and then the pointer type (if
+    // any) to get down to what might be a function type.
+    QualType ConvType = Conv->getConversionType().getNonReferenceType();
+    if (const PointerType *ConvPtrType = ConvType->getAs<PointerType>())
+      ConvType = ConvPtrType->getPointeeType();
+
+    if (const FunctionProtoType *Proto = ConvType->getAs<FunctionProtoType>())
+      AddSurrogateCandidate(Conv, I.getAccess(), ActingContext, Proto,
+                            Object->getType(), Args, NumArgs,
+                            CandidateSet);
+  }
+
+  // Perform overload resolution.
+  OverloadCandidateSet::iterator Best;
+  switch (BestViableFunction(CandidateSet, Object->getLocStart(), Best)) {
+  case OR_Success:
+    // Overload resolution succeeded; we'll build the appropriate call
+    // below.
+    break;
+
+  case OR_No_Viable_Function:
+    if (CandidateSet.empty())
+      Diag(Object->getSourceRange().getBegin(), diag::err_ovl_no_oper)
+        << Object->getType() << /*call*/ 1
+        << Object->getSourceRange();
+    else
+      Diag(Object->getSourceRange().getBegin(),
+           diag::err_ovl_no_viable_object_call)
+        << Object->getType() << Object->getSourceRange();
+    PrintOverloadCandidates(CandidateSet, OCD_AllCandidates, Args, NumArgs);
+    break;
+
+  case OR_Ambiguous:
+    Diag(Object->getSourceRange().getBegin(),
+         diag::err_ovl_ambiguous_object_call)
+      << Object->getType() << Object->getSourceRange();
+    PrintOverloadCandidates(CandidateSet, OCD_ViableCandidates, Args, NumArgs);
+    break;
+
+  case OR_Deleted:
+    Diag(Object->getSourceRange().getBegin(),
+         diag::err_ovl_deleted_object_call)
+      << Best->Function->isDeleted()
+      << Object->getType() << Object->getSourceRange();
+    PrintOverloadCandidates(CandidateSet, OCD_AllCandidates, Args, NumArgs);
+    break;
+  }
+
+  if (Best == CandidateSet.end()) {
+    // We had an error; delete all of the subexpressions and return
+    // the error.
+    Object->Destroy(Context);
+    for (unsigned ArgIdx = 0; ArgIdx < NumArgs; ++ArgIdx)
+      Args[ArgIdx]->Destroy(Context);
+    return true;
+  }
+
+  if (Best->Function == 0) {
+    // Since there is no function declaration, this is one of the
+    // surrogate candidates. Dig out the conversion function.
+    CXXConversionDecl *Conv
+      = cast<CXXConversionDecl>(
+                         Best->Conversions[0].UserDefined.ConversionFunction);
+
+    CheckMemberOperatorAccess(LParenLoc, Object, Conv, Best->getAccess());
+
+    // We selected one of the surrogate functions that converts the
+    // object parameter to a function pointer. Perform the conversion
+    // on the object argument, then let ActOnCallExpr finish the job.
+    
+    // Create an implicit member expr to refer to the conversion operator.
+    // and then call it.
+    CXXMemberCallExpr *CE = BuildCXXMemberCallExpr(Object, Conv);
+      
+    return ActOnCallExpr(S, ExprArg(*this, CE), LParenLoc,
+                         MultiExprArg(*this, (ExprTy**)Args, NumArgs),
+                         CommaLocs, RParenLoc).release();
+  }
+
+  CheckMemberOperatorAccess(LParenLoc, Object,
+                            Best->Function, Best->getAccess());
+
+  // We found an overloaded operator(). Build a CXXOperatorCallExpr
+  // that calls this method, using Object for the implicit object
+  // parameter and passing along the remaining arguments.
+  CXXMethodDecl *Method = cast<CXXMethodDecl>(Best->Function);
+  const FunctionProtoType *Proto = Method->getType()->getAs<FunctionProtoType>();
+
+  unsigned NumArgsInProto = Proto->getNumArgs();
+  unsigned NumArgsToCheck = NumArgs;
+
+  // Build the full argument list for the method call (the
+  // implicit object parameter is placed at the beginning of the
+  // list).
+  Expr **MethodArgs;
+  if (NumArgs < NumArgsInProto) {
+    NumArgsToCheck = NumArgsInProto;
+    MethodArgs = new Expr*[NumArgsInProto + 1];
+  } else {
+    MethodArgs = new Expr*[NumArgs + 1];
+  }
+  MethodArgs[0] = Object;
+  for (unsigned ArgIdx = 0; ArgIdx < NumArgs; ++ArgIdx)
+    MethodArgs[ArgIdx + 1] = Args[ArgIdx];
+
+  Expr *NewFn = new (Context) DeclRefExpr(Method, Method->getType(),
+                                          SourceLocation());
+  UsualUnaryConversions(NewFn);
+
+  // Once we've built TheCall, all of the expressions are properly
+  // owned.
+  QualType ResultTy = Method->getResultType().getNonReferenceType();
+  ExprOwningPtr<CXXOperatorCallExpr>
+    TheCall(this, new (Context) CXXOperatorCallExpr(Context, OO_Call, NewFn,
+                                                    MethodArgs, NumArgs + 1,
+                                                    ResultTy, RParenLoc));
+  delete [] MethodArgs;
+
+  if (CheckCallReturnType(Method->getResultType(), LParenLoc, TheCall.get(), 
+                          Method))
+    return true;
+  
+  // We may have default arguments. If so, we need to allocate more
+  // slots in the call for them.
+  if (NumArgs < NumArgsInProto)
+    TheCall->setNumArgs(Context, NumArgsInProto + 1);
+  else if (NumArgs > NumArgsInProto)
+    NumArgsToCheck = NumArgsInProto;
+
+  bool IsError = false;
+
+  // Initialize the implicit object parameter.
+  IsError |= PerformObjectArgumentInitialization(Object, Method);
+  TheCall->setArg(0, Object);
+
+
+  // Check the argument types.
+  for (unsigned i = 0; i != NumArgsToCheck; i++) {
+    Expr *Arg;
+    if (i < NumArgs) {
+      Arg = Args[i];
+
+      // Pass the argument.
+
+      OwningExprResult InputInit
+        = PerformCopyInitialization(InitializedEntity::InitializeParameter(
+                                                    Method->getParamDecl(i)),
+                                    SourceLocation(), Owned(Arg));
+      
+      IsError |= InputInit.isInvalid();
+      Arg = InputInit.takeAs<Expr>();
+    } else {
+      OwningExprResult DefArg
+        = BuildCXXDefaultArgExpr(LParenLoc, Method, Method->getParamDecl(i));
+      if (DefArg.isInvalid()) {
+        IsError = true;
+        break;
+      }
+      
+      Arg = DefArg.takeAs<Expr>();
+    }
+
+    TheCall->setArg(i + 1, Arg);
+  }
+
+  // If this is a variadic call, handle args passed through "...".
+  if (Proto->isVariadic()) {
+    // Promote the arguments (C99 6.5.2.2p7).
+    for (unsigned i = NumArgsInProto; i != NumArgs; i++) {
+      Expr *Arg = Args[i];
+      IsError |= DefaultVariadicArgumentPromotion(Arg, VariadicMethod);
+      TheCall->setArg(i + 1, Arg);
+    }
+  }
+
+  if (IsError) return true;
+
+  if (CheckFunctionCall(Method, TheCall.get()))
+    return true;
+
+  return MaybeBindToTemporary(TheCall.release()).release();
+}
+
+/// BuildOverloadedArrowExpr - Build a call to an overloaded @c operator->
+///  (if one exists), where @c Base is an expression of class type and
+/// @c Member is the name of the member we're trying to find.
+Sema::OwningExprResult
+Sema::BuildOverloadedArrowExpr(Scope *S, ExprArg BaseIn, SourceLocation OpLoc) {
+  Expr *Base = static_cast<Expr *>(BaseIn.get());
+  assert(Base->getType()->isRecordType() && "left-hand side must have class type");
+
+  SourceLocation Loc = Base->getExprLoc();
+
+  // C++ [over.ref]p1:
+  //
+  //   [...] An expression x->m is interpreted as (x.operator->())->m
+  //   for a class object x of type T if T::operator->() exists and if
+  //   the operator is selected as the best match function by the
+  //   overload resolution mechanism (13.3).
+  DeclarationName OpName = Context.DeclarationNames.getCXXOperatorName(OO_Arrow);
+  OverloadCandidateSet CandidateSet(Loc);
+  const RecordType *BaseRecord = Base->getType()->getAs<RecordType>();
+
+  if (RequireCompleteType(Loc, Base->getType(),
+                          PDiag(diag::err_typecheck_incomplete_tag)
+                            << Base->getSourceRange()))
+    return ExprError();
+
+  LookupResult R(*this, OpName, OpLoc, LookupOrdinaryName);
+  LookupQualifiedName(R, BaseRecord->getDecl());
+  R.suppressDiagnostics();
+
+  for (LookupResult::iterator Oper = R.begin(), OperEnd = R.end();
+       Oper != OperEnd; ++Oper) {
+    NamedDecl *D = *Oper;
+    CXXRecordDecl *ActingContext = cast<CXXRecordDecl>(D->getDeclContext());
+    if (isa<UsingShadowDecl>(D))
+      D = cast<UsingShadowDecl>(D)->getTargetDecl();
+
+    AddMethodCandidate(cast<CXXMethodDecl>(D), Oper.getAccess(), ActingContext,
+                       Base->getType(), 0, 0, CandidateSet,
+                       /*SuppressUserConversions=*/false);
+  }
+
+  // Perform overload resolution.
+  OverloadCandidateSet::iterator Best;
+  switch (BestViableFunction(CandidateSet, OpLoc, Best)) {
+  case OR_Success:
+    // Overload resolution succeeded; we'll build the call below.
+    break;
+
+  case OR_No_Viable_Function:
+    if (CandidateSet.empty())
+      Diag(OpLoc, diag::err_typecheck_member_reference_arrow)
+        << Base->getType() << Base->getSourceRange();
+    else
+      Diag(OpLoc, diag::err_ovl_no_viable_oper)
+        << "operator->" << Base->getSourceRange();
+    PrintOverloadCandidates(CandidateSet, OCD_AllCandidates, &Base, 1);
+    return ExprError();
+
+  case OR_Ambiguous:
+    Diag(OpLoc,  diag::err_ovl_ambiguous_oper)
+      << "->" << Base->getSourceRange();
+    PrintOverloadCandidates(CandidateSet, OCD_ViableCandidates, &Base, 1);
+    return ExprError();
+
+  case OR_Deleted:
+    Diag(OpLoc,  diag::err_ovl_deleted_oper)
+      << Best->Function->isDeleted()
+      << "->" << Base->getSourceRange();
+    PrintOverloadCandidates(CandidateSet, OCD_AllCandidates, &Base, 1);
+    return ExprError();
+  }
+
+  // Convert the object parameter.
+  CXXMethodDecl *Method = cast<CXXMethodDecl>(Best->Function);
+  if (PerformObjectArgumentInitialization(Base, Method))
+    return ExprError();
+
+  // No concerns about early exits now.
+  BaseIn.release();
+
+  // Build the operator call.
+  Expr *FnExpr = new (Context) DeclRefExpr(Method, Method->getType(),
+                                           SourceLocation());
+  UsualUnaryConversions(FnExpr);
+  
+  QualType ResultTy = Method->getResultType().getNonReferenceType();
+  ExprOwningPtr<CXXOperatorCallExpr> 
+    TheCall(this, new (Context) CXXOperatorCallExpr(Context, OO_Arrow, FnExpr, 
+                                                    &Base, 1, ResultTy, OpLoc));
+
+  if (CheckCallReturnType(Method->getResultType(), OpLoc, TheCall.get(), 
+                          Method))
+          return ExprError();
+  return move(TheCall);
+}
+
+/// FixOverloadedFunctionReference - E is an expression that refers to
+/// a C++ overloaded function (possibly with some parentheses and
+/// perhaps a '&' around it). We have resolved the overloaded function
+/// to the function declaration Fn, so patch up the expression E to
+/// refer (possibly indirectly) to Fn. Returns the new expr.
+Expr *Sema::FixOverloadedFunctionReference(Expr *E, FunctionDecl *Fn) {
+  if (ParenExpr *PE = dyn_cast<ParenExpr>(E)) {
+    Expr *SubExpr = FixOverloadedFunctionReference(PE->getSubExpr(), Fn);
+    if (SubExpr == PE->getSubExpr())
+      return PE->Retain();
+    
+    return new (Context) ParenExpr(PE->getLParen(), PE->getRParen(), SubExpr);
+  } 
+  
+  if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(E)) {
+    Expr *SubExpr = FixOverloadedFunctionReference(ICE->getSubExpr(), Fn);
+    assert(Context.hasSameType(ICE->getSubExpr()->getType(), 
+                               SubExpr->getType()) &&
+           "Implicit cast type cannot be determined from overload");
+    if (SubExpr == ICE->getSubExpr())
+      return ICE->Retain();
+    
+    return new (Context) ImplicitCastExpr(ICE->getType(), 
+                                          ICE->getCastKind(),
+                                          SubExpr,
+                                          ICE->isLvalueCast());
+  } 
+  
+  if (UnaryOperator *UnOp = dyn_cast<UnaryOperator>(E)) {
+    assert(UnOp->getOpcode() == UnaryOperator::AddrOf &&
+           "Can only take the address of an overloaded function");
+    if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(Fn)) {
+      if (Method->isStatic()) {
+        // Do nothing: static member functions aren't any different
+        // from non-member functions.
+      } else {
+        // Fix the sub expression, which really has to be an
+        // UnresolvedLookupExpr holding an overloaded member function
+        // or template.
+        Expr *SubExpr = FixOverloadedFunctionReference(UnOp->getSubExpr(), Fn);
+        if (SubExpr == UnOp->getSubExpr())
+          return UnOp->Retain();
+
+        assert(isa<DeclRefExpr>(SubExpr)
+               && "fixed to something other than a decl ref");
+        assert(cast<DeclRefExpr>(SubExpr)->getQualifier()
+               && "fixed to a member ref with no nested name qualifier");
+
+        // We have taken the address of a pointer to member
+        // function. Perform the computation here so that we get the
+        // appropriate pointer to member type.
+        QualType ClassType
+          = Context.getTypeDeclType(cast<RecordDecl>(Method->getDeclContext()));
+        QualType MemPtrType
+          = Context.getMemberPointerType(Fn->getType(), ClassType.getTypePtr());
+
+        return new (Context) UnaryOperator(SubExpr, UnaryOperator::AddrOf,
+                                           MemPtrType, UnOp->getOperatorLoc());
+      }
+    }
+    Expr *SubExpr = FixOverloadedFunctionReference(UnOp->getSubExpr(), Fn);
+    if (SubExpr == UnOp->getSubExpr())
+      return UnOp->Retain();
+    
+    return new (Context) UnaryOperator(SubExpr, UnaryOperator::AddrOf,
+                                     Context.getPointerType(SubExpr->getType()),
+                                       UnOp->getOperatorLoc());
+  } 
+
+  if (UnresolvedLookupExpr *ULE = dyn_cast<UnresolvedLookupExpr>(E)) {
+    // FIXME: avoid copy.
+    TemplateArgumentListInfo TemplateArgsBuffer, *TemplateArgs = 0;
+    if (ULE->hasExplicitTemplateArgs()) {
+      ULE->copyTemplateArgumentsInto(TemplateArgsBuffer);
+      TemplateArgs = &TemplateArgsBuffer;
+    }
+
+    return DeclRefExpr::Create(Context,
+                               ULE->getQualifier(),
+                               ULE->getQualifierRange(),
+                               Fn,
+                               ULE->getNameLoc(),
+                               Fn->getType(),
+                               TemplateArgs);
+  }
+
+  if (UnresolvedMemberExpr *MemExpr = dyn_cast<UnresolvedMemberExpr>(E)) {
+    // FIXME: avoid copy.
+    TemplateArgumentListInfo TemplateArgsBuffer, *TemplateArgs = 0;
+    if (MemExpr->hasExplicitTemplateArgs()) {
+      MemExpr->copyTemplateArgumentsInto(TemplateArgsBuffer);
+      TemplateArgs = &TemplateArgsBuffer;
+    }
+
+    Expr *Base;
+
+    // If we're filling in 
+    if (MemExpr->isImplicitAccess()) {
+      if (cast<CXXMethodDecl>(Fn)->isStatic()) {
+        return DeclRefExpr::Create(Context,
+                                   MemExpr->getQualifier(),
+                                   MemExpr->getQualifierRange(),
+                                   Fn,
+                                   MemExpr->getMemberLoc(),
+                                   Fn->getType(),
+                                   TemplateArgs);
+      } else {
+        SourceLocation Loc = MemExpr->getMemberLoc();
+        if (MemExpr->getQualifier())
+          Loc = MemExpr->getQualifierRange().getBegin();
+        Base = new (Context) CXXThisExpr(Loc,
+                                         MemExpr->getBaseType(),
+                                         /*isImplicit=*/true);
+      }
+    } else
+      Base = MemExpr->getBase()->Retain();
+
+    return MemberExpr::Create(Context, Base,
+                              MemExpr->isArrow(), 
+                              MemExpr->getQualifier(), 
+                              MemExpr->getQualifierRange(),
+                              Fn, 
+                              MemExpr->getMemberLoc(),
+                              TemplateArgs,
+                              Fn->getType());
+  }
+  
+  assert(false && "Invalid reference to overloaded function");
+  return E->Retain();
+}
+
+Sema::OwningExprResult Sema::FixOverloadedFunctionReference(OwningExprResult E, 
+                                                            FunctionDecl *Fn) {
+  return Owned(FixOverloadedFunctionReference((Expr *)E.get(), Fn));
+}
+
+} // end namespace clang
diff --git a/lib/Sema/SemaOverload.h b/lib/Sema/SemaOverload.h
new file mode 100644
index 0000000..e6dfa74
--- /dev/null
+++ b/lib/Sema/SemaOverload.h
@@ -0,0 +1,525 @@
+//===--- Overload.h - C++ Overloading ---------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the data structures and types used in C++
+// overload resolution.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_SEMA_OVERLOAD_H
+#define LLVM_CLANG_SEMA_OVERLOAD_H
+
+#include "clang/AST/Decl.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/Type.h"
+#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/SmallVector.h"
+
+namespace clang {
+  class ASTContext;
+  class CXXConstructorDecl;
+  class CXXConversionDecl;
+  class FunctionDecl;
+
+  /// OverloadingResult - Capture the result of performing overload
+  /// resolution.
+  enum OverloadingResult {
+    OR_Success,             ///< Overload resolution succeeded.
+    OR_No_Viable_Function,  ///< No viable function found.
+    OR_Ambiguous,           ///< Ambiguous candidates found.
+    OR_Deleted              ///< Overload resoltuion refers to a deleted function.
+  };
+    
+  /// ImplicitConversionKind - The kind of implicit conversion used to
+  /// convert an argument to a parameter's type. The enumerator values
+  /// match with Table 9 of (C++ 13.3.3.1.1) and are listed such that
+  /// better conversion kinds have smaller values.
+  enum ImplicitConversionKind {
+    ICK_Identity = 0,          ///< Identity conversion (no conversion)
+    ICK_Lvalue_To_Rvalue,      ///< Lvalue-to-rvalue conversion (C++ 4.1)
+    ICK_Array_To_Pointer,      ///< Array-to-pointer conversion (C++ 4.2)
+    ICK_Function_To_Pointer,   ///< Function-to-pointer (C++ 4.3)
+    ICK_NoReturn_Adjustment,   ///< Removal of noreturn from a type (Clang)
+    ICK_Qualification,         ///< Qualification conversions (C++ 4.4)
+    ICK_Integral_Promotion,    ///< Integral promotions (C++ 4.5)
+    ICK_Floating_Promotion,    ///< Floating point promotions (C++ 4.6)
+    ICK_Complex_Promotion,     ///< Complex promotions (Clang extension)
+    ICK_Integral_Conversion,   ///< Integral conversions (C++ 4.7)
+    ICK_Floating_Conversion,   ///< Floating point conversions (C++ 4.8)
+    ICK_Complex_Conversion,    ///< Complex conversions (C99 6.3.1.6)
+    ICK_Floating_Integral,     ///< Floating-integral conversions (C++ 4.9)
+    ICK_Complex_Real,          ///< Complex-real conversions (C99 6.3.1.7)
+    ICK_Pointer_Conversion,    ///< Pointer conversions (C++ 4.10)
+    ICK_Pointer_Member,        ///< Pointer-to-member conversions (C++ 4.11)
+    ICK_Boolean_Conversion,    ///< Boolean conversions (C++ 4.12)
+    ICK_Compatible_Conversion, ///< Conversions between compatible types in C99
+    ICK_Derived_To_Base,       ///< Derived-to-base (C++ [over.best.ics])
+    ICK_Num_Conversion_Kinds   ///< The number of conversion kinds
+  };
+
+  /// ImplicitConversionCategory - The category of an implicit
+  /// conversion kind. The enumerator values match with Table 9 of
+  /// (C++ 13.3.3.1.1) and are listed such that better conversion
+  /// categories have smaller values.
+  enum ImplicitConversionCategory {
+    ICC_Identity = 0,              ///< Identity
+    ICC_Lvalue_Transformation,     ///< Lvalue transformation
+    ICC_Qualification_Adjustment,  ///< Qualification adjustment
+    ICC_Promotion,                 ///< Promotion
+    ICC_Conversion                 ///< Conversion
+  };
+
+  ImplicitConversionCategory
+  GetConversionCategory(ImplicitConversionKind Kind);
+
+  /// ImplicitConversionRank - The rank of an implicit conversion
+  /// kind. The enumerator values match with Table 9 of (C++
+  /// 13.3.3.1.1) and are listed such that better conversion ranks
+  /// have smaller values.
+  enum ImplicitConversionRank {
+    ICR_Exact_Match = 0, ///< Exact Match
+    ICR_Promotion,       ///< Promotion
+    ICR_Conversion       ///< Conversion
+  };
+
+  ImplicitConversionRank GetConversionRank(ImplicitConversionKind Kind);
+
+  /// StandardConversionSequence - represents a standard conversion
+  /// sequence (C++ 13.3.3.1.1). A standard conversion sequence
+  /// contains between zero and three conversions. If a particular
+  /// conversion is not needed, it will be set to the identity conversion
+  /// (ICK_Identity). Note that the three conversions are
+  /// specified as separate members (rather than in an array) so that
+  /// we can keep the size of a standard conversion sequence to a
+  /// single word.
+  struct StandardConversionSequence {
+    /// First -- The first conversion can be an lvalue-to-rvalue
+    /// conversion, array-to-pointer conversion, or
+    /// function-to-pointer conversion.
+    ImplicitConversionKind First : 8;
+
+    /// Second - The second conversion can be an integral promotion,
+    /// floating point promotion, integral conversion, floating point
+    /// conversion, floating-integral conversion, pointer conversion,
+    /// pointer-to-member conversion, or boolean conversion.
+    ImplicitConversionKind Second : 8;
+
+    /// Third - The third conversion can be a qualification conversion.
+    ImplicitConversionKind Third : 8;
+
+    /// Deprecated - Whether this the deprecated conversion of a
+    /// string literal to a pointer to non-const character data
+    /// (C++ 4.2p2).
+    bool Deprecated : 1;
+
+    /// IncompatibleObjC - Whether this is an Objective-C conversion
+    /// that we should warn about (if we actually use it).
+    bool IncompatibleObjC : 1;
+
+    /// ReferenceBinding - True when this is a reference binding
+    /// (C++ [over.ics.ref]).
+    bool ReferenceBinding : 1;
+
+    /// DirectBinding - True when this is a reference binding that is a
+    /// direct binding (C++ [dcl.init.ref]).
+    bool DirectBinding : 1;
+
+    /// RRefBinding - True when this is a reference binding of an rvalue
+    /// reference to an rvalue (C++0x [over.ics.rank]p3b4).
+    bool RRefBinding : 1;
+
+    /// FromType - The type that this conversion is converting
+    /// from. This is an opaque pointer that can be translated into a
+    /// QualType.
+    void *FromTypePtr;
+
+    /// ToType - The types that this conversion is converting to in
+    /// each step. This is an opaque pointer that can be translated
+    /// into a QualType.
+    void *ToTypePtrs[3];
+
+    /// CopyConstructor - The copy constructor that is used to perform
+    /// this conversion, when the conversion is actually just the
+    /// initialization of an object via copy constructor. Such
+    /// conversions are either identity conversions or derived-to-base
+    /// conversions.
+    CXXConstructorDecl *CopyConstructor;
+
+    void setFromType(QualType T) { FromTypePtr = T.getAsOpaquePtr(); }
+    void setToType(unsigned Idx, QualType T) { 
+      assert(Idx < 3 && "To type index is out of range");
+      ToTypePtrs[Idx] = T.getAsOpaquePtr(); 
+    }
+    void setAllToTypes(QualType T) {
+      ToTypePtrs[0] = T.getAsOpaquePtr(); 
+      ToTypePtrs[1] = ToTypePtrs[0];
+      ToTypePtrs[2] = ToTypePtrs[0];
+    }
+
+    QualType getFromType() const {
+      return QualType::getFromOpaquePtr(FromTypePtr);
+    }
+    QualType getToType(unsigned Idx) const {
+      assert(Idx < 3 && "To type index is out of range");
+      return QualType::getFromOpaquePtr(ToTypePtrs[Idx]);
+    }
+
+    void setAsIdentityConversion();
+    ImplicitConversionRank getRank() const;
+    bool isPointerConversionToBool() const;
+    bool isPointerConversionToVoidPointer(ASTContext& Context) const;
+    void DebugPrint() const;
+  };
+
+  /// UserDefinedConversionSequence - Represents a user-defined
+  /// conversion sequence (C++ 13.3.3.1.2).
+  struct UserDefinedConversionSequence {
+    /// Before - Represents the standard conversion that occurs before
+    /// the actual user-defined conversion. (C++ 13.3.3.1.2p1):
+    ///
+    ///   If the user-defined conversion is specified by a constructor
+    ///   (12.3.1), the initial standard conversion sequence converts
+    ///   the source type to the type required by the argument of the
+    ///   constructor. If the user-defined conversion is specified by
+    ///   a conversion function (12.3.2), the initial standard
+    ///   conversion sequence converts the source type to the implicit
+    ///   object parameter of the conversion function.
+    StandardConversionSequence Before;
+
+    /// EllipsisConversion - When this is true, it means user-defined
+    /// conversion sequence starts with a ... (elipsis) conversion, instead of 
+    /// a standard conversion. In this case, 'Before' field must be ignored.
+    // FIXME. I much rather put this as the first field. But there seems to be
+    // a gcc code gen. bug which causes a crash in a test. Putting it here seems
+    // to work around the crash.
+    bool EllipsisConversion : 1;
+    
+    /// After - Represents the standard conversion that occurs after
+    /// the actual user-defined conversion.
+    StandardConversionSequence After;
+
+    /// ConversionFunction - The function that will perform the
+    /// user-defined conversion.
+    FunctionDecl* ConversionFunction;
+
+    void DebugPrint() const;
+  };
+
+  /// Represents an ambiguous user-defined conversion sequence.
+  struct AmbiguousConversionSequence {
+    typedef llvm::SmallVector<FunctionDecl*, 4> ConversionSet;
+
+    void *FromTypePtr;
+    void *ToTypePtr;
+    char Buffer[sizeof(ConversionSet)];
+
+    QualType getFromType() const {
+      return QualType::getFromOpaquePtr(FromTypePtr);
+    }
+    QualType getToType() const {
+      return QualType::getFromOpaquePtr(ToTypePtr);
+    }
+    void setFromType(QualType T) { FromTypePtr = T.getAsOpaquePtr(); }
+    void setToType(QualType T) { ToTypePtr = T.getAsOpaquePtr(); }
+
+    ConversionSet &conversions() {
+      return *reinterpret_cast<ConversionSet*>(Buffer);
+    }
+
+    const ConversionSet &conversions() const {
+      return *reinterpret_cast<const ConversionSet*>(Buffer);
+    }
+
+    void addConversion(FunctionDecl *D) {
+      conversions().push_back(D);
+    }
+
+    typedef ConversionSet::iterator iterator;
+    iterator begin() { return conversions().begin(); }
+    iterator end() { return conversions().end(); }
+
+    typedef ConversionSet::const_iterator const_iterator;
+    const_iterator begin() const { return conversions().begin(); }
+    const_iterator end() const { return conversions().end(); }
+
+    void construct();
+    void destruct();
+    void copyFrom(const AmbiguousConversionSequence &);
+  };
+
+  /// BadConversionSequence - Records information about an invalid
+  /// conversion sequence.
+  struct BadConversionSequence {
+    enum FailureKind {
+      no_conversion,
+      unrelated_class,
+      suppressed_user,
+      bad_qualifiers
+    };
+
+    // This can be null, e.g. for implicit object arguments.
+    Expr *FromExpr;
+
+    FailureKind Kind;
+
+  private:
+    // The type we're converting from (an opaque QualType).
+    void *FromTy;
+
+    // The type we're converting to (an opaque QualType).
+    void *ToTy;
+
+  public:
+    void init(FailureKind K, Expr *From, QualType To) {
+      init(K, From->getType(), To);
+      FromExpr = From;
+    }
+    void init(FailureKind K, QualType From, QualType To) {
+      Kind = K;
+      FromExpr = 0;
+      setFromType(From);
+      setToType(To);
+    }
+
+    QualType getFromType() const { return QualType::getFromOpaquePtr(FromTy); }
+    QualType getToType() const { return QualType::getFromOpaquePtr(ToTy); }
+
+    void setFromExpr(Expr *E) {
+      FromExpr = E;
+      setFromType(E->getType());
+    }
+    void setFromType(QualType T) { FromTy = T.getAsOpaquePtr(); }
+    void setToType(QualType T) { ToTy = T.getAsOpaquePtr(); }
+  };
+
+  /// ImplicitConversionSequence - Represents an implicit conversion
+  /// sequence, which may be a standard conversion sequence
+  /// (C++ 13.3.3.1.1), user-defined conversion sequence (C++ 13.3.3.1.2),
+  /// or an ellipsis conversion sequence (C++ 13.3.3.1.3).
+  struct ImplicitConversionSequence {
+    /// Kind - The kind of implicit conversion sequence. BadConversion
+    /// specifies that there is no conversion from the source type to
+    /// the target type.  AmbiguousConversion represents the unique
+    /// ambiguous conversion (C++0x [over.best.ics]p10).
+    enum Kind {
+      StandardConversion = 0,
+      UserDefinedConversion,
+      AmbiguousConversion,
+      EllipsisConversion,
+      BadConversion
+    };
+
+  private:
+    /// ConversionKind - The kind of implicit conversion sequence.
+    Kind ConversionKind;
+
+    void setKind(Kind K) {
+      if (isAmbiguous()) Ambiguous.destruct();
+      ConversionKind = K;
+    }
+
+  public:
+    union {
+      /// When ConversionKind == StandardConversion, provides the
+      /// details of the standard conversion sequence.
+      StandardConversionSequence Standard;
+
+      /// When ConversionKind == UserDefinedConversion, provides the
+      /// details of the user-defined conversion sequence.
+      UserDefinedConversionSequence UserDefined;
+
+      /// When ConversionKind == AmbiguousConversion, provides the
+      /// details of the ambiguous conversion.
+      AmbiguousConversionSequence Ambiguous;
+
+      /// When ConversionKind == BadConversion, provides the details
+      /// of the bad conversion.
+      BadConversionSequence Bad;
+    };
+
+    ImplicitConversionSequence() : ConversionKind(BadConversion) {}
+    ~ImplicitConversionSequence() {
+      if (isAmbiguous()) Ambiguous.destruct();
+    }
+    ImplicitConversionSequence(const ImplicitConversionSequence &Other)
+      : ConversionKind(Other.ConversionKind)
+    {
+      switch (ConversionKind) {
+      case StandardConversion: Standard = Other.Standard; break;
+      case UserDefinedConversion: UserDefined = Other.UserDefined; break;
+      case AmbiguousConversion: Ambiguous.copyFrom(Other.Ambiguous); break;
+      case EllipsisConversion: break;
+      case BadConversion: Bad = Other.Bad; break;
+      }
+    }
+
+    ImplicitConversionSequence &
+        operator=(const ImplicitConversionSequence &Other) {
+      if (isAmbiguous()) Ambiguous.destruct();
+      new (this) ImplicitConversionSequence(Other);
+      return *this;
+    }
+    
+    Kind getKind() const { return ConversionKind; }
+    bool isBad() const { return ConversionKind == BadConversion; }
+    bool isStandard() const { return ConversionKind == StandardConversion; }
+    bool isEllipsis() const { return ConversionKind == EllipsisConversion; }
+    bool isAmbiguous() const { return ConversionKind == AmbiguousConversion; }
+    bool isUserDefined() const {
+      return ConversionKind == UserDefinedConversion;
+    }
+
+    void setBad() { setKind(BadConversion); }
+    void setStandard() { setKind(StandardConversion); }
+    void setEllipsis() { setKind(EllipsisConversion); }
+    void setUserDefined() { setKind(UserDefinedConversion); }
+    void setAmbiguous() {
+      if (isAmbiguous()) return;
+      ConversionKind = AmbiguousConversion;
+      Ambiguous.construct();
+    }
+
+    // The result of a comparison between implicit conversion
+    // sequences. Use Sema::CompareImplicitConversionSequences to
+    // actually perform the comparison.
+    enum CompareKind {
+      Better = -1,
+      Indistinguishable = 0,
+      Worse = 1
+    };
+
+    void DebugPrint() const;
+  };
+
+  enum OverloadFailureKind {
+    ovl_fail_too_many_arguments,
+    ovl_fail_too_few_arguments,
+    ovl_fail_bad_conversion,
+    ovl_fail_bad_deduction,
+
+    /// This conversion candidate was not considered because it
+    /// duplicates the work of a trivial or derived-to-base
+    /// conversion.
+    ovl_fail_trivial_conversion,
+
+    /// This conversion candidate is not viable because its result
+    /// type is not implicitly convertible to the desired type.
+    ovl_fail_bad_final_conversion
+  };
+
+  /// OverloadCandidate - A single candidate in an overload set (C++ 13.3).
+  struct OverloadCandidate {
+    /// Function - The actual function that this candidate
+    /// represents. When NULL, this is a built-in candidate
+    /// (C++ [over.oper]) or a surrogate for a conversion to a
+    /// function pointer or reference (C++ [over.call.object]).
+    FunctionDecl *Function;
+
+    // BuiltinTypes - Provides the return and parameter types of a
+    // built-in overload candidate. Only valid when Function is NULL.
+    struct {
+      QualType ResultTy;
+      QualType ParamTypes[3];
+    } BuiltinTypes;
+
+    /// Surrogate - The conversion function for which this candidate
+    /// is a surrogate, but only if IsSurrogate is true.
+    CXXConversionDecl *Surrogate;
+
+    /// Conversions - The conversion sequences used to convert the
+    /// function arguments to the function parameters.
+    llvm::SmallVector<ImplicitConversionSequence, 4> Conversions;
+
+    /// Viable - True to indicate that this overload candidate is viable.
+    bool Viable;
+
+    /// IsSurrogate - True to indicate that this candidate is a
+    /// surrogate for a conversion to a function pointer or reference
+    /// (C++ [over.call.object]).
+    bool IsSurrogate;
+
+    /// IgnoreObjectArgument - True to indicate that the first
+    /// argument's conversion, which for this function represents the
+    /// implicit object argument, should be ignored. This will be true
+    /// when the candidate is a static member function (where the
+    /// implicit object argument is just a placeholder) or a
+    /// non-static member function when the call doesn't have an
+    /// object argument.
+    bool IgnoreObjectArgument;
+
+    /// FailureKind - The reason why this candidate is not viable.
+    /// Actually an OverloadFailureKind.
+    unsigned char FailureKind;
+
+    /// PathAccess - The 'path access' to the given function/conversion.
+    /// Actually an AccessSpecifier.
+    unsigned Access;
+
+    AccessSpecifier getAccess() const {
+      return AccessSpecifier(Access);
+    }
+
+    /// A structure used to record information about a failed
+    /// template argument deduction.
+    struct DeductionFailureInfo {
+      // A Sema::TemplateDeductionResult.
+      unsigned Result;
+
+      // A TemplateParameter.
+      void *TemplateParameter;
+    };
+
+    union {
+      DeductionFailureInfo DeductionFailure;
+      
+      /// FinalConversion - For a conversion function (where Function is
+      /// a CXXConversionDecl), the standard conversion that occurs
+      /// after the call to the overload candidate to convert the result
+      /// of calling the conversion function to the required type.
+      StandardConversionSequence FinalConversion;
+    };
+
+    /// hasAmbiguousConversion - Returns whether this overload
+    /// candidate requires an ambiguous conversion or not.
+    bool hasAmbiguousConversion() const {
+      for (llvm::SmallVectorImpl<ImplicitConversionSequence>::const_iterator
+             I = Conversions.begin(), E = Conversions.end(); I != E; ++I) {
+        if (I->isAmbiguous()) return true;
+      }
+      return false;
+    }
+  };
+
+  /// OverloadCandidateSet - A set of overload candidates, used in C++
+  /// overload resolution (C++ 13.3).
+  class OverloadCandidateSet : public llvm::SmallVector<OverloadCandidate, 16> {
+    typedef llvm::SmallVector<OverloadCandidate, 16> inherited;
+    llvm::SmallPtrSet<Decl *, 16> Functions;
+
+    SourceLocation Loc;    
+  public:
+    OverloadCandidateSet(SourceLocation Loc) : Loc(Loc) {}
+
+    SourceLocation getLocation() const { return Loc; }
+
+    /// \brief Determine when this overload candidate will be new to the
+    /// overload set.
+    bool isNewCandidate(Decl *F) { 
+      return Functions.insert(F->getCanonicalDecl()); 
+    }
+
+    /// \brief Clear out all of the candidates.
+    void clear() {
+      inherited::clear();
+      Functions.clear();
+    }
+  };
+} // end namespace clang
+
+#endif // LLVM_CLANG_SEMA_OVERLOAD_H
diff --git a/lib/Sema/SemaStmt.cpp b/lib/Sema/SemaStmt.cpp
new file mode 100644
index 0000000..50479a9
--- /dev/null
+++ b/lib/Sema/SemaStmt.cpp
@@ -0,0 +1,1644 @@
+//===--- SemaStmt.cpp - Semantic Analysis for Statements ------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+//  This file implements semantic analysis for statements.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Sema.h"
+#include "SemaInit.h"
+#include "clang/AST/APValue.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/AST/ExprCXX.h"
+#include "clang/AST/ExprObjC.h"
+#include "clang/AST/StmtObjC.h"
+#include "clang/AST/StmtCXX.h"
+#include "clang/Lex/Preprocessor.h"
+#include "clang/Basic/TargetInfo.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SmallVector.h"
+using namespace clang;
+
+Sema::OwningStmtResult Sema::ActOnExprStmt(FullExprArg expr) {
+  Expr *E = expr->takeAs<Expr>();
+  assert(E && "ActOnExprStmt(): missing expression");
+  if (E->getType()->isObjCInterfaceType()) {
+    if (LangOpts.ObjCNonFragileABI)
+      Diag(E->getLocEnd(), diag::err_indirection_requires_nonfragile_object)
+             << E->getType();
+    else
+      Diag(E->getLocEnd(), diag::err_direct_interface_unsupported)
+             << E->getType();
+    return StmtError();
+  }
+  // C99 6.8.3p2: The expression in an expression statement is evaluated as a
+  // void expression for its side effects.  Conversion to void allows any
+  // operand, even incomplete types.
+
+  // Same thing in for stmt first clause (when expr) and third clause.
+  return Owned(static_cast<Stmt*>(E));
+}
+
+
+Sema::OwningStmtResult Sema::ActOnNullStmt(SourceLocation SemiLoc) {
+  return Owned(new (Context) NullStmt(SemiLoc));
+}
+
+Sema::OwningStmtResult Sema::ActOnDeclStmt(DeclGroupPtrTy dg,
+                                           SourceLocation StartLoc,
+                                           SourceLocation EndLoc) {
+  DeclGroupRef DG = dg.getAsVal<DeclGroupRef>();
+
+  // If we have an invalid decl, just return an error.
+  if (DG.isNull()) return StmtError();
+
+  return Owned(new (Context) DeclStmt(DG, StartLoc, EndLoc));
+}
+
+void Sema::ActOnForEachDeclStmt(DeclGroupPtrTy dg) {
+  DeclGroupRef DG = dg.getAsVal<DeclGroupRef>();
+  
+  // If we have an invalid decl, just return.
+  if (DG.isNull() || !DG.isSingleDecl()) return;
+  // suppress any potential 'unused variable' warning.
+  DG.getSingleDecl()->setUsed();
+}
+
+void Sema::DiagnoseUnusedExprResult(const Stmt *S) {
+  const Expr *E = dyn_cast_or_null<Expr>(S);
+  if (!E)
+    return;
+
+  // Ignore expressions that have void type.
+  if (E->getType()->isVoidType())
+    return;
+
+  SourceLocation Loc;
+  SourceRange R1, R2;
+  if (!E->isUnusedResultAWarning(Loc, R1, R2, Context))
+    return;
+
+  // Okay, we have an unused result.  Depending on what the base expression is,
+  // we might want to make a more specific diagnostic.  Check for one of these
+  // cases now.
+  unsigned DiagID = diag::warn_unused_expr;
+  E = E->IgnoreParens();
+  if (isa<ObjCImplicitSetterGetterRefExpr>(E))
+    DiagID = diag::warn_unused_property_expr;
+  
+  if (const CallExpr *CE = dyn_cast<CallExpr>(E)) {
+    // If the callee has attribute pure, const, or warn_unused_result, warn with
+    // a more specific message to make it clear what is happening.
+    if (const Decl *FD = CE->getCalleeDecl()) {
+      if (FD->getAttr<WarnUnusedResultAttr>()) {
+        Diag(Loc, diag::warn_unused_call) << R1 << R2 << "warn_unused_result";
+        return;
+      }
+      if (FD->getAttr<PureAttr>()) {
+        Diag(Loc, diag::warn_unused_call) << R1 << R2 << "pure";
+        return;
+      }
+      if (FD->getAttr<ConstAttr>()) {
+        Diag(Loc, diag::warn_unused_call) << R1 << R2 << "const";
+        return;
+      }
+    }        
+  }
+
+  Diag(Loc, DiagID) << R1 << R2;
+}
+
+Action::OwningStmtResult
+Sema::ActOnCompoundStmt(SourceLocation L, SourceLocation R,
+                        MultiStmtArg elts, bool isStmtExpr) {
+  unsigned NumElts = elts.size();
+  Stmt **Elts = reinterpret_cast<Stmt**>(elts.release());
+  // If we're in C89 mode, check that we don't have any decls after stmts.  If
+  // so, emit an extension diagnostic.
+  if (!getLangOptions().C99 && !getLangOptions().CPlusPlus) {
+    // Note that __extension__ can be around a decl.
+    unsigned i = 0;
+    // Skip over all declarations.
+    for (; i != NumElts && isa<DeclStmt>(Elts[i]); ++i)
+      /*empty*/;
+
+    // We found the end of the list or a statement.  Scan for another declstmt.
+    for (; i != NumElts && !isa<DeclStmt>(Elts[i]); ++i)
+      /*empty*/;
+
+    if (i != NumElts) {
+      Decl *D = *cast<DeclStmt>(Elts[i])->decl_begin();
+      Diag(D->getLocation(), diag::ext_mixed_decls_code);
+    }
+  }
+  // Warn about unused expressions in statements.
+  for (unsigned i = 0; i != NumElts; ++i) {
+    // Ignore statements that are last in a statement expression.
+    if (isStmtExpr && i == NumElts - 1)
+      continue;
+
+    DiagnoseUnusedExprResult(Elts[i]);
+  }
+
+  return Owned(new (Context) CompoundStmt(Context, Elts, NumElts, L, R));
+}
+
+Action::OwningStmtResult
+Sema::ActOnCaseStmt(SourceLocation CaseLoc, ExprArg lhsval,
+                    SourceLocation DotDotDotLoc, ExprArg rhsval,
+                    SourceLocation ColonLoc) {
+  assert((lhsval.get() != 0) && "missing expression in case statement");
+
+  // C99 6.8.4.2p3: The expression shall be an integer constant.
+  // However, GCC allows any evaluatable integer expression.
+  Expr *LHSVal = static_cast<Expr*>(lhsval.get());
+  if (!LHSVal->isTypeDependent() && !LHSVal->isValueDependent() &&
+      VerifyIntegerConstantExpression(LHSVal))
+    return StmtError();
+
+  // GCC extension: The expression shall be an integer constant.
+
+  Expr *RHSVal = static_cast<Expr*>(rhsval.get());
+  if (RHSVal && !RHSVal->isTypeDependent() && !RHSVal->isValueDependent() &&
+      VerifyIntegerConstantExpression(RHSVal)) {
+    RHSVal = 0;  // Recover by just forgetting about it.
+    rhsval = 0;
+  }
+
+  if (getSwitchStack().empty()) {
+    Diag(CaseLoc, diag::err_case_not_in_switch);
+    return StmtError();
+  }
+
+  // Only now release the smart pointers.
+  lhsval.release();
+  rhsval.release();
+  CaseStmt *CS = new (Context) CaseStmt(LHSVal, RHSVal, CaseLoc, DotDotDotLoc,
+                                        ColonLoc);
+  getSwitchStack().back()->addSwitchCase(CS);
+  return Owned(CS);
+}
+
+/// ActOnCaseStmtBody - This installs a statement as the body of a case.
+void Sema::ActOnCaseStmtBody(StmtTy *caseStmt, StmtArg subStmt) {
+  CaseStmt *CS = static_cast<CaseStmt*>(caseStmt);
+  Stmt *SubStmt = subStmt.takeAs<Stmt>();
+  CS->setSubStmt(SubStmt);
+}
+
+Action::OwningStmtResult
+Sema::ActOnDefaultStmt(SourceLocation DefaultLoc, SourceLocation ColonLoc,
+                       StmtArg subStmt, Scope *CurScope) {
+  Stmt *SubStmt = subStmt.takeAs<Stmt>();
+
+  if (getSwitchStack().empty()) {
+    Diag(DefaultLoc, diag::err_default_not_in_switch);
+    return Owned(SubStmt);
+  }
+
+  DefaultStmt *DS = new (Context) DefaultStmt(DefaultLoc, ColonLoc, SubStmt);
+  getSwitchStack().back()->addSwitchCase(DS);
+  return Owned(DS);
+}
+
+Action::OwningStmtResult
+Sema::ActOnLabelStmt(SourceLocation IdentLoc, IdentifierInfo *II,
+                     SourceLocation ColonLoc, StmtArg subStmt) {
+  Stmt *SubStmt = subStmt.takeAs<Stmt>();
+  // Look up the record for this label identifier.
+  LabelStmt *&LabelDecl = getLabelMap()[II];
+
+  // If not forward referenced or defined already, just create a new LabelStmt.
+  if (LabelDecl == 0)
+    return Owned(LabelDecl = new (Context) LabelStmt(IdentLoc, II, 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->getID();
+    Diag(LabelDecl->getIdentLoc(), diag::note_previous_definition);
+    return Owned(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(SubStmt);
+  return Owned(LabelDecl);
+}
+
+Action::OwningStmtResult
+Sema::ActOnIfStmt(SourceLocation IfLoc, FullExprArg CondVal, DeclPtrTy CondVar,
+                  StmtArg ThenVal, SourceLocation ElseLoc,
+                  StmtArg ElseVal) {
+  OwningExprResult CondResult(CondVal.release());
+
+  VarDecl *ConditionVar = 0;
+  if (CondVar.get()) {
+    ConditionVar = CondVar.getAs<VarDecl>();
+    CondResult = CheckConditionVariable(ConditionVar);
+    if (CondResult.isInvalid())
+      return StmtError();
+  }
+  Expr *ConditionExpr = CondResult.takeAs<Expr>();
+  if (!ConditionExpr)
+    return StmtError();
+  
+  if (CheckBooleanCondition(ConditionExpr, IfLoc)) {
+    CondResult = ConditionExpr;
+    return StmtError();
+  }
+
+  Stmt *thenStmt = ThenVal.takeAs<Stmt>();
+  DiagnoseUnusedExprResult(thenStmt);
+
+  // Warn if the if block has a null body without an else value.
+  // this helps prevent bugs due to typos, such as
+  // if (condition);
+  //   do_stuff();
+  if (!ElseVal.get()) {
+    if (NullStmt* stmt = dyn_cast<NullStmt>(thenStmt))
+      Diag(stmt->getSemiLoc(), diag::warn_empty_if_body);
+  }
+
+  Stmt *elseStmt = ElseVal.takeAs<Stmt>();
+  DiagnoseUnusedExprResult(elseStmt);
+
+  CondResult.release();
+  return Owned(new (Context) IfStmt(IfLoc, ConditionVar, ConditionExpr, 
+                                    thenStmt, ElseLoc, elseStmt));
+}
+
+Action::OwningStmtResult
+Sema::ActOnStartOfSwitchStmt(FullExprArg cond, DeclPtrTy CondVar) {
+  OwningExprResult CondResult(cond.release());
+  
+  VarDecl *ConditionVar = 0;
+  if (CondVar.get()) {
+    ConditionVar = CondVar.getAs<VarDecl>();
+    CondResult = CheckConditionVariable(ConditionVar);
+    if (CondResult.isInvalid())
+      return StmtError();
+  }
+  SwitchStmt *SS = new (Context) SwitchStmt(ConditionVar, 
+                                            CondResult.takeAs<Expr>());
+  getSwitchStack().push_back(SS);
+  return Owned(SS);
+}
+
+/// ConvertIntegerToTypeWarnOnOverflow - Convert the specified APInt to have
+/// the specified width and sign.  If an overflow occurs, detect it and emit
+/// the specified diagnostic.
+void Sema::ConvertIntegerToTypeWarnOnOverflow(llvm::APSInt &Val,
+                                              unsigned NewWidth, bool NewSign,
+                                              SourceLocation Loc,
+                                              unsigned DiagID) {
+  // Perform a conversion to the promoted condition type if needed.
+  if (NewWidth > Val.getBitWidth()) {
+    // If this is an extension, just do it.
+    llvm::APSInt OldVal(Val);
+    Val.extend(NewWidth);
+
+    // If the input was signed and negative and the output is unsigned,
+    // warn.
+    if (!NewSign && OldVal.isSigned() && OldVal.isNegative())
+      Diag(Loc, DiagID) << OldVal.toString(10) << Val.toString(10);
+
+    Val.setIsSigned(NewSign);
+  } else if (NewWidth < Val.getBitWidth()) {
+    // If this is a truncation, check for overflow.
+    llvm::APSInt ConvVal(Val);
+    ConvVal.trunc(NewWidth);
+    ConvVal.setIsSigned(NewSign);
+    ConvVal.extend(Val.getBitWidth());
+    ConvVal.setIsSigned(Val.isSigned());
+    if (ConvVal != Val)
+      Diag(Loc, DiagID) << Val.toString(10) << ConvVal.toString(10);
+
+    // Regardless of whether a diagnostic was emitted, really do the
+    // truncation.
+    Val.trunc(NewWidth);
+    Val.setIsSigned(NewSign);
+  } else if (NewSign != Val.isSigned()) {
+    // Convert the sign to match the sign of the condition.  This can cause
+    // overflow as well: unsigned(INTMIN)
+    llvm::APSInt OldVal(Val);
+    Val.setIsSigned(NewSign);
+
+    if (Val.isNegative())  // Sign bit changes meaning.
+      Diag(Loc, DiagID) << OldVal.toString(10) << Val.toString(10);
+  }
+}
+
+namespace {
+  struct CaseCompareFunctor {
+    bool operator()(const std::pair<llvm::APSInt, CaseStmt*> &LHS,
+                    const llvm::APSInt &RHS) {
+      return LHS.first < RHS;
+    }
+    bool operator()(const std::pair<llvm::APSInt, CaseStmt*> &LHS,
+                    const std::pair<llvm::APSInt, CaseStmt*> &RHS) {
+      return LHS.first < RHS.first;
+    }
+    bool operator()(const llvm::APSInt &LHS,
+                    const std::pair<llvm::APSInt, CaseStmt*> &RHS) {
+      return LHS < RHS.first;
+    }
+  };
+}
+
+/// CmpCaseVals - Comparison predicate for sorting case values.
+///
+static bool CmpCaseVals(const std::pair<llvm::APSInt, CaseStmt*>& lhs,
+                        const std::pair<llvm::APSInt, CaseStmt*>& rhs) {
+  if (lhs.first < rhs.first)
+    return true;
+
+  if (lhs.first == rhs.first &&
+      lhs.second->getCaseLoc().getRawEncoding()
+       < rhs.second->getCaseLoc().getRawEncoding())
+    return true;
+  return false;
+}
+
+/// CmpEnumVals - Comparison predicate for sorting enumeration values.
+///
+static bool CmpEnumVals(const std::pair<llvm::APSInt, EnumConstantDecl*>& lhs,
+                        const std::pair<llvm::APSInt, EnumConstantDecl*>& rhs)
+{
+  return lhs.first < rhs.first;
+}
+
+/// EqEnumVals - Comparison preficate for uniqing enumeration values.
+///
+static bool EqEnumVals(const std::pair<llvm::APSInt, EnumConstantDecl*>& lhs,
+                       const std::pair<llvm::APSInt, EnumConstantDecl*>& rhs)
+{
+  return lhs.first == rhs.first;
+}
+
+/// GetTypeBeforeIntegralPromotion - Returns the pre-promotion type of
+/// potentially integral-promoted expression @p expr.
+static QualType GetTypeBeforeIntegralPromotion(const Expr* expr) {
+  const ImplicitCastExpr *ImplicitCast =
+      dyn_cast_or_null<ImplicitCastExpr>(expr);
+  if (ImplicitCast != NULL) {
+    const Expr *ExprBeforePromotion = ImplicitCast->getSubExpr();
+    QualType TypeBeforePromotion = ExprBeforePromotion->getType();
+    if (TypeBeforePromotion->isIntegralType()) {
+      return TypeBeforePromotion;
+    }
+  }
+  return expr->getType();
+}
+
+/// \brief Check (and possibly convert) the condition in a switch
+/// statement in C++.
+static bool CheckCXXSwitchCondition(Sema &S, SourceLocation SwitchLoc,
+                                    Expr *&CondExpr) {
+  if (CondExpr->isTypeDependent())
+    return false;
+
+  QualType CondType = CondExpr->getType();
+
+  // C++ 6.4.2.p2:
+  // The condition shall be of integral type, enumeration type, or of a class
+  // type for which a single conversion function to integral or enumeration
+  // type exists (12.3). If the condition is of class type, the condition is
+  // converted by calling that conversion function, and the result of the
+  // conversion is used in place of the original condition for the remainder
+  // of this section. Integral promotions are performed.
+
+  // Make sure that the condition expression has a complete type,
+  // otherwise we'll never find any conversions.
+  if (S.RequireCompleteType(SwitchLoc, CondType,
+                            PDiag(diag::err_switch_incomplete_class_type)
+                              << CondExpr->getSourceRange()))
+    return true;
+
+  llvm::SmallVector<CXXConversionDecl *, 4> ViableConversions;
+  llvm::SmallVector<CXXConversionDecl *, 4> ExplicitConversions;
+  if (const RecordType *RecordTy = CondType->getAs<RecordType>()) {
+    const UnresolvedSetImpl *Conversions
+      = cast<CXXRecordDecl>(RecordTy->getDecl())
+                                             ->getVisibleConversionFunctions();
+    for (UnresolvedSetImpl::iterator I = Conversions->begin(),
+           E = Conversions->end(); I != E; ++I) {
+      if (CXXConversionDecl *Conversion = dyn_cast<CXXConversionDecl>(*I))
+        if (Conversion->getConversionType().getNonReferenceType()
+              ->isIntegralType()) {
+          if (Conversion->isExplicit())
+            ExplicitConversions.push_back(Conversion);
+          else
+          ViableConversions.push_back(Conversion);
+        }
+    }
+
+    switch (ViableConversions.size()) {
+    case 0:
+      if (ExplicitConversions.size() == 1) {
+        // The user probably meant to invoke the given explicit
+        // conversion; use it.
+        QualType ConvTy
+          = ExplicitConversions[0]->getConversionType()
+                        .getNonReferenceType();
+        std::string TypeStr;
+        ConvTy.getAsStringInternal(TypeStr, S.Context.PrintingPolicy);
+
+        S.Diag(SwitchLoc, diag::err_switch_explicit_conversion)
+          << CondType << ConvTy << CondExpr->getSourceRange()
+          << CodeModificationHint::CreateInsertion(CondExpr->getLocStart(),
+                                         "static_cast<" + TypeStr + ">(")
+          << CodeModificationHint::CreateInsertion(
+                            S.PP.getLocForEndOfToken(CondExpr->getLocEnd()),
+                               ")");
+        S.Diag(ExplicitConversions[0]->getLocation(),
+             diag::note_switch_conversion)
+          << ConvTy->isEnumeralType() << ConvTy;
+
+        // If we aren't in a SFINAE context, build a call to the 
+        // explicit conversion function.
+        if (S.isSFINAEContext())
+          return true;
+
+        CondExpr = S.BuildCXXMemberCallExpr(CondExpr, ExplicitConversions[0]);
+      }
+
+      // We'll complain below about a non-integral condition type.
+      break;
+
+    case 1:
+      // Apply this conversion.
+      CondExpr = S.BuildCXXMemberCallExpr(CondExpr, ViableConversions[0]);
+      break;
+
+    default:
+      S.Diag(SwitchLoc, diag::err_switch_multiple_conversions)
+        << CondType << CondExpr->getSourceRange();
+      for (unsigned I = 0, N = ViableConversions.size(); I != N; ++I) {
+        QualType ConvTy
+          = ViableConversions[I]->getConversionType().getNonReferenceType();
+        S.Diag(ViableConversions[I]->getLocation(),
+             diag::note_switch_conversion)
+          << ConvTy->isEnumeralType() << ConvTy;
+      }
+      return true;
+    }
+  } 
+
+  return false;
+}
+
+/// ActOnSwitchBodyError - This is called if there is an error parsing the
+/// body of the switch stmt instead of ActOnFinishSwitchStmt.
+void Sema::ActOnSwitchBodyError(SourceLocation SwitchLoc, StmtArg Switch,
+                                StmtArg Body) {
+  // Keep the switch stack balanced.
+  assert(getSwitchStack().back() == (SwitchStmt*)Switch.get() &&
+         "switch stack missing push/pop!");
+  getSwitchStack().pop_back();
+}
+
+Action::OwningStmtResult
+Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, StmtArg Switch,
+                            StmtArg Body) {
+  Stmt *BodyStmt = Body.takeAs<Stmt>();
+
+  SwitchStmt *SS = getSwitchStack().back();
+  assert(SS == (SwitchStmt*)Switch.get() && "switch stack missing push/pop!");
+
+  SS->setBody(BodyStmt, SwitchLoc);
+  getSwitchStack().pop_back();
+
+  if (SS->getCond() == 0) {
+    SS->Destroy(Context);
+    return StmtError();
+  }
+    
+  Expr *CondExpr = SS->getCond();
+  QualType CondTypeBeforePromotion =
+      GetTypeBeforeIntegralPromotion(CondExpr);
+
+  if (getLangOptions().CPlusPlus &&
+      CheckCXXSwitchCondition(*this, SwitchLoc, CondExpr))
+    return StmtError();
+
+  // C99 6.8.4.2p5 - Integer promotions are performed on the controlling expr.
+  UsualUnaryConversions(CondExpr);
+  QualType CondType = CondExpr->getType();
+  SS->setCond(CondExpr);
+
+  // C++ 6.4.2.p2:
+  // Integral promotions are performed (on the switch condition).
+  //
+  // A case value unrepresentable by the original switch condition
+  // type (before the promotion) doesn't make sense, even when it can
+  // be represented by the promoted type.  Therefore we need to find
+  // the pre-promotion type of the switch condition.
+  if (!CondExpr->isTypeDependent()) {
+    if (!CondType->isIntegerType()) { // C99 6.8.4.2p1
+      Diag(SwitchLoc, diag::err_typecheck_statement_requires_integer)
+          << CondType << CondExpr->getSourceRange();
+      return StmtError();
+    }
+
+    if (CondTypeBeforePromotion->isBooleanType()) {
+      // switch(bool_expr) {...} is often a programmer error, e.g.
+      //   switch(n && mask) { ... }  // Doh - should be "n & mask".
+      // One can always use an if statement instead of switch(bool_expr).
+      Diag(SwitchLoc, diag::warn_bool_switch_condition)
+          << CondExpr->getSourceRange();
+    }
+  }
+
+  // Get the bitwidth of the switched-on value before promotions.  We must
+  // convert the integer case values to this width before comparison.
+  bool HasDependentValue
+    = CondExpr->isTypeDependent() || CondExpr->isValueDependent();
+  unsigned CondWidth
+    = HasDependentValue? 0
+      : static_cast<unsigned>(Context.getTypeSize(CondTypeBeforePromotion));
+  bool CondIsSigned = CondTypeBeforePromotion->isSignedIntegerType();
+
+  // Accumulate all of the case values in a vector so that we can sort them
+  // and detect duplicates.  This vector contains the APInt for the case after
+  // it has been converted to the condition type.
+  typedef llvm::SmallVector<std::pair<llvm::APSInt, CaseStmt*>, 64> CaseValsTy;
+  CaseValsTy CaseVals;
+
+  // Keep track of any GNU case ranges we see.  The APSInt is the low value.
+  typedef std::vector<std::pair<llvm::APSInt, CaseStmt*> > CaseRangesTy;
+  CaseRangesTy CaseRanges;
+
+  DefaultStmt *TheDefaultStmt = 0;
+
+  bool CaseListIsErroneous = false;
+
+  for (SwitchCase *SC = SS->getSwitchCaseList(); SC && !HasDependentValue;
+       SC = SC->getNextSwitchCase()) {
+
+    if (DefaultStmt *DS = dyn_cast<DefaultStmt>(SC)) {
+      if (TheDefaultStmt) {
+        Diag(DS->getDefaultLoc(), diag::err_multiple_default_labels_defined);
+        Diag(TheDefaultStmt->getDefaultLoc(), diag::note_duplicate_case_prev);
+
+        // FIXME: Remove the default statement from the switch block so that
+        // we'll return a valid AST.  This requires recursing down the AST and
+        // finding it, not something we are set up to do right now.  For now,
+        // just lop the entire switch stmt out of the AST.
+        CaseListIsErroneous = true;
+      }
+      TheDefaultStmt = DS;
+
+    } else {
+      CaseStmt *CS = cast<CaseStmt>(SC);
+
+      // We already verified that the expression has a i-c-e value (C99
+      // 6.8.4.2p3) - get that value now.
+      Expr *Lo = CS->getLHS();
+
+      if (Lo->isTypeDependent() || Lo->isValueDependent()) {
+        HasDependentValue = true;
+        break;
+      }
+
+      llvm::APSInt LoVal = Lo->EvaluateAsInt(Context);
+
+      // Convert the value to the same width/sign as the condition.
+      ConvertIntegerToTypeWarnOnOverflow(LoVal, CondWidth, CondIsSigned,
+                                         CS->getLHS()->getLocStart(),
+                                         diag::warn_case_value_overflow);
+
+      // If the LHS is not the same type as the condition, insert an implicit
+      // cast.
+      ImpCastExprToType(Lo, CondType, CastExpr::CK_IntegralCast);
+      CS->setLHS(Lo);
+
+      // If this is a case range, remember it in CaseRanges, otherwise CaseVals.
+      if (CS->getRHS()) {
+        if (CS->getRHS()->isTypeDependent() ||
+            CS->getRHS()->isValueDependent()) {
+          HasDependentValue = true;
+          break;
+        }
+        CaseRanges.push_back(std::make_pair(LoVal, CS));
+      } else
+        CaseVals.push_back(std::make_pair(LoVal, CS));
+    }
+  }
+
+  if (!HasDependentValue) {
+    // Sort all the scalar case values so we can easily detect duplicates.
+    std::stable_sort(CaseVals.begin(), CaseVals.end(), CmpCaseVals);
+
+    if (!CaseVals.empty()) {
+      for (unsigned i = 0, e = CaseVals.size()-1; i != e; ++i) {
+        if (CaseVals[i].first == CaseVals[i+1].first) {
+          // If we have a duplicate, report it.
+          Diag(CaseVals[i+1].second->getLHS()->getLocStart(),
+               diag::err_duplicate_case) << CaseVals[i].first.toString(10);
+          Diag(CaseVals[i].second->getLHS()->getLocStart(),
+               diag::note_duplicate_case_prev);
+          // FIXME: We really want to remove the bogus case stmt from the
+          // substmt, but we have no way to do this right now.
+          CaseListIsErroneous = true;
+        }
+      }
+    }
+
+    // Detect duplicate case ranges, which usually don't exist at all in
+    // the first place.
+    if (!CaseRanges.empty()) {
+      // Sort all the case ranges by their low value so we can easily detect
+      // overlaps between ranges.
+      std::stable_sort(CaseRanges.begin(), CaseRanges.end());
+
+      // Scan the ranges, computing the high values and removing empty ranges.
+      std::vector<llvm::APSInt> HiVals;
+      for (unsigned i = 0, e = CaseRanges.size(); i != e; ++i) {
+        CaseStmt *CR = CaseRanges[i].second;
+        Expr *Hi = CR->getRHS();
+        llvm::APSInt HiVal = Hi->EvaluateAsInt(Context);
+
+        // Convert the value to the same width/sign as the condition.
+        ConvertIntegerToTypeWarnOnOverflow(HiVal, CondWidth, CondIsSigned,
+                                           CR->getRHS()->getLocStart(),
+                                           diag::warn_case_value_overflow);
+
+        // If the LHS is not the same type as the condition, insert an implicit
+        // cast.
+        ImpCastExprToType(Hi, CondType, CastExpr::CK_IntegralCast);
+        CR->setRHS(Hi);
+
+        // If the low value is bigger than the high value, the case is empty.
+        if (CaseRanges[i].first > HiVal) {
+          Diag(CR->getLHS()->getLocStart(), diag::warn_case_empty_range)
+            << SourceRange(CR->getLHS()->getLocStart(),
+                           CR->getRHS()->getLocEnd());
+          CaseRanges.erase(CaseRanges.begin()+i);
+          --i, --e;
+          continue;
+        }
+        HiVals.push_back(HiVal);
+      }
+
+      // Rescan the ranges, looking for overlap with singleton values and other
+      // ranges.  Since the range list is sorted, we only need to compare case
+      // ranges with their neighbors.
+      for (unsigned i = 0, e = CaseRanges.size(); i != e; ++i) {
+        llvm::APSInt &CRLo = CaseRanges[i].first;
+        llvm::APSInt &CRHi = HiVals[i];
+        CaseStmt *CR = CaseRanges[i].second;
+
+        // Check to see whether the case range overlaps with any
+        // singleton cases.
+        CaseStmt *OverlapStmt = 0;
+        llvm::APSInt OverlapVal(32);
+
+        // Find the smallest value >= the lower bound.  If I is in the
+        // case range, then we have overlap.
+        CaseValsTy::iterator I = std::lower_bound(CaseVals.begin(),
+                                                  CaseVals.end(), CRLo,
+                                                  CaseCompareFunctor());
+        if (I != CaseVals.end() && I->first < CRHi) {
+          OverlapVal  = I->first;   // Found overlap with scalar.
+          OverlapStmt = I->second;
+        }
+
+        // Find the smallest value bigger than the upper bound.
+        I = std::upper_bound(I, CaseVals.end(), CRHi, CaseCompareFunctor());
+        if (I != CaseVals.begin() && (I-1)->first >= CRLo) {
+          OverlapVal  = (I-1)->first;      // Found overlap with scalar.
+          OverlapStmt = (I-1)->second;
+        }
+
+        // Check to see if this case stmt overlaps with the subsequent
+        // case range.
+        if (i && CRLo <= HiVals[i-1]) {
+          OverlapVal  = HiVals[i-1];       // Found overlap with range.
+          OverlapStmt = CaseRanges[i-1].second;
+        }
+
+        if (OverlapStmt) {
+          // If we have a duplicate, report it.
+          Diag(CR->getLHS()->getLocStart(), diag::err_duplicate_case)
+            << OverlapVal.toString(10);
+          Diag(OverlapStmt->getLHS()->getLocStart(),
+               diag::note_duplicate_case_prev);
+          // FIXME: We really want to remove the bogus case stmt from the
+          // substmt, but we have no way to do this right now.
+          CaseListIsErroneous = true;
+        }
+      }
+    }
+
+    // Check to see if switch is over an Enum and handles all of its 
+    // values  
+    const EnumType* ET = dyn_cast<EnumType>(CondTypeBeforePromotion);
+    // If switch has default case, then ignore it.
+    if (!CaseListIsErroneous && !TheDefaultStmt && ET) {
+      const EnumDecl *ED = ET->getDecl();
+      typedef llvm::SmallVector<std::pair<llvm::APSInt, EnumConstantDecl*>, 64> EnumValsTy;
+      EnumValsTy EnumVals;
+
+      // Gather all enum values, set their type and sort them, allowing easier comparison 
+      // with CaseVals.
+      for (EnumDecl::enumerator_iterator EDI = ED->enumerator_begin(); EDI != ED->enumerator_end(); EDI++) {
+        llvm::APSInt Val = (*EDI)->getInitVal();
+        if(Val.getBitWidth() < CondWidth)
+          Val.extend(CondWidth);
+        Val.setIsSigned(CondIsSigned);
+        EnumVals.push_back(std::make_pair(Val, (*EDI)));
+      }
+      std::stable_sort(EnumVals.begin(), EnumVals.end(), CmpEnumVals);
+      EnumValsTy::iterator EIend = std::unique(EnumVals.begin(), EnumVals.end(), EqEnumVals);
+      // See which case values aren't in enum 
+      EnumValsTy::const_iterator EI = EnumVals.begin();
+      for (CaseValsTy::const_iterator CI = CaseVals.begin(); CI != CaseVals.end(); CI++) {
+        while (EI != EIend && EI->first < CI->first)
+          EI++;
+        if (EI == EIend || EI->first > CI->first)
+            Diag(CI->second->getLHS()->getExprLoc(), diag::not_in_enum) << ED->getDeclName();
+      }
+      // See which of case ranges aren't in enum
+      EI = EnumVals.begin();
+      for (CaseRangesTy::const_iterator RI = CaseRanges.begin(); RI != CaseRanges.end() && EI != EIend; RI++) {
+        while (EI != EIend && EI->first < RI->first)
+          EI++;
+        
+        if (EI == EIend || EI->first != RI->first) {
+          Diag(RI->second->getLHS()->getExprLoc(), diag::not_in_enum) << ED->getDeclName();
+        }
+
+        llvm::APSInt Hi = RI->second->getRHS()->EvaluateAsInt(Context);
+        while (EI != EIend && EI->first < Hi)
+          EI++;
+        if (EI == EIend || EI->first != Hi)
+          Diag(RI->second->getRHS()->getExprLoc(), diag::not_in_enum) << ED->getDeclName();
+      }
+      //Check which enum vals aren't in switch
+      CaseValsTy::const_iterator CI = CaseVals.begin();
+      CaseRangesTy::const_iterator RI = CaseRanges.begin();
+      EI = EnumVals.begin();
+      for (; EI != EIend; EI++) {
+        //Drop unneeded case values
+        llvm::APSInt CIVal;
+        while (CI != CaseVals.end() && CI->first < EI->first)
+          CI++;
+        
+        if (CI != CaseVals.end() && CI->first == EI->first)
+          continue;
+
+        //Drop unneeded case ranges
+        for (; RI != CaseRanges.end(); RI++) {
+          llvm::APSInt Hi = RI->second->getRHS()->EvaluateAsInt(Context);
+          if (EI->first <= Hi)
+            break;
+        }
+
+        if (RI == CaseRanges.end() || EI->first < RI->first)
+          Diag(CondExpr->getExprLoc(), diag::warn_missing_cases) << EI->second->getDeclName();
+      }
+    }
+  }
+
+  // FIXME: If the case list was broken is some way, we don't have a good system
+  // to patch it up.  Instead, just return the whole substmt as broken.
+  if (CaseListIsErroneous)
+    return StmtError();
+
+  Switch.release();
+  return Owned(SS);
+}
+
+Action::OwningStmtResult
+Sema::ActOnWhileStmt(SourceLocation WhileLoc, FullExprArg Cond, 
+                     DeclPtrTy CondVar, StmtArg Body) {
+  OwningExprResult CondResult(Cond.release());
+  
+  VarDecl *ConditionVar = 0;
+  if (CondVar.get()) {
+    ConditionVar = CondVar.getAs<VarDecl>();
+    CondResult = CheckConditionVariable(ConditionVar);
+    if (CondResult.isInvalid())
+      return StmtError();
+  }
+  Expr *ConditionExpr = CondResult.takeAs<Expr>();
+  if (!ConditionExpr)
+    return StmtError();
+  
+  if (CheckBooleanCondition(ConditionExpr, WhileLoc)) {
+    CondResult = ConditionExpr;
+    return StmtError();
+  }
+
+  Stmt *bodyStmt = Body.takeAs<Stmt>();
+  DiagnoseUnusedExprResult(bodyStmt);
+
+  CondResult.release();
+  return Owned(new (Context) WhileStmt(ConditionVar, ConditionExpr, bodyStmt, 
+                                       WhileLoc));
+}
+
+Action::OwningStmtResult
+Sema::ActOnDoStmt(SourceLocation DoLoc, StmtArg Body,
+                  SourceLocation WhileLoc, SourceLocation CondLParen,
+                  ExprArg Cond, SourceLocation CondRParen) {
+  Expr *condExpr = Cond.takeAs<Expr>();
+  assert(condExpr && "ActOnDoStmt(): missing expression");
+
+  if (CheckBooleanCondition(condExpr, DoLoc)) {
+    Cond = condExpr;
+    return StmtError();
+  }
+
+  Stmt *bodyStmt = Body.takeAs<Stmt>();
+  DiagnoseUnusedExprResult(bodyStmt);
+
+  Cond.release();
+  return Owned(new (Context) DoStmt(bodyStmt, condExpr, DoLoc,
+                                    WhileLoc, CondRParen));
+}
+
+Action::OwningStmtResult
+Sema::ActOnForStmt(SourceLocation ForLoc, SourceLocation LParenLoc,
+                   StmtArg first, FullExprArg second, DeclPtrTy secondVar,
+                   FullExprArg third,
+                   SourceLocation RParenLoc, StmtArg body) {
+  Stmt *First  = static_cast<Stmt*>(first.get());
+
+  if (!getLangOptions().CPlusPlus) {
+    if (DeclStmt *DS = dyn_cast_or_null<DeclStmt>(First)) {
+      // C99 6.8.5p3: The declaration part of a 'for' statement shall only
+      // declare identifiers for objects having storage class 'auto' or
+      // 'register'.
+      for (DeclStmt::decl_iterator DI=DS->decl_begin(), DE=DS->decl_end();
+           DI!=DE; ++DI) {
+        VarDecl *VD = dyn_cast<VarDecl>(*DI);
+        if (VD && VD->isBlockVarDecl() && !VD->hasLocalStorage())
+          VD = 0;
+        if (VD == 0)
+          Diag((*DI)->getLocation(), diag::err_non_variable_decl_in_for);
+        // FIXME: mark decl erroneous!
+      }
+    }
+  }
+
+  OwningExprResult SecondResult(second.release());
+  VarDecl *ConditionVar = 0;
+  if (secondVar.get()) {
+    ConditionVar = secondVar.getAs<VarDecl>();
+    SecondResult = CheckConditionVariable(ConditionVar);
+    if (SecondResult.isInvalid())
+      return StmtError();
+  }
+  
+  Expr *Second = SecondResult.takeAs<Expr>();
+  if (Second && CheckBooleanCondition(Second, ForLoc)) {
+    SecondResult = Second;
+    return StmtError();
+  }
+
+  Expr *Third  = third.release().takeAs<Expr>();
+  Stmt *Body  = static_cast<Stmt*>(body.get());
+  
+  DiagnoseUnusedExprResult(First);
+  DiagnoseUnusedExprResult(Third);
+  DiagnoseUnusedExprResult(Body);
+
+  first.release();
+  body.release();
+  return Owned(new (Context) ForStmt(First, Second, ConditionVar, Third, Body, 
+                                     ForLoc, LParenLoc, RParenLoc));
+}
+
+Action::OwningStmtResult
+Sema::ActOnObjCForCollectionStmt(SourceLocation ForLoc,
+                                 SourceLocation LParenLoc,
+                                 StmtArg first, ExprArg second,
+                                 SourceLocation RParenLoc, StmtArg body) {
+  Stmt *First  = static_cast<Stmt*>(first.get());
+  Expr *Second = static_cast<Expr*>(second.get());
+  Stmt *Body  = static_cast<Stmt*>(body.get());
+  if (First) {
+    QualType FirstType;
+    if (DeclStmt *DS = dyn_cast<DeclStmt>(First)) {
+      if (!DS->isSingleDecl())
+        return StmtError(Diag((*DS->decl_begin())->getLocation(),
+                         diag::err_toomany_element_decls));
+
+      Decl *D = DS->getSingleDecl();
+      FirstType = cast<ValueDecl>(D)->getType();
+      // C99 6.8.5p3: The declaration part of a 'for' statement shall only
+      // declare identifiers for objects having storage class 'auto' or
+      // 'register'.
+      VarDecl *VD = cast<VarDecl>(D);
+      if (VD->isBlockVarDecl() && !VD->hasLocalStorage())
+        return StmtError(Diag(VD->getLocation(),
+                              diag::err_non_variable_decl_in_for));
+    } else {
+      if (cast<Expr>(First)->isLvalue(Context) != Expr::LV_Valid)
+        return StmtError(Diag(First->getLocStart(),
+                   diag::err_selector_element_not_lvalue)
+          << First->getSourceRange());
+
+      FirstType = static_cast<Expr*>(First)->getType();
+    }
+    if (!FirstType->isObjCObjectPointerType() &&
+        !FirstType->isBlockPointerType())
+        Diag(ForLoc, diag::err_selector_element_type)
+          << FirstType << First->getSourceRange();
+  }
+  if (Second) {
+    DefaultFunctionArrayLvalueConversion(Second);
+    QualType SecondType = Second->getType();
+    if (!SecondType->isObjCObjectPointerType())
+      Diag(ForLoc, diag::err_collection_expr_type)
+        << SecondType << Second->getSourceRange();
+  }
+  first.release();
+  second.release();
+  body.release();
+  return Owned(new (Context) ObjCForCollectionStmt(First, Second, Body,
+                                                   ForLoc, RParenLoc));
+}
+
+Action::OwningStmtResult
+Sema::ActOnGotoStmt(SourceLocation GotoLoc, SourceLocation LabelLoc,
+                    IdentifierInfo *LabelII) {
+  // Look up the record for this label identifier.
+  LabelStmt *&LabelDecl = getLabelMap()[LabelII];
+
+  // If we haven't seen this label yet, create a forward reference.
+  if (LabelDecl == 0)
+    LabelDecl = new (Context) LabelStmt(LabelLoc, LabelII, 0);
+
+  return Owned(new (Context) GotoStmt(LabelDecl, GotoLoc, LabelLoc));
+}
+
+Action::OwningStmtResult
+Sema::ActOnIndirectGotoStmt(SourceLocation GotoLoc, SourceLocation StarLoc,
+                            ExprArg DestExp) {
+  // Convert operand to void*
+  Expr* E = DestExp.takeAs<Expr>();
+  if (!E->isTypeDependent()) {
+    QualType ETy = E->getType();
+    QualType DestTy = Context.getPointerType(Context.VoidTy.withConst());
+    AssignConvertType ConvTy =
+      CheckSingleAssignmentConstraints(DestTy, E);
+    if (DiagnoseAssignmentResult(ConvTy, StarLoc, DestTy, ETy, E, AA_Passing))
+      return StmtError();
+  }
+  return Owned(new (Context) IndirectGotoStmt(GotoLoc, StarLoc, E));
+}
+
+Action::OwningStmtResult
+Sema::ActOnContinueStmt(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.
+    return StmtError(Diag(ContinueLoc, diag::err_continue_not_in_loop));
+  }
+
+  return Owned(new (Context) ContinueStmt(ContinueLoc));
+}
+
+Action::OwningStmtResult
+Sema::ActOnBreakStmt(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.
+    return StmtError(Diag(BreakLoc, diag::err_break_not_in_loop_or_switch));
+  }
+
+  return Owned(new (Context) BreakStmt(BreakLoc));
+}
+
+/// ActOnBlockReturnStmt - Utility routine to figure out block's return type.
+///
+Action::OwningStmtResult
+Sema::ActOnBlockReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) {
+  // If this is the first return we've seen in the block, infer the type of
+  // the block from it.
+  if (CurBlock->ReturnType.isNull()) {
+    if (RetValExp) {
+      // Don't call UsualUnaryConversions(), since we don't want to do
+      // integer promotions here.
+      DefaultFunctionArrayLvalueConversion(RetValExp);
+      CurBlock->ReturnType = RetValExp->getType();
+      if (BlockDeclRefExpr *CDRE = dyn_cast<BlockDeclRefExpr>(RetValExp)) {
+        // We have to remove a 'const' added to copied-in variable which was
+        // part of the implementation spec. and not the actual qualifier for
+        // the variable.
+        if (CDRE->isConstQualAdded())
+           CurBlock->ReturnType.removeConst();
+      }
+    } else
+      CurBlock->ReturnType = Context.VoidTy;
+  }
+  QualType FnRetType = CurBlock->ReturnType;
+
+  if (CurBlock->TheDecl->hasAttr<NoReturnAttr>()) {
+    Diag(ReturnLoc, diag::err_noreturn_block_has_return_expr)
+      << getCurFunctionOrMethodDecl()->getDeclName();
+    return StmtError();
+  }
+
+  // Otherwise, verify that this result type matches the previous one.  We are
+  // pickier with blocks than for normal functions because we don't have GCC
+  // compatibility to worry about here.
+  if (CurBlock->ReturnType->isVoidType()) {
+    if (RetValExp) {
+      Diag(ReturnLoc, diag::err_return_block_has_expr);
+      RetValExp->Destroy(Context);
+      RetValExp = 0;
+    }
+    return Owned(new (Context) ReturnStmt(ReturnLoc, RetValExp));
+  }
+
+  if (!RetValExp)
+    return StmtError(Diag(ReturnLoc, diag::err_block_return_missing_expr));
+
+  if (!FnRetType->isDependentType() && !RetValExp->isTypeDependent()) {
+    // we have a non-void block with an expression, continue checking
+
+    // 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.
+
+    // In C++ the return statement is handled via a copy initialization.
+    // the C version of which boils down to CheckSingleAssignmentConstraints.
+    OwningExprResult Res = PerformCopyInitialization(
+                             InitializedEntity::InitializeResult(ReturnLoc, 
+                                                                 FnRetType),
+                             SourceLocation(),
+                             Owned(RetValExp));
+    if (Res.isInvalid()) {
+      // FIXME: Cleanup temporaries here, anyway?
+      return StmtError();
+    }
+    
+    RetValExp = Res.takeAs<Expr>();
+    if (RetValExp) 
+      CheckReturnStackAddr(RetValExp, FnRetType, ReturnLoc);
+  }
+
+  return Owned(new (Context) ReturnStmt(ReturnLoc, RetValExp));
+}
+
+/// IsReturnCopyElidable - Whether returning @p RetExpr from a function that
+/// returns a @p RetType fulfills the criteria for copy elision (C++0x 12.8p15).
+static bool IsReturnCopyElidable(ASTContext &Ctx, QualType RetType,
+                                 Expr *RetExpr) {
+  QualType ExprType = RetExpr->getType();
+  // - in a return statement in a function with ...
+  // ... a class return type ...
+  if (!RetType->isRecordType())
+    return false;
+  // ... the same cv-unqualified type as the function return type ...
+  if (!Ctx.hasSameUnqualifiedType(RetType, ExprType))
+    return false;
+  // ... the expression is the name of a non-volatile automatic object ...
+  // We ignore parentheses here.
+  // FIXME: Is this compliant?
+  const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(RetExpr->IgnoreParens());
+  if (!DR)
+    return false;
+  const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl());
+  if (!VD)
+    return false;
+  return VD->hasLocalStorage() && !VD->getType()->isReferenceType()
+    && !VD->getType().isVolatileQualified();
+}
+
+Action::OwningStmtResult
+Sema::ActOnReturnStmt(SourceLocation ReturnLoc, ExprArg rex) {
+  Expr *RetValExp = rex.takeAs<Expr>();
+  if (CurBlock)
+    return ActOnBlockReturnStmt(ReturnLoc, RetValExp);
+
+  QualType FnRetType;
+  if (const FunctionDecl *FD = getCurFunctionDecl()) {
+    FnRetType = FD->getResultType();
+    if (FD->hasAttr<NoReturnAttr>() ||
+        FD->getType()->getAs<FunctionType>()->getNoReturnAttr())
+      Diag(ReturnLoc, diag::warn_noreturn_function_has_return_expr)
+        << getCurFunctionOrMethodDecl()->getDeclName();
+  } else if (ObjCMethodDecl *MD = getCurMethodDecl())
+    FnRetType = MD->getResultType();
+  else // If we don't have a function/method context, bail.
+    return StmtError();
+
+  if (FnRetType->isVoidType()) {
+    if (RetValExp && !RetValExp->isTypeDependent()) {
+      // C99 6.8.6.4p1 (ext_ since GCC warns)
+      unsigned D = diag::ext_return_has_expr;
+      if (RetValExp->getType()->isVoidType())
+        D = diag::ext_return_has_void_expr;
+
+      // return (some void expression); is legal in C++.
+      if (D != diag::ext_return_has_void_expr ||
+          !getLangOptions().CPlusPlus) {
+        NamedDecl *CurDecl = getCurFunctionOrMethodDecl();
+        Diag(ReturnLoc, D)
+          << CurDecl->getDeclName() << isa<ObjCMethodDecl>(CurDecl)
+          << RetValExp->getSourceRange();
+      }
+
+      RetValExp = MaybeCreateCXXExprWithTemporaries(RetValExp);
+    }
+    return Owned(new (Context) ReturnStmt(ReturnLoc, RetValExp));
+  }
+
+  if (!RetValExp && !FnRetType->isDependentType()) {
+    unsigned DiagID = diag::warn_return_missing_expr;  // C90 6.6.6.4p4
+    // C99 6.8.6.4p1 (ext_ since GCC warns)
+    if (getLangOptions().C99) DiagID = diag::ext_return_missing_expr;
+
+    if (FunctionDecl *FD = getCurFunctionDecl())
+      Diag(ReturnLoc, DiagID) << FD->getIdentifier() << 0/*fn*/;
+    else
+      Diag(ReturnLoc, DiagID) << getCurMethodDecl()->getDeclName() << 1/*meth*/;
+    return Owned(new (Context) ReturnStmt(ReturnLoc, (Expr*)0));
+  }
+
+  if (!FnRetType->isDependentType() && !RetValExp->isTypeDependent()) {
+    // we have a non-void function with an expression, continue checking
+
+    // 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.
+
+    // C++0x 12.8p15: When certain criteria are met, an implementation is
+    //   allowed to omit the copy construction of a class object, [...]
+    //   - in a return statement in a function with a class return type, when
+    //     the expression is the name of a non-volatile automatic object with
+    //     the same cv-unqualified type as the function return type, the copy
+    //     operation can be omitted [...]
+    // C++0x 12.8p16: When the criteria for elision of a copy operation are met
+    //   and the object to be copied is designated by an lvalue, overload
+    //   resolution to select the constructor for the copy is first performed
+    //   as if the object were designated by an rvalue.
+    // Note that we only compute Elidable if we're in C++0x, since we don't
+    // care otherwise.
+    bool Elidable = getLangOptions().CPlusPlus0x ?
+                      IsReturnCopyElidable(Context, FnRetType, RetValExp) :
+                      false;
+    // FIXME: Elidable
+    (void)Elidable;
+
+    // In C++ the return statement is handled via a copy initialization.
+    // the C version of which boils down to CheckSingleAssignmentConstraints.
+    OwningExprResult Res = PerformCopyInitialization(
+                             InitializedEntity::InitializeResult(ReturnLoc, 
+                                                                 FnRetType),
+                             SourceLocation(),
+                             Owned(RetValExp));
+    if (Res.isInvalid()) {
+      // FIXME: Cleanup temporaries here, anyway?
+      return StmtError();
+    }
+
+    RetValExp = Res.takeAs<Expr>();
+    if (RetValExp) 
+      CheckReturnStackAddr(RetValExp, FnRetType, ReturnLoc);
+  }
+
+  if (RetValExp)
+    RetValExp = MaybeCreateCXXExprWithTemporaries(RetValExp);
+  return Owned(new (Context) ReturnStmt(ReturnLoc, RetValExp));
+}
+
+/// CheckAsmLValue - GNU C has an extremely ugly extension whereby they silently
+/// ignore "noop" casts in places where an lvalue is required by an inline asm.
+/// We emulate this behavior when -fheinous-gnu-extensions is specified, but
+/// provide a strong guidance to not use it.
+///
+/// This method checks to see if the argument is an acceptable l-value and
+/// returns false if it is a case we can handle.
+static bool CheckAsmLValue(const Expr *E, Sema &S) {
+  // Type dependent expressions will be checked during instantiation.
+  if (E->isTypeDependent())
+    return false;
+  
+  if (E->isLvalue(S.Context) == Expr::LV_Valid)
+    return false;  // Cool, this is an lvalue.
+
+  // Okay, this is not an lvalue, but perhaps it is the result of a cast that we
+  // are supposed to allow.
+  const Expr *E2 = E->IgnoreParenNoopCasts(S.Context);
+  if (E != E2 && E2->isLvalue(S.Context) == Expr::LV_Valid) {
+    if (!S.getLangOptions().HeinousExtensions)
+      S.Diag(E2->getLocStart(), diag::err_invalid_asm_cast_lvalue)
+        << E->getSourceRange();
+    else
+      S.Diag(E2->getLocStart(), diag::warn_invalid_asm_cast_lvalue)
+        << E->getSourceRange();
+    // Accept, even if we emitted an error diagnostic.
+    return false;
+  }
+
+  // None of the above, just randomly invalid non-lvalue.
+  return true;
+}
+
+
+Sema::OwningStmtResult Sema::ActOnAsmStmt(SourceLocation AsmLoc,
+                                          bool IsSimple,
+                                          bool IsVolatile,
+                                          unsigned NumOutputs,
+                                          unsigned NumInputs,
+                                          IdentifierInfo **Names,
+                                          MultiExprArg constraints,
+                                          MultiExprArg exprs,
+                                          ExprArg asmString,
+                                          MultiExprArg clobbers,
+                                          SourceLocation RParenLoc,
+                                          bool MSAsm) {
+  unsigned NumClobbers = clobbers.size();
+  StringLiteral **Constraints =
+    reinterpret_cast<StringLiteral**>(constraints.get());
+  Expr **Exprs = reinterpret_cast<Expr **>(exprs.get());
+  StringLiteral *AsmString = cast<StringLiteral>((Expr *)asmString.get());
+  StringLiteral **Clobbers = reinterpret_cast<StringLiteral**>(clobbers.get());
+
+  llvm::SmallVector<TargetInfo::ConstraintInfo, 4> OutputConstraintInfos;
+
+  // The parser verifies that there is a string literal here.
+  if (AsmString->isWide())
+    return StmtError(Diag(AsmString->getLocStart(),diag::err_asm_wide_character)
+      << AsmString->getSourceRange());
+
+  for (unsigned i = 0; i != NumOutputs; i++) {
+    StringLiteral *Literal = Constraints[i];
+    if (Literal->isWide())
+      return StmtError(Diag(Literal->getLocStart(),diag::err_asm_wide_character)
+        << Literal->getSourceRange());
+
+    llvm::StringRef OutputName;
+    if (Names[i])
+      OutputName = Names[i]->getName();
+
+    TargetInfo::ConstraintInfo Info(Literal->getString(), OutputName);
+    if (!Context.Target.validateOutputConstraint(Info))
+      return StmtError(Diag(Literal->getLocStart(),
+                            diag::err_asm_invalid_output_constraint)
+                       << Info.getConstraintStr());
+
+    // Check that the output exprs are valid lvalues.
+    Expr *OutputExpr = Exprs[i];
+    if (CheckAsmLValue(OutputExpr, *this)) {
+      return StmtError(Diag(OutputExpr->getLocStart(),
+                  diag::err_asm_invalid_lvalue_in_output)
+        << OutputExpr->getSourceRange());
+    }
+
+    OutputConstraintInfos.push_back(Info);
+  }
+
+  llvm::SmallVector<TargetInfo::ConstraintInfo, 4> InputConstraintInfos;
+
+  for (unsigned i = NumOutputs, e = NumOutputs + NumInputs; i != e; i++) {
+    StringLiteral *Literal = Constraints[i];
+    if (Literal->isWide())
+      return StmtError(Diag(Literal->getLocStart(),diag::err_asm_wide_character)
+        << Literal->getSourceRange());
+
+    llvm::StringRef InputName;
+    if (Names[i])
+      InputName = Names[i]->getName();
+
+    TargetInfo::ConstraintInfo Info(Literal->getString(), InputName);
+    if (!Context.Target.validateInputConstraint(OutputConstraintInfos.data(),
+                                                NumOutputs, Info)) {
+      return StmtError(Diag(Literal->getLocStart(),
+                            diag::err_asm_invalid_input_constraint)
+                       << Info.getConstraintStr());
+    }
+
+    Expr *InputExpr = Exprs[i];
+
+    // Only allow void types for memory constraints.
+    if (Info.allowsMemory() && !Info.allowsRegister()) {
+      if (CheckAsmLValue(InputExpr, *this))
+        return StmtError(Diag(InputExpr->getLocStart(),
+                              diag::err_asm_invalid_lvalue_in_input)
+                         << Info.getConstraintStr()
+                         << InputExpr->getSourceRange());
+    }
+
+    if (Info.allowsRegister()) {
+      if (InputExpr->getType()->isVoidType()) {
+        return StmtError(Diag(InputExpr->getLocStart(),
+                              diag::err_asm_invalid_type_in_input)
+          << InputExpr->getType() << Info.getConstraintStr()
+          << InputExpr->getSourceRange());
+      }
+    }
+
+    DefaultFunctionArrayLvalueConversion(Exprs[i]);
+
+    InputConstraintInfos.push_back(Info);
+  }
+
+  // Check that the clobbers are valid.
+  for (unsigned i = 0; i != NumClobbers; i++) {
+    StringLiteral *Literal = Clobbers[i];
+    if (Literal->isWide())
+      return StmtError(Diag(Literal->getLocStart(),diag::err_asm_wide_character)
+        << Literal->getSourceRange());
+
+    llvm::StringRef Clobber = Literal->getString();
+
+    if (!Context.Target.isValidGCCRegisterName(Clobber))
+      return StmtError(Diag(Literal->getLocStart(),
+                  diag::err_asm_unknown_register_name) << Clobber);
+  }
+
+  constraints.release();
+  exprs.release();
+  asmString.release();
+  clobbers.release();
+  AsmStmt *NS =
+    new (Context) AsmStmt(Context, AsmLoc, IsSimple, IsVolatile, MSAsm, 
+                          NumOutputs, NumInputs, Names, Constraints, Exprs, 
+                          AsmString, NumClobbers, Clobbers, RParenLoc);
+  // Validate the asm string, ensuring it makes sense given the operands we
+  // have.
+  llvm::SmallVector<AsmStmt::AsmStringPiece, 8> Pieces;
+  unsigned DiagOffs;
+  if (unsigned DiagID = NS->AnalyzeAsmString(Pieces, Context, DiagOffs)) {
+    Diag(getLocationOfStringLiteralByte(AsmString, DiagOffs), DiagID)
+           << AsmString->getSourceRange();
+    DeleteStmt(NS);
+    return StmtError();
+  }
+
+  // Validate tied input operands for type mismatches.
+  for (unsigned i = 0, e = InputConstraintInfos.size(); i != e; ++i) {
+    TargetInfo::ConstraintInfo &Info = InputConstraintInfos[i];
+
+    // If this is a tied constraint, verify that the output and input have
+    // either exactly the same type, or that they are int/ptr operands with the
+    // same size (int/long, int*/long, are ok etc).
+    if (!Info.hasTiedOperand()) continue;
+
+    unsigned TiedTo = Info.getTiedOperand();
+    Expr *OutputExpr = Exprs[TiedTo];
+    Expr *InputExpr = Exprs[i+NumOutputs];
+    QualType InTy = InputExpr->getType();
+    QualType OutTy = OutputExpr->getType();
+    if (Context.hasSameType(InTy, OutTy))
+      continue;  // All types can be tied to themselves.
+
+    // Int/ptr operands have some special cases that we allow.
+    if ((OutTy->isIntegerType() || OutTy->isPointerType()) &&
+        (InTy->isIntegerType() || InTy->isPointerType())) {
+
+      // They are ok if they are the same size.  Tying void* to int is ok if
+      // they are the same size, for example.  This also allows tying void* to
+      // int*.
+      uint64_t OutSize = Context.getTypeSize(OutTy);
+      uint64_t InSize = Context.getTypeSize(InTy);
+      if (OutSize == InSize)
+        continue;
+
+      // If the smaller input/output operand is not mentioned in the asm string,
+      // then we can promote it and the asm string won't notice.  Check this
+      // case now.
+      bool SmallerValueMentioned = false;
+      for (unsigned p = 0, e = Pieces.size(); p != e; ++p) {
+        AsmStmt::AsmStringPiece &Piece = Pieces[p];
+        if (!Piece.isOperand()) continue;
+
+        // If this is a reference to the input and if the input was the smaller
+        // one, then we have to reject this asm.
+        if (Piece.getOperandNo() == i+NumOutputs) {
+          if (InSize < OutSize) {
+            SmallerValueMentioned = true;
+            break;
+          }
+        }
+
+        // If this is a reference to the input and if the input was the smaller
+        // one, then we have to reject this asm.
+        if (Piece.getOperandNo() == TiedTo) {
+          if (InSize > OutSize) {
+            SmallerValueMentioned = true;
+            break;
+          }
+        }
+      }
+
+      // If the smaller value wasn't mentioned in the asm string, and if the
+      // output was a register, just extend the shorter one to the size of the
+      // larger one.
+      if (!SmallerValueMentioned &&
+          OutputConstraintInfos[TiedTo].allowsRegister())
+        continue;
+    }
+
+    Diag(InputExpr->getLocStart(),
+         diag::err_asm_tying_incompatible_types)
+      << InTy << OutTy << OutputExpr->getSourceRange()
+      << InputExpr->getSourceRange();
+    DeleteStmt(NS);
+    return StmtError();
+  }
+
+  return Owned(NS);
+}
+
+Action::OwningStmtResult
+Sema::ActOnObjCAtCatchStmt(SourceLocation AtLoc,
+                           SourceLocation RParen, DeclPtrTy Parm,
+                           StmtArg Body, StmtArg catchList) {
+  Stmt *CatchList = catchList.takeAs<Stmt>();
+  ParmVarDecl *PVD = cast_or_null<ParmVarDecl>(Parm.getAs<Decl>());
+
+  // PVD == 0 implies @catch(...).
+  if (PVD) {
+    // If we already know the decl is invalid, reject it.
+    if (PVD->isInvalidDecl())
+      return StmtError();
+
+    if (!PVD->getType()->isObjCObjectPointerType())
+      return StmtError(Diag(PVD->getLocation(),
+                       diag::err_catch_param_not_objc_type));
+    if (PVD->getType()->isObjCQualifiedIdType())
+      return StmtError(Diag(PVD->getLocation(),
+                       diag::err_illegal_qualifiers_on_catch_parm));
+  }
+
+  ObjCAtCatchStmt *CS = new (Context) ObjCAtCatchStmt(AtLoc, RParen,
+    PVD, Body.takeAs<Stmt>(), CatchList);
+  return Owned(CatchList ? CatchList : CS);
+}
+
+Action::OwningStmtResult
+Sema::ActOnObjCAtFinallyStmt(SourceLocation AtLoc, StmtArg Body) {
+  return Owned(new (Context) ObjCAtFinallyStmt(AtLoc,
+                                           static_cast<Stmt*>(Body.release())));
+}
+
+Action::OwningStmtResult
+Sema::ActOnObjCAtTryStmt(SourceLocation AtLoc,
+                         StmtArg Try, StmtArg Catch, StmtArg Finally) {
+  CurFunctionNeedsScopeChecking = true;
+  return Owned(new (Context) ObjCAtTryStmt(AtLoc, Try.takeAs<Stmt>(),
+                                           Catch.takeAs<Stmt>(),
+                                           Finally.takeAs<Stmt>()));
+}
+
+Action::OwningStmtResult
+Sema::ActOnObjCAtThrowStmt(SourceLocation AtLoc, ExprArg expr,Scope *CurScope) {
+  Expr *ThrowExpr = expr.takeAs<Expr>();
+  if (!ThrowExpr) {
+    // @throw without an expression designates a rethrow (which much occur
+    // in the context of an @catch clause).
+    Scope *AtCatchParent = CurScope;
+    while (AtCatchParent && !AtCatchParent->isAtCatchScope())
+      AtCatchParent = AtCatchParent->getParent();
+    if (!AtCatchParent)
+      return StmtError(Diag(AtLoc, diag::error_rethrow_used_outside_catch));
+  } else {
+    QualType ThrowType = ThrowExpr->getType();
+    // Make sure the expression type is an ObjC pointer or "void *".
+    if (!ThrowType->isObjCObjectPointerType()) {
+      const PointerType *PT = ThrowType->getAs<PointerType>();
+      if (!PT || !PT->getPointeeType()->isVoidType())
+        return StmtError(Diag(AtLoc, diag::error_objc_throw_expects_object)
+                        << ThrowExpr->getType() << ThrowExpr->getSourceRange());
+    }
+  }
+  return Owned(new (Context) ObjCAtThrowStmt(AtLoc, ThrowExpr));
+}
+
+Action::OwningStmtResult
+Sema::ActOnObjCAtSynchronizedStmt(SourceLocation AtLoc, ExprArg SynchExpr,
+                                  StmtArg SynchBody) {
+  CurFunctionNeedsScopeChecking = true;
+
+  // Make sure the expression type is an ObjC pointer or "void *".
+  Expr *SyncExpr = static_cast<Expr*>(SynchExpr.get());
+  if (!SyncExpr->getType()->isObjCObjectPointerType()) {
+    const PointerType *PT = SyncExpr->getType()->getAs<PointerType>();
+    if (!PT || !PT->getPointeeType()->isVoidType())
+      return StmtError(Diag(AtLoc, diag::error_objc_synchronized_expects_object)
+                       << SyncExpr->getType() << SyncExpr->getSourceRange());
+  }
+
+  return Owned(new (Context) ObjCAtSynchronizedStmt(AtLoc,
+                                                    SynchExpr.takeAs<Stmt>(),
+                                                    SynchBody.takeAs<Stmt>()));
+}
+
+/// ActOnCXXCatchBlock - Takes an exception declaration and a handler block
+/// and creates a proper catch handler from them.
+Action::OwningStmtResult
+Sema::ActOnCXXCatchBlock(SourceLocation CatchLoc, DeclPtrTy ExDecl,
+                         StmtArg HandlerBlock) {
+  // There's nothing to test that ActOnExceptionDecl didn't already test.
+  return Owned(new (Context) CXXCatchStmt(CatchLoc,
+                                  cast_or_null<VarDecl>(ExDecl.getAs<Decl>()),
+                                          HandlerBlock.takeAs<Stmt>()));
+}
+
+class TypeWithHandler {
+  QualType t;
+  CXXCatchStmt *stmt;
+public:
+  TypeWithHandler(const QualType &type, CXXCatchStmt *statement)
+  : t(type), stmt(statement) {}
+
+  // An arbitrary order is fine as long as it places identical
+  // types next to each other.
+  bool operator<(const TypeWithHandler &y) const {
+    if (t.getAsOpaquePtr() < y.t.getAsOpaquePtr())
+      return true;
+    if (t.getAsOpaquePtr() > y.t.getAsOpaquePtr())
+      return false;
+    else
+      return getTypeSpecStartLoc() < y.getTypeSpecStartLoc();
+  }
+
+  bool operator==(const TypeWithHandler& other) const {
+    return t == other.t;
+  }
+
+  QualType getQualType() const { return t; }
+  CXXCatchStmt *getCatchStmt() const { return stmt; }
+  SourceLocation getTypeSpecStartLoc() const {
+    return stmt->getExceptionDecl()->getTypeSpecStartLoc();
+  }
+};
+
+/// ActOnCXXTryBlock - Takes a try compound-statement and a number of
+/// handlers and creates a try statement from them.
+Action::OwningStmtResult
+Sema::ActOnCXXTryBlock(SourceLocation TryLoc, StmtArg TryBlock,
+                       MultiStmtArg RawHandlers) {
+  unsigned NumHandlers = RawHandlers.size();
+  assert(NumHandlers > 0 &&
+         "The parser shouldn't call this if there are no handlers.");
+  Stmt **Handlers = reinterpret_cast<Stmt**>(RawHandlers.get());
+
+  llvm::SmallVector<TypeWithHandler, 8> TypesWithHandlers;
+
+  for (unsigned i = 0; i < NumHandlers; ++i) {
+    CXXCatchStmt *Handler = llvm::cast<CXXCatchStmt>(Handlers[i]);
+    if (!Handler->getExceptionDecl()) {
+      if (i < NumHandlers - 1)
+        return StmtError(Diag(Handler->getLocStart(),
+                              diag::err_early_catch_all));
+
+      continue;
+    }
+
+    const QualType CaughtType = Handler->getCaughtType();
+    const QualType CanonicalCaughtType = Context.getCanonicalType(CaughtType);
+    TypesWithHandlers.push_back(TypeWithHandler(CanonicalCaughtType, Handler));
+  }
+
+  // Detect handlers for the same type as an earlier one.
+  if (NumHandlers > 1) {
+    llvm::array_pod_sort(TypesWithHandlers.begin(), TypesWithHandlers.end());
+
+    TypeWithHandler prev = TypesWithHandlers[0];
+    for (unsigned i = 1; i < TypesWithHandlers.size(); ++i) {
+      TypeWithHandler curr = TypesWithHandlers[i];
+
+      if (curr == prev) {
+        Diag(curr.getTypeSpecStartLoc(),
+             diag::warn_exception_caught_by_earlier_handler)
+          << curr.getCatchStmt()->getCaughtType().getAsString();
+        Diag(prev.getTypeSpecStartLoc(),
+             diag::note_previous_exception_handler)
+          << prev.getCatchStmt()->getCaughtType().getAsString();
+      }
+
+      prev = curr;
+    }
+  }
+
+  // FIXME: We should detect handlers that cannot catch anything because an
+  // earlier handler catches a superclass. Need to find a method that is not
+  // quadratic for this.
+  // Neither of these are explicitly forbidden, but every compiler detects them
+  // and warns.
+
+  CurFunctionNeedsScopeChecking = true;
+  RawHandlers.release();
+  return Owned(CXXTryStmt::Create(Context, TryLoc,
+                                  static_cast<Stmt*>(TryBlock.release()),
+                                  Handlers, NumHandlers));
+}
diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp
new file mode 100644
index 0000000..1779bde
--- /dev/null
+++ b/lib/Sema/SemaTemplate.cpp
@@ -0,0 +1,5083 @@
+//===------- SemaTemplate.cpp - Semantic Analysis for C++ Templates -------===/
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//===----------------------------------------------------------------------===/
+//
+//  This file implements semantic analysis for C++ templates.
+//===----------------------------------------------------------------------===/
+
+#include "Sema.h"
+#include "Lookup.h"
+#include "TreeTransform.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/ExprCXX.h"
+#include "clang/AST/DeclTemplate.h"
+#include "clang/Parse/DeclSpec.h"
+#include "clang/Parse/Template.h"
+#include "clang/Basic/LangOptions.h"
+#include "clang/Basic/PartialDiagnostic.h"
+#include "llvm/ADT/StringExtras.h"
+using namespace clang;
+
+/// \brief Determine whether the declaration found is acceptable as the name
+/// of a template and, if so, return that template declaration. Otherwise,
+/// returns NULL.
+static NamedDecl *isAcceptableTemplateName(ASTContext &Context, NamedDecl *D) {
+  if (!D)
+    return 0;
+
+  if (isa<TemplateDecl>(D))
+    return D;
+
+  if (CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(D)) {
+    // C++ [temp.local]p1:
+    //   Like normal (non-template) classes, class templates have an
+    //   injected-class-name (Clause 9). The injected-class-name
+    //   can be used with or without a template-argument-list. When
+    //   it is used without a template-argument-list, it is
+    //   equivalent to the injected-class-name followed by the
+    //   template-parameters of the class template enclosed in
+    //   <>. When it is used with a template-argument-list, it
+    //   refers to the specified class template specialization,
+    //   which could be the current specialization or another
+    //   specialization.
+    if (Record->isInjectedClassName()) {
+      Record = cast<CXXRecordDecl>(Record->getDeclContext());
+      if (Record->getDescribedClassTemplate())
+        return Record->getDescribedClassTemplate();
+
+      if (ClassTemplateSpecializationDecl *Spec
+            = dyn_cast<ClassTemplateSpecializationDecl>(Record))
+        return Spec->getSpecializedTemplate();
+    }
+
+    return 0;
+  }
+
+  return 0;
+}
+
+static void FilterAcceptableTemplateNames(ASTContext &C, LookupResult &R) {
+  LookupResult::Filter filter = R.makeFilter();
+  while (filter.hasNext()) {
+    NamedDecl *Orig = filter.next();
+    NamedDecl *Repl = isAcceptableTemplateName(C, Orig->getUnderlyingDecl());
+    if (!Repl)
+      filter.erase();
+    else if (Repl != Orig)
+      filter.replace(Repl);
+  }
+  filter.done();
+}
+
+TemplateNameKind Sema::isTemplateName(Scope *S,
+                                      const CXXScopeSpec &SS,
+                                      UnqualifiedId &Name,
+                                      TypeTy *ObjectTypePtr,
+                                      bool EnteringContext,
+                                      TemplateTy &TemplateResult) {
+  assert(getLangOptions().CPlusPlus && "No template names in C!");
+
+  DeclarationName TName;
+  
+  switch (Name.getKind()) {
+  case UnqualifiedId::IK_Identifier:
+    TName = DeclarationName(Name.Identifier);
+    break;
+      
+  case UnqualifiedId::IK_OperatorFunctionId:
+    TName = Context.DeclarationNames.getCXXOperatorName(
+                                              Name.OperatorFunctionId.Operator);
+    break;
+
+  case UnqualifiedId::IK_LiteralOperatorId:
+    TName = Context.DeclarationNames.getCXXLiteralOperatorName(Name.Identifier);
+    break;
+
+  default:
+    return TNK_Non_template;
+  }
+
+  QualType ObjectType = QualType::getFromOpaquePtr(ObjectTypePtr);
+
+  LookupResult R(*this, TName, Name.getSourceRange().getBegin(), 
+                 LookupOrdinaryName);
+  R.suppressDiagnostics();
+  LookupTemplateName(R, S, SS, ObjectType, EnteringContext);
+  if (R.empty())
+    return TNK_Non_template;
+
+  TemplateName Template;
+  TemplateNameKind TemplateKind;
+
+  unsigned ResultCount = R.end() - R.begin();
+  if (ResultCount > 1) {
+    // We assume that we'll preserve the qualifier from a function
+    // template name in other ways.
+    Template = Context.getOverloadedTemplateName(R.begin(), R.end());
+    TemplateKind = TNK_Function_template;
+  } else {
+    TemplateDecl *TD = cast<TemplateDecl>((*R.begin())->getUnderlyingDecl());
+
+    if (SS.isSet() && !SS.isInvalid()) {
+      NestedNameSpecifier *Qualifier
+        = static_cast<NestedNameSpecifier *>(SS.getScopeRep());
+      Template = Context.getQualifiedTemplateName(Qualifier, false, TD);
+    } else {
+      Template = TemplateName(TD);
+    }
+
+    if (isa<FunctionTemplateDecl>(TD))
+      TemplateKind = TNK_Function_template;
+    else {
+      assert(isa<ClassTemplateDecl>(TD) || isa<TemplateTemplateParmDecl>(TD));
+      TemplateKind = TNK_Type_template;
+    }
+  }
+
+  TemplateResult = TemplateTy::make(Template);
+  return TemplateKind;
+}
+
+bool Sema::DiagnoseUnknownTemplateName(const IdentifierInfo &II, 
+                                       SourceLocation IILoc,
+                                       Scope *S,
+                                       const CXXScopeSpec *SS,
+                                       TemplateTy &SuggestedTemplate,
+                                       TemplateNameKind &SuggestedKind) {
+  // We can't recover unless there's a dependent scope specifier preceding the
+  // template name.
+  if (!SS || !SS->isSet() || !isDependentScopeSpecifier(*SS) ||
+      computeDeclContext(*SS))
+    return false;
+  
+  // The code is missing a 'template' keyword prior to the dependent template
+  // name.
+  NestedNameSpecifier *Qualifier = (NestedNameSpecifier*)SS->getScopeRep();
+  Diag(IILoc, diag::err_template_kw_missing)
+    << Qualifier << II.getName()
+    << CodeModificationHint::CreateInsertion(IILoc, "template ");
+  SuggestedTemplate 
+    = TemplateTy::make(Context.getDependentTemplateName(Qualifier, &II));
+  SuggestedKind = TNK_Dependent_template_name;
+  return true;
+}
+
+void Sema::LookupTemplateName(LookupResult &Found,
+                              Scope *S, const CXXScopeSpec &SS,
+                              QualType ObjectType,
+                              bool EnteringContext) {
+  // Determine where to perform name lookup
+  DeclContext *LookupCtx = 0;
+  bool isDependent = false;
+  if (!ObjectType.isNull()) {
+    // This nested-name-specifier occurs in a member access expression, e.g.,
+    // x->B::f, and we are looking into the type of the object.
+    assert(!SS.isSet() && "ObjectType and scope specifier cannot coexist");
+    LookupCtx = computeDeclContext(ObjectType);
+    isDependent = ObjectType->isDependentType();
+    assert((isDependent || !ObjectType->isIncompleteType()) && 
+           "Caller should have completed object type");
+  } else if (SS.isSet()) {
+    // This nested-name-specifier occurs after another nested-name-specifier,
+    // so long into the context associated with the prior nested-name-specifier.
+    LookupCtx = computeDeclContext(SS, EnteringContext);
+    isDependent = isDependentScopeSpecifier(SS);
+    
+    // The declaration context must be complete.
+    if (LookupCtx && RequireCompleteDeclContext(SS))
+      return;
+  }
+
+  bool ObjectTypeSearchedInScope = false;
+  if (LookupCtx) {
+    // Perform "qualified" name lookup into the declaration context we
+    // computed, which is either the type of the base of a member access
+    // expression or the declaration context associated with a prior
+    // nested-name-specifier.
+    LookupQualifiedName(Found, LookupCtx);
+
+    if (!ObjectType.isNull() && Found.empty()) {
+      // C++ [basic.lookup.classref]p1:
+      //   In a class member access expression (5.2.5), if the . or -> token is
+      //   immediately followed by an identifier followed by a <, the
+      //   identifier must be looked up to determine whether the < is the
+      //   beginning of a template argument list (14.2) or a less-than operator.
+      //   The identifier is first looked up in the class of the object
+      //   expression. If the identifier is not found, it is then looked up in
+      //   the context of the entire postfix-expression and shall name a class
+      //   or function template.
+      //
+      // FIXME: When we're instantiating a template, do we actually have to
+      // look in the scope of the template? Seems fishy...
+      if (S) LookupName(Found, S);
+      ObjectTypeSearchedInScope = true;
+    }
+  } else if (isDependent) {
+    // We cannot look into a dependent object type or nested nme
+    // specifier.
+    return;
+  } else {
+    // Perform unqualified name lookup in the current scope.
+    LookupName(Found, S);
+  }
+
+  // FIXME: Cope with ambiguous name-lookup results.
+  assert(!Found.isAmbiguous() &&
+         "Cannot handle template name-lookup ambiguities");
+
+  if (Found.empty() && !isDependent) {
+    // If we did not find any names, attempt to correct any typos.
+    DeclarationName Name = Found.getLookupName();
+    if (CorrectTypo(Found, S, &SS, LookupCtx)) {
+      FilterAcceptableTemplateNames(Context, Found);
+      if (!Found.empty() && isa<TemplateDecl>(*Found.begin())) {
+        if (LookupCtx)
+          Diag(Found.getNameLoc(), diag::err_no_member_template_suggest)
+            << Name << LookupCtx << Found.getLookupName() << SS.getRange()
+            << CodeModificationHint::CreateReplacement(Found.getNameLoc(),
+                                          Found.getLookupName().getAsString());
+        else
+          Diag(Found.getNameLoc(), diag::err_no_template_suggest)
+            << Name << Found.getLookupName()
+            << CodeModificationHint::CreateReplacement(Found.getNameLoc(),
+                                          Found.getLookupName().getAsString());
+        if (TemplateDecl *Template = Found.getAsSingle<TemplateDecl>())
+          Diag(Template->getLocation(), diag::note_previous_decl)
+            << Template->getDeclName();
+      } else
+        Found.clear();
+    } else {
+      Found.clear();
+    }
+  }
+
+  FilterAcceptableTemplateNames(Context, Found);
+  if (Found.empty())
+    return;
+
+  if (S && !ObjectType.isNull() && !ObjectTypeSearchedInScope) {
+    // C++ [basic.lookup.classref]p1:
+    //   [...] If the lookup in the class of the object expression finds a
+    //   template, the name is also looked up in the context of the entire
+    //   postfix-expression and [...]
+    //
+    LookupResult FoundOuter(*this, Found.getLookupName(), Found.getNameLoc(),
+                            LookupOrdinaryName);
+    LookupName(FoundOuter, S);
+    FilterAcceptableTemplateNames(Context, FoundOuter);
+    // FIXME: Handle ambiguities in this lookup better
+
+    if (FoundOuter.empty()) {
+      //   - if the name is not found, the name found in the class of the
+      //     object expression is used, otherwise
+    } else if (!FoundOuter.getAsSingle<ClassTemplateDecl>()) {
+      //   - if the name is found in the context of the entire
+      //     postfix-expression and does not name a class template, the name
+      //     found in the class of the object expression is used, otherwise
+    } else {
+      //   - if the name found is a class template, it must refer to the same
+      //     entity as the one found in the class of the object expression,
+      //     otherwise the program is ill-formed.
+      if (!Found.isSingleResult() ||
+          Found.getFoundDecl()->getCanonicalDecl()
+            != FoundOuter.getFoundDecl()->getCanonicalDecl()) {
+        Diag(Found.getNameLoc(), 
+             diag::err_nested_name_member_ref_lookup_ambiguous)
+          << Found.getLookupName();
+        Diag(Found.getRepresentativeDecl()->getLocation(),
+             diag::note_ambig_member_ref_object_type)
+          << ObjectType;
+        Diag(FoundOuter.getFoundDecl()->getLocation(),
+             diag::note_ambig_member_ref_scope);
+
+        // Recover by taking the template that we found in the object
+        // expression's type.
+      }
+    }
+  }
+}
+
+/// ActOnDependentIdExpression - Handle a dependent id-expression that
+/// was just parsed.  This is only possible with an explicit scope
+/// specifier naming a dependent type.
+Sema::OwningExprResult
+Sema::ActOnDependentIdExpression(const CXXScopeSpec &SS,
+                                 DeclarationName Name,
+                                 SourceLocation NameLoc,
+                                 bool isAddressOfOperand,
+                           const TemplateArgumentListInfo *TemplateArgs) {
+  NestedNameSpecifier *Qualifier
+    = static_cast<NestedNameSpecifier*>(SS.getScopeRep());
+    
+  if (!isAddressOfOperand &&
+      isa<CXXMethodDecl>(CurContext) &&
+      cast<CXXMethodDecl>(CurContext)->isInstance()) {
+    QualType ThisType = cast<CXXMethodDecl>(CurContext)->getThisType(Context);
+    
+    // Since the 'this' expression is synthesized, we don't need to
+    // perform the double-lookup check.
+    NamedDecl *FirstQualifierInScope = 0;
+
+    return Owned(CXXDependentScopeMemberExpr::Create(Context,
+                                                     /*This*/ 0, ThisType,
+                                                     /*IsArrow*/ true,
+                                                     /*Op*/ SourceLocation(),
+                                                     Qualifier, SS.getRange(),
+                                                     FirstQualifierInScope,
+                                                     Name, NameLoc,
+                                                     TemplateArgs));
+  }
+
+  return BuildDependentDeclRefExpr(SS, Name, NameLoc, TemplateArgs);
+}
+
+Sema::OwningExprResult
+Sema::BuildDependentDeclRefExpr(const CXXScopeSpec &SS,
+                                DeclarationName Name,
+                                SourceLocation NameLoc,
+                                const TemplateArgumentListInfo *TemplateArgs) {
+  return Owned(DependentScopeDeclRefExpr::Create(Context,
+               static_cast<NestedNameSpecifier*>(SS.getScopeRep()),
+                                                 SS.getRange(),
+                                                 Name, NameLoc,
+                                                 TemplateArgs));
+}
+
+/// DiagnoseTemplateParameterShadow - Produce a diagnostic complaining
+/// that the template parameter 'PrevDecl' is being shadowed by a new
+/// declaration at location Loc. Returns true to indicate that this is
+/// an error, and false otherwise.
+bool Sema::DiagnoseTemplateParameterShadow(SourceLocation Loc, Decl *PrevDecl) {
+  assert(PrevDecl->isTemplateParameter() && "Not a template parameter");
+
+  // Microsoft Visual C++ permits template parameters to be shadowed.
+  if (getLangOptions().Microsoft)
+    return false;
+
+  // C++ [temp.local]p4:
+  //   A template-parameter shall not be redeclared within its
+  //   scope (including nested scopes).
+  Diag(Loc, diag::err_template_param_shadow)
+    << cast<NamedDecl>(PrevDecl)->getDeclName();
+  Diag(PrevDecl->getLocation(), diag::note_template_param_here);
+  return true;
+}
+
+/// AdjustDeclIfTemplate - If the given decl happens to be a template, reset
+/// the parameter D to reference the templated declaration and return a pointer
+/// to the template declaration. Otherwise, do nothing to D and return null.
+TemplateDecl *Sema::AdjustDeclIfTemplate(DeclPtrTy &D) {
+  if (TemplateDecl *Temp = dyn_cast_or_null<TemplateDecl>(D.getAs<Decl>())) {
+    D = DeclPtrTy::make(Temp->getTemplatedDecl());
+    return Temp;
+  }
+  return 0;
+}
+
+static TemplateArgumentLoc translateTemplateArgument(Sema &SemaRef,
+                                            const ParsedTemplateArgument &Arg) {
+  
+  switch (Arg.getKind()) {
+  case ParsedTemplateArgument::Type: {
+    TypeSourceInfo *DI;
+    QualType T = SemaRef.GetTypeFromParser(Arg.getAsType(), &DI);
+    if (!DI) 
+      DI = SemaRef.Context.getTrivialTypeSourceInfo(T, Arg.getLocation());
+    return TemplateArgumentLoc(TemplateArgument(T), DI);
+  }
+    
+  case ParsedTemplateArgument::NonType: {
+    Expr *E = static_cast<Expr *>(Arg.getAsExpr());
+    return TemplateArgumentLoc(TemplateArgument(E), E);
+  }
+    
+  case ParsedTemplateArgument::Template: {
+    TemplateName Template
+      = TemplateName::getFromVoidPointer(Arg.getAsTemplate().get());
+    return TemplateArgumentLoc(TemplateArgument(Template),
+                               Arg.getScopeSpec().getRange(),
+                               Arg.getLocation());
+  }
+  }
+  
+  llvm_unreachable("Unhandled parsed template argument");
+  return TemplateArgumentLoc();
+}
+                                                     
+/// \brief Translates template arguments as provided by the parser
+/// into template arguments used by semantic analysis.
+void Sema::translateTemplateArguments(const ASTTemplateArgsPtr &TemplateArgsIn,
+                                      TemplateArgumentListInfo &TemplateArgs) {
+ for (unsigned I = 0, Last = TemplateArgsIn.size(); I != Last; ++I)
+   TemplateArgs.addArgument(translateTemplateArgument(*this,
+                                                      TemplateArgsIn[I]));
+}
+                                                     
+/// ActOnTypeParameter - Called when a C++ template type parameter
+/// (e.g., "typename T") has been parsed. Typename specifies whether
+/// the keyword "typename" was used to declare the type parameter
+/// (otherwise, "class" was used), and KeyLoc is the location of the
+/// "class" or "typename" keyword. ParamName is the name of the
+/// parameter (NULL indicates an unnamed template parameter) and
+/// ParamName is the location of the parameter name (if any).
+/// If the type parameter has a default argument, it will be added
+/// later via ActOnTypeParameterDefault.
+Sema::DeclPtrTy Sema::ActOnTypeParameter(Scope *S, bool Typename, bool Ellipsis,
+                                         SourceLocation EllipsisLoc,
+                                         SourceLocation KeyLoc,
+                                         IdentifierInfo *ParamName,
+                                         SourceLocation ParamNameLoc,
+                                         unsigned Depth, unsigned Position) {
+  assert(S->isTemplateParamScope() &&
+         "Template type parameter not in template parameter scope!");
+  bool Invalid = false;
+
+  if (ParamName) {
+    NamedDecl *PrevDecl = LookupSingleName(S, ParamName, LookupTagName);
+    if (PrevDecl && PrevDecl->isTemplateParameter())
+      Invalid = Invalid || DiagnoseTemplateParameterShadow(ParamNameLoc,
+                                                           PrevDecl);
+  }
+
+  SourceLocation Loc = ParamNameLoc;
+  if (!ParamName)
+    Loc = KeyLoc;
+
+  TemplateTypeParmDecl *Param
+    = TemplateTypeParmDecl::Create(Context, Context.getTranslationUnitDecl(),
+                                   Loc, Depth, Position, ParamName, Typename,
+                                   Ellipsis);
+  if (Invalid)
+    Param->setInvalidDecl();
+
+  if (ParamName) {
+    // Add the template parameter into the current scope.
+    S->AddDecl(DeclPtrTy::make(Param));
+    IdResolver.AddDecl(Param);
+  }
+
+  return DeclPtrTy::make(Param);
+}
+
+/// ActOnTypeParameterDefault - Adds a default argument (the type
+/// Default) to the given template type parameter (TypeParam).
+void Sema::ActOnTypeParameterDefault(DeclPtrTy TypeParam,
+                                     SourceLocation EqualLoc,
+                                     SourceLocation DefaultLoc,
+                                     TypeTy *DefaultT) {
+  TemplateTypeParmDecl *Parm
+    = cast<TemplateTypeParmDecl>(TypeParam.getAs<Decl>());
+
+  TypeSourceInfo *DefaultTInfo;
+  GetTypeFromParser(DefaultT, &DefaultTInfo);
+
+  assert(DefaultTInfo && "expected source information for type");
+
+  // C++0x [temp.param]p9:
+  // A default template-argument may be specified for any kind of
+  // template-parameter that is not a template parameter pack.
+  if (Parm->isParameterPack()) {
+    Diag(DefaultLoc, diag::err_template_param_pack_default_arg);
+    return;
+  }
+
+  // C++ [temp.param]p14:
+  //   A template-parameter shall not be used in its own default argument.
+  // FIXME: Implement this check! Needs a recursive walk over the types.
+
+  // Check the template argument itself.
+  if (CheckTemplateArgument(Parm, DefaultTInfo)) {
+    Parm->setInvalidDecl();
+    return;
+  }
+
+  Parm->setDefaultArgument(DefaultTInfo, false);
+}
+
+/// \brief Check that the type of a non-type template parameter is
+/// well-formed.
+///
+/// \returns the (possibly-promoted) parameter type if valid;
+/// otherwise, produces a diagnostic and returns a NULL type.
+QualType
+Sema::CheckNonTypeTemplateParameterType(QualType T, SourceLocation Loc) {
+  // C++ [temp.param]p4:
+  //
+  // A non-type template-parameter shall have one of the following
+  // (optionally cv-qualified) types:
+  //
+  //       -- integral or enumeration type,
+  if (T->isIntegralType() || T->isEnumeralType() ||
+      //   -- pointer to object or pointer to function,
+      (T->isPointerType() &&
+       (T->getAs<PointerType>()->getPointeeType()->isObjectType() ||
+        T->getAs<PointerType>()->getPointeeType()->isFunctionType())) ||
+      //   -- reference to object or reference to function,
+      T->isReferenceType() ||
+      //   -- pointer to member.
+      T->isMemberPointerType() ||
+      // If T is a dependent type, we can't do the check now, so we
+      // assume that it is well-formed.
+      T->isDependentType())
+    return T;
+  // C++ [temp.param]p8:
+  //
+  //   A non-type template-parameter of type "array of T" or
+  //   "function returning T" is adjusted to be of type "pointer to
+  //   T" or "pointer to function returning T", respectively.
+  else if (T->isArrayType())
+    // FIXME: Keep the type prior to promotion?
+    return Context.getArrayDecayedType(T);
+  else if (T->isFunctionType())
+    // FIXME: Keep the type prior to promotion?
+    return Context.getPointerType(T);
+
+  Diag(Loc, diag::err_template_nontype_parm_bad_type)
+    << T;
+
+  return QualType();
+}
+
+/// ActOnNonTypeTemplateParameter - Called when a C++ non-type
+/// template parameter (e.g., "int Size" in "template<int Size>
+/// class Array") has been parsed. S is the current scope and D is
+/// the parsed declarator.
+Sema::DeclPtrTy Sema::ActOnNonTypeTemplateParameter(Scope *S, Declarator &D,
+                                                    unsigned Depth,
+                                                    unsigned Position) {
+  TypeSourceInfo *TInfo = 0;
+  QualType T = GetTypeForDeclarator(D, S, &TInfo);
+
+  assert(S->isTemplateParamScope() &&
+         "Non-type template parameter not in template parameter scope!");
+  bool Invalid = false;
+
+  IdentifierInfo *ParamName = D.getIdentifier();
+  if (ParamName) {
+    NamedDecl *PrevDecl = LookupSingleName(S, ParamName, LookupTagName);
+    if (PrevDecl && PrevDecl->isTemplateParameter())
+      Invalid = Invalid || DiagnoseTemplateParameterShadow(D.getIdentifierLoc(),
+                                                           PrevDecl);
+  }
+
+  T = CheckNonTypeTemplateParameterType(T, D.getIdentifierLoc());
+  if (T.isNull()) {
+    T = Context.IntTy; // Recover with an 'int' type.
+    Invalid = true;
+  }
+
+  NonTypeTemplateParmDecl *Param
+    = NonTypeTemplateParmDecl::Create(Context, Context.getTranslationUnitDecl(),
+                                      D.getIdentifierLoc(),
+                                      Depth, Position, ParamName, T, TInfo);
+  if (Invalid)
+    Param->setInvalidDecl();
+
+  if (D.getIdentifier()) {
+    // Add the template parameter into the current scope.
+    S->AddDecl(DeclPtrTy::make(Param));
+    IdResolver.AddDecl(Param);
+  }
+  return DeclPtrTy::make(Param);
+}
+
+/// \brief Adds a default argument to the given non-type template
+/// parameter.
+void Sema::ActOnNonTypeTemplateParameterDefault(DeclPtrTy TemplateParamD,
+                                                SourceLocation EqualLoc,
+                                                ExprArg DefaultE) {
+  NonTypeTemplateParmDecl *TemplateParm
+    = cast<NonTypeTemplateParmDecl>(TemplateParamD.getAs<Decl>());
+  Expr *Default = static_cast<Expr *>(DefaultE.get());
+
+  // C++ [temp.param]p14:
+  //   A template-parameter shall not be used in its own default argument.
+  // FIXME: Implement this check! Needs a recursive walk over the types.
+
+  // Check the well-formedness of the default template argument.
+  TemplateArgument Converted;
+  if (CheckTemplateArgument(TemplateParm, TemplateParm->getType(), Default,
+                            Converted)) {
+    TemplateParm->setInvalidDecl();
+    return;
+  }
+
+  TemplateParm->setDefaultArgument(DefaultE.takeAs<Expr>());
+}
+
+
+/// ActOnTemplateTemplateParameter - Called when a C++ template template
+/// parameter (e.g. T in template <template <typename> class T> class array)
+/// has been parsed. S is the current scope.
+Sema::DeclPtrTy Sema::ActOnTemplateTemplateParameter(Scope* S,
+                                                     SourceLocation TmpLoc,
+                                                     TemplateParamsTy *Params,
+                                                     IdentifierInfo *Name,
+                                                     SourceLocation NameLoc,
+                                                     unsigned Depth,
+                                                     unsigned Position) {
+  assert(S->isTemplateParamScope() &&
+         "Template template parameter not in template parameter scope!");
+
+  // Construct the parameter object.
+  TemplateTemplateParmDecl *Param =
+    TemplateTemplateParmDecl::Create(Context, Context.getTranslationUnitDecl(),
+                                     TmpLoc, Depth, Position, Name,
+                                     (TemplateParameterList*)Params);
+
+  // Make sure the parameter is valid.
+  // FIXME: Decl object is not currently invalidated anywhere so this doesn't
+  // do anything yet. However, if the template parameter list or (eventual)
+  // default value is ever invalidated, that will propagate here.
+  bool Invalid = false;
+  if (Invalid) {
+    Param->setInvalidDecl();
+  }
+
+  // If the tt-param has a name, then link the identifier into the scope
+  // and lookup mechanisms.
+  if (Name) {
+    S->AddDecl(DeclPtrTy::make(Param));
+    IdResolver.AddDecl(Param);
+  }
+
+  return DeclPtrTy::make(Param);
+}
+
+/// \brief Adds a default argument to the given template template
+/// parameter.
+void Sema::ActOnTemplateTemplateParameterDefault(DeclPtrTy TemplateParamD,
+                                                 SourceLocation EqualLoc,
+                                        const ParsedTemplateArgument &Default) {
+  TemplateTemplateParmDecl *TemplateParm
+    = cast<TemplateTemplateParmDecl>(TemplateParamD.getAs<Decl>());
+  
+  // C++ [temp.param]p14:
+  //   A template-parameter shall not be used in its own default argument.
+  // FIXME: Implement this check! Needs a recursive walk over the types.
+
+  // Check only that we have a template template argument. We don't want to
+  // try to check well-formedness now, because our template template parameter
+  // might have dependent types in its template parameters, which we wouldn't
+  // be able to match now.
+  //
+  // If none of the template template parameter's template arguments mention
+  // other template parameters, we could actually perform more checking here.
+  // However, it isn't worth doing.
+  TemplateArgumentLoc DefaultArg = translateTemplateArgument(*this, Default);
+  if (DefaultArg.getArgument().getAsTemplate().isNull()) {
+    Diag(DefaultArg.getLocation(), diag::err_template_arg_not_class_template)
+      << DefaultArg.getSourceRange();
+    return;
+  }
+  
+  TemplateParm->setDefaultArgument(DefaultArg);
+}
+
+/// ActOnTemplateParameterList - Builds a TemplateParameterList that
+/// contains the template parameters in Params/NumParams.
+Sema::TemplateParamsTy *
+Sema::ActOnTemplateParameterList(unsigned Depth,
+                                 SourceLocation ExportLoc,
+                                 SourceLocation TemplateLoc,
+                                 SourceLocation LAngleLoc,
+                                 DeclPtrTy *Params, unsigned NumParams,
+                                 SourceLocation RAngleLoc) {
+  if (ExportLoc.isValid())
+    Diag(ExportLoc, diag::warn_template_export_unsupported);
+
+  return TemplateParameterList::Create(Context, TemplateLoc, LAngleLoc,
+                                       (NamedDecl**)Params, NumParams, 
+                                       RAngleLoc);
+}
+
+Sema::DeclResult
+Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK,
+                         SourceLocation KWLoc, const CXXScopeSpec &SS,
+                         IdentifierInfo *Name, SourceLocation NameLoc,
+                         AttributeList *Attr,
+                         TemplateParameterList *TemplateParams,
+                         AccessSpecifier AS) {
+  assert(TemplateParams && TemplateParams->size() > 0 &&
+         "No template parameters");
+  assert(TUK != TUK_Reference && "Can only declare or define class templates");
+  bool Invalid = false;
+
+  // Check that we can declare a template here.
+  if (CheckTemplateDeclScope(S, TemplateParams))
+    return true;
+
+  TagDecl::TagKind Kind = TagDecl::getTagKindForTypeSpec(TagSpec);
+  assert(Kind != TagDecl::TK_enum && "can't build template of enumerated type");
+
+  // There is no such thing as an unnamed class template.
+  if (!Name) {
+    Diag(KWLoc, diag::err_template_unnamed_class);
+    return true;
+  }
+
+  // Find any previous declaration with this name.
+  DeclContext *SemanticContext;
+  LookupResult Previous(*this, Name, NameLoc, LookupOrdinaryName,
+                        ForRedeclaration);
+  if (SS.isNotEmpty() && !SS.isInvalid()) {
+    if (RequireCompleteDeclContext(SS))
+      return true;
+
+    SemanticContext = computeDeclContext(SS, true);
+    if (!SemanticContext) {
+      // FIXME: Produce a reasonable diagnostic here
+      return true;
+    }
+
+    LookupQualifiedName(Previous, SemanticContext);
+  } else {
+    SemanticContext = CurContext;
+    LookupName(Previous, S);
+  }
+
+  assert(!Previous.isAmbiguous() && "Ambiguity in class template redecl?");
+  NamedDecl *PrevDecl = 0;
+  if (Previous.begin() != Previous.end())
+    PrevDecl = *Previous.begin();
+
+  // If there is a previous declaration with the same name, check
+  // whether this is a valid redeclaration.
+  ClassTemplateDecl *PrevClassTemplate
+    = dyn_cast_or_null<ClassTemplateDecl>(PrevDecl);
+
+  // We may have found the injected-class-name of a class template,
+  // class template partial specialization, or class template specialization. 
+  // In these cases, grab the template that is being defined or specialized.
+  if (!PrevClassTemplate && PrevDecl && isa<CXXRecordDecl>(PrevDecl) && 
+      cast<CXXRecordDecl>(PrevDecl)->isInjectedClassName()) {
+    PrevDecl = cast<CXXRecordDecl>(PrevDecl->getDeclContext());
+    PrevClassTemplate 
+      = cast<CXXRecordDecl>(PrevDecl)->getDescribedClassTemplate();
+    if (!PrevClassTemplate && isa<ClassTemplateSpecializationDecl>(PrevDecl)) {
+      PrevClassTemplate
+        = cast<ClassTemplateSpecializationDecl>(PrevDecl)
+            ->getSpecializedTemplate();
+    }
+  }
+
+  if (TUK == TUK_Friend) {
+    // C++ [namespace.memdef]p3:
+    //   [...] When looking for a prior declaration of a class or a function 
+    //   declared as a friend, and when the name of the friend class or 
+    //   function is neither a qualified name nor a template-id, scopes outside
+    //   the innermost enclosing namespace scope are not considered.
+    DeclContext *OutermostContext = CurContext;
+    while (!OutermostContext->isFileContext())
+      OutermostContext = OutermostContext->getLookupParent();
+
+    if (PrevDecl &&
+        (OutermostContext->Equals(PrevDecl->getDeclContext()) ||
+         OutermostContext->Encloses(PrevDecl->getDeclContext()))) {
+      SemanticContext = PrevDecl->getDeclContext();
+    } else {
+      // Declarations in outer scopes don't matter. However, the outermost
+      // context we computed is the semantic context for our new 
+      // declaration.
+      PrevDecl = PrevClassTemplate = 0;
+      SemanticContext = OutermostContext;
+    }
+    
+    if (CurContext->isDependentContext()) {
+      // If this is a dependent context, we don't want to link the friend
+      // class template to the template in scope, because that would perform
+      // checking of the template parameter lists that can't be performed
+      // until the outer context is instantiated.
+      PrevDecl = PrevClassTemplate = 0;
+    }
+  } else if (PrevDecl && !isDeclInScope(PrevDecl, SemanticContext, S))
+    PrevDecl = PrevClassTemplate = 0;
+
+  if (PrevClassTemplate) {
+    // Ensure that the template parameter lists are compatible.
+    if (!TemplateParameterListsAreEqual(TemplateParams,
+                                   PrevClassTemplate->getTemplateParameters(),
+                                        /*Complain=*/true,
+                                        TPL_TemplateMatch))
+      return true;
+
+    // C++ [temp.class]p4:
+    //   In a redeclaration, partial specialization, explicit
+    //   specialization or explicit instantiation of a class template,
+    //   the class-key shall agree in kind with the original class
+    //   template declaration (7.1.5.3).
+    RecordDecl *PrevRecordDecl = PrevClassTemplate->getTemplatedDecl();
+    if (!isAcceptableTagRedeclaration(PrevRecordDecl, Kind, KWLoc, *Name)) {
+      Diag(KWLoc, diag::err_use_with_wrong_tag)
+        << Name
+        << CodeModificationHint::CreateReplacement(KWLoc,
+                            PrevRecordDecl->getKindName());
+      Diag(PrevRecordDecl->getLocation(), diag::note_previous_use);
+      Kind = PrevRecordDecl->getTagKind();
+    }
+
+    // Check for redefinition of this class template.
+    if (TUK == TUK_Definition) {
+      if (TagDecl *Def = PrevRecordDecl->getDefinition(Context)) {
+        Diag(NameLoc, diag::err_redefinition) << Name;
+        Diag(Def->getLocation(), diag::note_previous_definition);
+        // FIXME: Would it make sense to try to "forget" the previous
+        // definition, as part of error recovery?
+        return true;
+      }
+    }
+  } else if (PrevDecl && PrevDecl->isTemplateParameter()) {
+    // Maybe we will complain about the shadowed template parameter.
+    DiagnoseTemplateParameterShadow(NameLoc, PrevDecl);
+    // Just pretend that we didn't see the previous declaration.
+    PrevDecl = 0;
+  } else if (PrevDecl) {
+    // C++ [temp]p5:
+    //   A class template shall not have the same name as any other
+    //   template, class, function, object, enumeration, enumerator,
+    //   namespace, or type in the same scope (3.3), except as specified
+    //   in (14.5.4).
+    Diag(NameLoc, diag::err_redefinition_different_kind) << Name;
+    Diag(PrevDecl->getLocation(), diag::note_previous_definition);
+    return true;
+  }
+
+  // Check the template parameter list of this declaration, possibly
+  // merging in the template parameter list from the previous class
+  // template declaration.
+  if (CheckTemplateParameterList(TemplateParams,
+            PrevClassTemplate? PrevClassTemplate->getTemplateParameters() : 0,
+                                 TPC_ClassTemplate))
+    Invalid = true;
+
+  // FIXME: If we had a scope specifier, we better have a previous template
+  // declaration!
+
+  CXXRecordDecl *NewClass =
+    CXXRecordDecl::Create(Context, Kind, SemanticContext, NameLoc, Name, KWLoc,
+                          PrevClassTemplate?
+                            PrevClassTemplate->getTemplatedDecl() : 0,
+                          /*DelayTypeCreation=*/true);
+
+  ClassTemplateDecl *NewTemplate
+    = ClassTemplateDecl::Create(Context, SemanticContext, NameLoc,
+                                DeclarationName(Name), TemplateParams,
+                                NewClass, PrevClassTemplate);
+  NewClass->setDescribedClassTemplate(NewTemplate);
+
+  // Build the type for the class template declaration now.
+  QualType T =
+    Context.getTypeDeclType(NewClass,
+                            PrevClassTemplate?
+                              PrevClassTemplate->getTemplatedDecl() : 0);
+  assert(T->isDependentType() && "Class template type is not dependent?");
+  (void)T;
+
+  // If we are providing an explicit specialization of a member that is a 
+  // class template, make a note of that.
+  if (PrevClassTemplate && 
+      PrevClassTemplate->getInstantiatedFromMemberTemplate())
+    PrevClassTemplate->setMemberSpecialization();
+  
+  // Set the access specifier.
+  if (!Invalid && TUK != TUK_Friend)
+    SetMemberAccessSpecifier(NewTemplate, PrevClassTemplate, AS);
+
+  // Set the lexical context of these templates
+  NewClass->setLexicalDeclContext(CurContext);
+  NewTemplate->setLexicalDeclContext(CurContext);
+
+  if (TUK == TUK_Definition)
+    NewClass->startDefinition();
+
+  if (Attr)
+    ProcessDeclAttributeList(S, NewClass, Attr);
+
+  if (TUK != TUK_Friend)
+    PushOnScopeChains(NewTemplate, S);
+  else {
+    if (PrevClassTemplate && PrevClassTemplate->getAccess() != AS_none) {
+      NewTemplate->setAccess(PrevClassTemplate->getAccess());
+      NewClass->setAccess(PrevClassTemplate->getAccess());
+    }
+
+    NewTemplate->setObjectOfFriendDecl(/* PreviouslyDeclared = */
+                                       PrevClassTemplate != NULL);
+    
+    // Friend templates are visible in fairly strange ways.
+    if (!CurContext->isDependentContext()) {
+      DeclContext *DC = SemanticContext->getLookupContext();
+      DC->makeDeclVisibleInContext(NewTemplate, /* Recoverable = */ false);
+      if (Scope *EnclosingScope = getScopeForDeclContext(S, DC))
+        PushOnScopeChains(NewTemplate, EnclosingScope,
+                          /* AddToContext = */ false);      
+    }
+    
+    FriendDecl *Friend = FriendDecl::Create(Context, CurContext,
+                                            NewClass->getLocation(),
+                                            NewTemplate,
+                                    /*FIXME:*/NewClass->getLocation());
+    Friend->setAccess(AS_public);
+    CurContext->addDecl(Friend);
+  }
+
+  if (Invalid) {
+    NewTemplate->setInvalidDecl();
+    NewClass->setInvalidDecl();
+  }
+  return DeclPtrTy::make(NewTemplate);
+}
+
+/// \brief Diagnose the presence of a default template argument on a
+/// template parameter, which is ill-formed in certain contexts.
+///
+/// \returns true if the default template argument should be dropped.
+static bool DiagnoseDefaultTemplateArgument(Sema &S, 
+                                            Sema::TemplateParamListContext TPC,
+                                            SourceLocation ParamLoc,
+                                            SourceRange DefArgRange) {
+  switch (TPC) {
+  case Sema::TPC_ClassTemplate:
+    return false;
+
+  case Sema::TPC_FunctionTemplate:
+    // C++ [temp.param]p9: 
+    //   A default template-argument shall not be specified in a
+    //   function template declaration or a function template
+    //   definition [...]
+    // (This sentence is not in C++0x, per DR226).
+    if (!S.getLangOptions().CPlusPlus0x)
+      S.Diag(ParamLoc, 
+             diag::err_template_parameter_default_in_function_template)
+        << DefArgRange;
+    return false;
+
+  case Sema::TPC_ClassTemplateMember:
+    // C++0x [temp.param]p9:
+    //   A default template-argument shall not be specified in the
+    //   template-parameter-lists of the definition of a member of a
+    //   class template that appears outside of the member's class.
+    S.Diag(ParamLoc, diag::err_template_parameter_default_template_member)
+      << DefArgRange;
+    return true;
+
+  case Sema::TPC_FriendFunctionTemplate:
+    // C++ [temp.param]p9:
+    //   A default template-argument shall not be specified in a
+    //   friend template declaration.
+    S.Diag(ParamLoc, diag::err_template_parameter_default_friend_template)
+      << DefArgRange;
+    return true;
+
+    // FIXME: C++0x [temp.param]p9 allows default template-arguments
+    // for friend function templates if there is only a single
+    // declaration (and it is a definition). Strange!
+  }
+
+  return false;
+}
+
+/// \brief Checks the validity of a template parameter list, possibly
+/// considering the template parameter list from a previous
+/// declaration.
+///
+/// If an "old" template parameter list is provided, it must be
+/// equivalent (per TemplateParameterListsAreEqual) to the "new"
+/// template parameter list.
+///
+/// \param NewParams Template parameter list for a new template
+/// declaration. This template parameter list will be updated with any
+/// default arguments that are carried through from the previous
+/// template parameter list.
+///
+/// \param OldParams If provided, template parameter list from a
+/// previous declaration of the same template. Default template
+/// arguments will be merged from the old template parameter list to
+/// the new template parameter list.
+///
+/// \param TPC Describes the context in which we are checking the given
+/// template parameter list.
+///
+/// \returns true if an error occurred, false otherwise.
+bool Sema::CheckTemplateParameterList(TemplateParameterList *NewParams,
+                                      TemplateParameterList *OldParams,
+                                      TemplateParamListContext TPC) {
+  bool Invalid = false;
+
+  // C++ [temp.param]p10:
+  //   The set of default template-arguments available for use with a
+  //   template declaration or definition is obtained by merging the
+  //   default arguments from the definition (if in scope) and all
+  //   declarations in scope in the same way default function
+  //   arguments are (8.3.6).
+  bool SawDefaultArgument = false;
+  SourceLocation PreviousDefaultArgLoc;
+
+  bool SawParameterPack = false;
+  SourceLocation ParameterPackLoc;
+
+  // Dummy initialization to avoid warnings.
+  TemplateParameterList::iterator OldParam = NewParams->end();
+  if (OldParams)
+    OldParam = OldParams->begin();
+
+  for (TemplateParameterList::iterator NewParam = NewParams->begin(),
+                                    NewParamEnd = NewParams->end();
+       NewParam != NewParamEnd; ++NewParam) {
+    // Variables used to diagnose redundant default arguments
+    bool RedundantDefaultArg = false;
+    SourceLocation OldDefaultLoc;
+    SourceLocation NewDefaultLoc;
+
+    // Variables used to diagnose missing default arguments
+    bool MissingDefaultArg = false;
+
+    // C++0x [temp.param]p11:
+    // If a template parameter of a class template is a template parameter pack,
+    // it must be the last template parameter.
+    if (SawParameterPack) {
+      Diag(ParameterPackLoc,
+           diag::err_template_param_pack_must_be_last_template_parameter);
+      Invalid = true;
+    }
+
+    if (TemplateTypeParmDecl *NewTypeParm
+          = dyn_cast<TemplateTypeParmDecl>(*NewParam)) {
+      // Check the presence of a default argument here.
+      if (NewTypeParm->hasDefaultArgument() && 
+          DiagnoseDefaultTemplateArgument(*this, TPC, 
+                                          NewTypeParm->getLocation(), 
+               NewTypeParm->getDefaultArgumentInfo()->getTypeLoc()
+                                                       .getFullSourceRange()))
+        NewTypeParm->removeDefaultArgument();
+
+      // Merge default arguments for template type parameters.
+      TemplateTypeParmDecl *OldTypeParm
+          = OldParams? cast<TemplateTypeParmDecl>(*OldParam) : 0;
+
+      if (NewTypeParm->isParameterPack()) {
+        assert(!NewTypeParm->hasDefaultArgument() &&
+               "Parameter packs can't have a default argument!");
+        SawParameterPack = true;
+        ParameterPackLoc = NewTypeParm->getLocation();
+      } else if (OldTypeParm && OldTypeParm->hasDefaultArgument() &&
+                 NewTypeParm->hasDefaultArgument()) {
+        OldDefaultLoc = OldTypeParm->getDefaultArgumentLoc();
+        NewDefaultLoc = NewTypeParm->getDefaultArgumentLoc();
+        SawDefaultArgument = true;
+        RedundantDefaultArg = true;
+        PreviousDefaultArgLoc = NewDefaultLoc;
+      } else if (OldTypeParm && OldTypeParm->hasDefaultArgument()) {
+        // Merge the default argument from the old declaration to the
+        // new declaration.
+        SawDefaultArgument = true;
+        NewTypeParm->setDefaultArgument(OldTypeParm->getDefaultArgumentInfo(),
+                                        true);
+        PreviousDefaultArgLoc = OldTypeParm->getDefaultArgumentLoc();
+      } else if (NewTypeParm->hasDefaultArgument()) {
+        SawDefaultArgument = true;
+        PreviousDefaultArgLoc = NewTypeParm->getDefaultArgumentLoc();
+      } else if (SawDefaultArgument)
+        MissingDefaultArg = true;
+    } else if (NonTypeTemplateParmDecl *NewNonTypeParm
+               = dyn_cast<NonTypeTemplateParmDecl>(*NewParam)) {
+      // Check the presence of a default argument here.
+      if (NewNonTypeParm->hasDefaultArgument() && 
+          DiagnoseDefaultTemplateArgument(*this, TPC, 
+                                          NewNonTypeParm->getLocation(), 
+                    NewNonTypeParm->getDefaultArgument()->getSourceRange())) {
+        NewNonTypeParm->getDefaultArgument()->Destroy(Context);
+        NewNonTypeParm->setDefaultArgument(0);
+      }
+
+      // Merge default arguments for non-type template parameters
+      NonTypeTemplateParmDecl *OldNonTypeParm
+        = OldParams? cast<NonTypeTemplateParmDecl>(*OldParam) : 0;
+      if (OldNonTypeParm && OldNonTypeParm->hasDefaultArgument() &&
+          NewNonTypeParm->hasDefaultArgument()) {
+        OldDefaultLoc = OldNonTypeParm->getDefaultArgumentLoc();
+        NewDefaultLoc = NewNonTypeParm->getDefaultArgumentLoc();
+        SawDefaultArgument = true;
+        RedundantDefaultArg = true;
+        PreviousDefaultArgLoc = NewDefaultLoc;
+      } else if (OldNonTypeParm && OldNonTypeParm->hasDefaultArgument()) {
+        // Merge the default argument from the old declaration to the
+        // new declaration.
+        SawDefaultArgument = true;
+        // FIXME: We need to create a new kind of "default argument"
+        // expression that points to a previous template template
+        // parameter.
+        NewNonTypeParm->setDefaultArgument(
+                                        OldNonTypeParm->getDefaultArgument());
+        PreviousDefaultArgLoc = OldNonTypeParm->getDefaultArgumentLoc();
+      } else if (NewNonTypeParm->hasDefaultArgument()) {
+        SawDefaultArgument = true;
+        PreviousDefaultArgLoc = NewNonTypeParm->getDefaultArgumentLoc();
+      } else if (SawDefaultArgument)
+        MissingDefaultArg = true;
+    } else {
+      // Check the presence of a default argument here.
+      TemplateTemplateParmDecl *NewTemplateParm
+        = cast<TemplateTemplateParmDecl>(*NewParam);
+      if (NewTemplateParm->hasDefaultArgument() && 
+          DiagnoseDefaultTemplateArgument(*this, TPC, 
+                                          NewTemplateParm->getLocation(), 
+                     NewTemplateParm->getDefaultArgument().getSourceRange()))
+        NewTemplateParm->setDefaultArgument(TemplateArgumentLoc());
+
+      // Merge default arguments for template template parameters
+      TemplateTemplateParmDecl *OldTemplateParm
+        = OldParams? cast<TemplateTemplateParmDecl>(*OldParam) : 0;
+      if (OldTemplateParm && OldTemplateParm->hasDefaultArgument() &&
+          NewTemplateParm->hasDefaultArgument()) {
+        OldDefaultLoc = OldTemplateParm->getDefaultArgument().getLocation();
+        NewDefaultLoc = NewTemplateParm->getDefaultArgument().getLocation();
+        SawDefaultArgument = true;
+        RedundantDefaultArg = true;
+        PreviousDefaultArgLoc = NewDefaultLoc;
+      } else if (OldTemplateParm && OldTemplateParm->hasDefaultArgument()) {
+        // Merge the default argument from the old declaration to the
+        // new declaration.
+        SawDefaultArgument = true;
+        // FIXME: We need to create a new kind of "default argument" expression
+        // that points to a previous template template parameter.
+        NewTemplateParm->setDefaultArgument(
+                                        OldTemplateParm->getDefaultArgument());
+        PreviousDefaultArgLoc
+          = OldTemplateParm->getDefaultArgument().getLocation();
+      } else if (NewTemplateParm->hasDefaultArgument()) {
+        SawDefaultArgument = true;
+        PreviousDefaultArgLoc
+          = NewTemplateParm->getDefaultArgument().getLocation();
+      } else if (SawDefaultArgument)
+        MissingDefaultArg = true;
+    }
+
+    if (RedundantDefaultArg) {
+      // C++ [temp.param]p12:
+      //   A template-parameter shall not be given default arguments
+      //   by two different declarations in the same scope.
+      Diag(NewDefaultLoc, diag::err_template_param_default_arg_redefinition);
+      Diag(OldDefaultLoc, diag::note_template_param_prev_default_arg);
+      Invalid = true;
+    } else if (MissingDefaultArg) {
+      // C++ [temp.param]p11:
+      //   If a template-parameter has a default template-argument,
+      //   all subsequent template-parameters shall have a default
+      //   template-argument supplied.
+      Diag((*NewParam)->getLocation(),
+           diag::err_template_param_default_arg_missing);
+      Diag(PreviousDefaultArgLoc, diag::note_template_param_prev_default_arg);
+      Invalid = true;
+    }
+
+    // If we have an old template parameter list that we're merging
+    // in, move on to the next parameter.
+    if (OldParams)
+      ++OldParam;
+  }
+
+  return Invalid;
+}
+
+/// \brief Match the given template parameter lists to the given scope
+/// specifier, returning the template parameter list that applies to the
+/// name.
+///
+/// \param DeclStartLoc the start of the declaration that has a scope
+/// specifier or a template parameter list.
+///
+/// \param SS the scope specifier that will be matched to the given template
+/// parameter lists. This scope specifier precedes a qualified name that is
+/// being declared.
+///
+/// \param ParamLists the template parameter lists, from the outermost to the
+/// innermost template parameter lists.
+///
+/// \param NumParamLists the number of template parameter lists in ParamLists.
+///
+/// \param IsExplicitSpecialization will be set true if the entity being
+/// declared is an explicit specialization, false otherwise.
+///
+/// \returns the template parameter list, if any, that corresponds to the
+/// name that is preceded by the scope specifier @p SS. This template
+/// parameter list may be have template parameters (if we're declaring a
+/// template) or may have no template parameters (if we're declaring a
+/// template specialization), or may be NULL (if we were's declaring isn't
+/// itself a template).
+TemplateParameterList *
+Sema::MatchTemplateParametersToScopeSpecifier(SourceLocation DeclStartLoc,
+                                              const CXXScopeSpec &SS,
+                                          TemplateParameterList **ParamLists,
+                                              unsigned NumParamLists,
+                                              bool &IsExplicitSpecialization) {
+  IsExplicitSpecialization = false;
+  
+  // Find the template-ids that occur within the nested-name-specifier. These
+  // template-ids will match up with the template parameter lists.
+  llvm::SmallVector<const TemplateSpecializationType *, 4>
+    TemplateIdsInSpecifier;
+  llvm::SmallVector<ClassTemplateSpecializationDecl *, 4>
+    ExplicitSpecializationsInSpecifier;
+  for (NestedNameSpecifier *NNS = (NestedNameSpecifier *)SS.getScopeRep();
+       NNS; NNS = NNS->getPrefix()) {
+    const Type *T = NNS->getAsType();
+    if (!T) break;
+
+    // C++0x [temp.expl.spec]p17:
+    //   A member or a member template may be nested within many
+    //   enclosing class templates. In an explicit specialization for
+    //   such a member, the member declaration shall be preceded by a
+    //   template<> for each enclosing class template that is
+    //   explicitly specialized.
+    // We interpret this as forbidding typedefs of template
+    // specializations in the scope specifiers of out-of-line decls.
+    if (const TypedefType *TT = dyn_cast<TypedefType>(T)) {
+      const Type *UnderlyingT = TT->LookThroughTypedefs().getTypePtr();
+      if (isa<TemplateSpecializationType>(UnderlyingT))
+        // FIXME: better source location information.
+        Diag(DeclStartLoc, diag::err_typedef_in_def_scope) << QualType(T,0);
+      T = UnderlyingT;
+    }
+
+    if (const TemplateSpecializationType *SpecType
+          = dyn_cast<TemplateSpecializationType>(T)) {
+      TemplateDecl *Template = SpecType->getTemplateName().getAsTemplateDecl();
+      if (!Template)
+        continue; // FIXME: should this be an error? probably...
+
+      if (const RecordType *Record = SpecType->getAs<RecordType>()) {
+        ClassTemplateSpecializationDecl *SpecDecl
+          = cast<ClassTemplateSpecializationDecl>(Record->getDecl());
+        // If the nested name specifier refers to an explicit specialization,
+        // we don't need a template<> header.
+        if (SpecDecl->getSpecializationKind() == TSK_ExplicitSpecialization) {
+          ExplicitSpecializationsInSpecifier.push_back(SpecDecl);
+          continue;
+        }
+      }
+
+      TemplateIdsInSpecifier.push_back(SpecType);
+    }
+  }
+
+  // Reverse the list of template-ids in the scope specifier, so that we can
+  // more easily match up the template-ids and the template parameter lists.
+  std::reverse(TemplateIdsInSpecifier.begin(), TemplateIdsInSpecifier.end());
+
+  SourceLocation FirstTemplateLoc = DeclStartLoc;
+  if (NumParamLists)
+    FirstTemplateLoc = ParamLists[0]->getTemplateLoc();
+
+  // Match the template-ids found in the specifier to the template parameter
+  // lists.
+  unsigned Idx = 0;
+  for (unsigned NumTemplateIds = TemplateIdsInSpecifier.size();
+       Idx != NumTemplateIds; ++Idx) {
+    QualType TemplateId = QualType(TemplateIdsInSpecifier[Idx], 0);
+    bool DependentTemplateId = TemplateId->isDependentType();
+    if (Idx >= NumParamLists) {
+      // We have a template-id without a corresponding template parameter
+      // list.
+      if (DependentTemplateId) {
+        // FIXME: the location information here isn't great.
+        Diag(SS.getRange().getBegin(),
+             diag::err_template_spec_needs_template_parameters)
+          << TemplateId
+          << SS.getRange();
+      } else {
+        Diag(SS.getRange().getBegin(), diag::err_template_spec_needs_header)
+          << SS.getRange()
+          << CodeModificationHint::CreateInsertion(FirstTemplateLoc,
+                                                   "template<> ");
+        IsExplicitSpecialization = true;
+      }
+      return 0;
+    }
+
+    // Check the template parameter list against its corresponding template-id.
+    if (DependentTemplateId) {
+      TemplateDecl *Template
+        = TemplateIdsInSpecifier[Idx]->getTemplateName().getAsTemplateDecl();
+
+      if (ClassTemplateDecl *ClassTemplate
+            = dyn_cast<ClassTemplateDecl>(Template)) {
+        TemplateParameterList *ExpectedTemplateParams = 0;
+        // Is this template-id naming the primary template?
+        if (Context.hasSameType(TemplateId,
+                             ClassTemplate->getInjectedClassNameType(Context)))
+          ExpectedTemplateParams = ClassTemplate->getTemplateParameters();
+        // ... or a partial specialization?
+        else if (ClassTemplatePartialSpecializationDecl *PartialSpec
+                   = ClassTemplate->findPartialSpecialization(TemplateId))
+          ExpectedTemplateParams = PartialSpec->getTemplateParameters();
+
+        if (ExpectedTemplateParams)
+          TemplateParameterListsAreEqual(ParamLists[Idx],
+                                         ExpectedTemplateParams,
+                                         true, TPL_TemplateMatch);
+      }
+
+      CheckTemplateParameterList(ParamLists[Idx], 0, TPC_ClassTemplateMember);
+    } else if (ParamLists[Idx]->size() > 0)
+      Diag(ParamLists[Idx]->getTemplateLoc(),
+           diag::err_template_param_list_matches_nontemplate)
+        << TemplateId
+        << ParamLists[Idx]->getSourceRange();
+    else
+      IsExplicitSpecialization = true;
+  }
+
+  // If there were at least as many template-ids as there were template
+  // parameter lists, then there are no template parameter lists remaining for
+  // the declaration itself.
+  if (Idx >= NumParamLists)
+    return 0;
+
+  // If there were too many template parameter lists, complain about that now.
+  if (Idx != NumParamLists - 1) {
+    while (Idx < NumParamLists - 1) {
+      bool isExplicitSpecHeader = ParamLists[Idx]->size() == 0;
+      Diag(ParamLists[Idx]->getTemplateLoc(),
+           isExplicitSpecHeader? diag::warn_template_spec_extra_headers
+                               : diag::err_template_spec_extra_headers)
+        << SourceRange(ParamLists[Idx]->getTemplateLoc(),
+                       ParamLists[Idx]->getRAngleLoc());
+
+      if (isExplicitSpecHeader && !ExplicitSpecializationsInSpecifier.empty()) {
+        Diag(ExplicitSpecializationsInSpecifier.back()->getLocation(),
+             diag::note_explicit_template_spec_does_not_need_header)
+          << ExplicitSpecializationsInSpecifier.back();
+        ExplicitSpecializationsInSpecifier.pop_back();
+      }
+        
+      ++Idx;
+    }
+  }
+
+  // Return the last template parameter list, which corresponds to the
+  // entity being declared.
+  return ParamLists[NumParamLists - 1];
+}
+
+QualType Sema::CheckTemplateIdType(TemplateName Name,
+                                   SourceLocation TemplateLoc,
+                              const TemplateArgumentListInfo &TemplateArgs) {
+  TemplateDecl *Template = Name.getAsTemplateDecl();
+  if (!Template) {
+    // The template name does not resolve to a template, so we just
+    // build a dependent template-id type.
+    return Context.getTemplateSpecializationType(Name, TemplateArgs);
+  }
+
+  // Check that the template argument list is well-formed for this
+  // template.
+  TemplateArgumentListBuilder Converted(Template->getTemplateParameters(),
+                                        TemplateArgs.size());
+  if (CheckTemplateArgumentList(Template, TemplateLoc, TemplateArgs,
+                                false, Converted))
+    return QualType();
+
+  assert((Converted.structuredSize() ==
+            Template->getTemplateParameters()->size()) &&
+         "Converted template argument list is too short!");
+
+  QualType CanonType;
+
+  if (Name.isDependent() ||
+      TemplateSpecializationType::anyDependentTemplateArguments(
+                                                      TemplateArgs)) {
+    // This class template specialization is a dependent
+    // type. Therefore, its canonical type is another class template
+    // specialization type that contains all of the converted
+    // arguments in canonical form. This ensures that, e.g., A<T> and
+    // A<T, T> have identical types when A is declared as:
+    //
+    //   template<typename T, typename U = T> struct A;
+    TemplateName CanonName = Context.getCanonicalTemplateName(Name);
+    CanonType = Context.getTemplateSpecializationType(CanonName,
+                                                   Converted.getFlatArguments(),
+                                                   Converted.flatSize());
+
+    // FIXME: CanonType is not actually the canonical type, and unfortunately
+    // it is a TemplateSpecializationType that we will never use again.
+    // In the future, we need to teach getTemplateSpecializationType to only
+    // build the canonical type and return that to us.
+    CanonType = Context.getCanonicalType(CanonType);
+  } else if (ClassTemplateDecl *ClassTemplate
+               = dyn_cast<ClassTemplateDecl>(Template)) {
+    // Find the class template specialization declaration that
+    // corresponds to these arguments.
+    llvm::FoldingSetNodeID ID;
+    ClassTemplateSpecializationDecl::Profile(ID,
+                                             Converted.getFlatArguments(),
+                                             Converted.flatSize(),
+                                             Context);
+    void *InsertPos = 0;
+    ClassTemplateSpecializationDecl *Decl
+      = ClassTemplate->getSpecializations().FindNodeOrInsertPos(ID, InsertPos);
+    if (!Decl) {
+      // This is the first time we have referenced this class template
+      // specialization. Create the canonical declaration and add it to
+      // the set of specializations.
+      Decl = ClassTemplateSpecializationDecl::Create(Context,
+                                    ClassTemplate->getDeclContext(),
+                                    ClassTemplate->getLocation(),
+                                    ClassTemplate,
+                                    Converted, 0);
+      ClassTemplate->getSpecializations().InsertNode(Decl, InsertPos);
+      Decl->setLexicalDeclContext(CurContext);
+    }
+
+    CanonType = Context.getTypeDeclType(Decl);
+  }
+
+  // Build the fully-sugared type for this class template
+  // specialization, which refers back to the class template
+  // specialization we created or found.
+  return Context.getTemplateSpecializationType(Name, TemplateArgs, CanonType);
+}
+
+Action::TypeResult
+Sema::ActOnTemplateIdType(TemplateTy TemplateD, SourceLocation TemplateLoc,
+                          SourceLocation LAngleLoc,
+                          ASTTemplateArgsPtr TemplateArgsIn,
+                          SourceLocation RAngleLoc) {
+  TemplateName Template = TemplateD.getAsVal<TemplateName>();
+
+  // Translate the parser's template argument list in our AST format.
+  TemplateArgumentListInfo TemplateArgs(LAngleLoc, RAngleLoc);
+  translateTemplateArguments(TemplateArgsIn, TemplateArgs);
+
+  QualType Result = CheckTemplateIdType(Template, TemplateLoc, TemplateArgs);
+  TemplateArgsIn.release();
+
+  if (Result.isNull())
+    return true;
+
+  TypeSourceInfo *DI = Context.CreateTypeSourceInfo(Result);
+  TemplateSpecializationTypeLoc TL
+    = cast<TemplateSpecializationTypeLoc>(DI->getTypeLoc());
+  TL.setTemplateNameLoc(TemplateLoc);
+  TL.setLAngleLoc(LAngleLoc);
+  TL.setRAngleLoc(RAngleLoc);
+  for (unsigned i = 0, e = TL.getNumArgs(); i != e; ++i)
+    TL.setArgLocInfo(i, TemplateArgs[i].getLocInfo());
+
+  return CreateLocInfoType(Result, DI).getAsOpaquePtr();
+}
+
+Sema::TypeResult Sema::ActOnTagTemplateIdType(TypeResult TypeResult,
+                                              TagUseKind TUK,
+                                              DeclSpec::TST TagSpec,
+                                              SourceLocation TagLoc) {
+  if (TypeResult.isInvalid())
+    return Sema::TypeResult();
+
+  // FIXME: preserve source info, ideally without copying the DI.
+  TypeSourceInfo *DI;
+  QualType Type = GetTypeFromParser(TypeResult.get(), &DI);
+
+  // Verify the tag specifier.
+  TagDecl::TagKind TagKind = TagDecl::getTagKindForTypeSpec(TagSpec);
+
+  if (const RecordType *RT = Type->getAs<RecordType>()) {
+    RecordDecl *D = RT->getDecl();
+
+    IdentifierInfo *Id = D->getIdentifier();
+    assert(Id && "templated class must have an identifier");
+
+    if (!isAcceptableTagRedeclaration(D, TagKind, TagLoc, *Id)) {
+      Diag(TagLoc, diag::err_use_with_wrong_tag)
+        << Type
+        << CodeModificationHint::CreateReplacement(SourceRange(TagLoc),
+                                                   D->getKindName());
+      Diag(D->getLocation(), diag::note_previous_use);
+    }
+  }
+
+  QualType ElabType = Context.getElaboratedType(Type, TagKind);
+
+  return ElabType.getAsOpaquePtr();
+}
+
+Sema::OwningExprResult Sema::BuildTemplateIdExpr(const CXXScopeSpec &SS,
+                                                 LookupResult &R,
+                                                 bool RequiresADL,
+                                 const TemplateArgumentListInfo &TemplateArgs) {
+  // FIXME: Can we do any checking at this point? I guess we could check the
+  // template arguments that we have against the template name, if the template
+  // name refers to a single template. That's not a terribly common case,
+  // though.
+
+  // These should be filtered out by our callers.
+  assert(!R.empty() && "empty lookup results when building templateid");
+  assert(!R.isAmbiguous() && "ambiguous lookup when building templateid");
+
+  NestedNameSpecifier *Qualifier = 0;
+  SourceRange QualifierRange;
+  if (SS.isSet()) {
+    Qualifier = static_cast<NestedNameSpecifier*>(SS.getScopeRep());
+    QualifierRange = SS.getRange();
+  }
+
+  // We don't want lookup warnings at this point.
+  R.suppressDiagnostics();
+  
+  bool Dependent
+    = UnresolvedLookupExpr::ComputeDependence(R.begin(), R.end(),
+                                              &TemplateArgs);
+  UnresolvedLookupExpr *ULE
+    = UnresolvedLookupExpr::Create(Context, Dependent, R.getNamingClass(),
+                                   Qualifier, QualifierRange,
+                                   R.getLookupName(), R.getNameLoc(),
+                                   RequiresADL, TemplateArgs);
+  ULE->addDecls(R.begin(), R.end());
+
+  return Owned(ULE);
+}
+
+// We actually only call this from template instantiation.
+Sema::OwningExprResult
+Sema::BuildQualifiedTemplateIdExpr(const CXXScopeSpec &SS,
+                                   DeclarationName Name,
+                                   SourceLocation NameLoc,
+                             const TemplateArgumentListInfo &TemplateArgs) {
+  DeclContext *DC;
+  if (!(DC = computeDeclContext(SS, false)) ||
+      DC->isDependentContext() ||
+      RequireCompleteDeclContext(SS))
+    return BuildDependentDeclRefExpr(SS, Name, NameLoc, &TemplateArgs);
+
+  LookupResult R(*this, Name, NameLoc, LookupOrdinaryName);
+  LookupTemplateName(R, (Scope*) 0, SS, QualType(), /*Entering*/ false);
+
+  if (R.isAmbiguous())
+    return ExprError();
+  
+  if (R.empty()) {
+    Diag(NameLoc, diag::err_template_kw_refers_to_non_template)
+      << Name << SS.getRange();
+    return ExprError();
+  }
+
+  if (ClassTemplateDecl *Temp = R.getAsSingle<ClassTemplateDecl>()) {
+    Diag(NameLoc, diag::err_template_kw_refers_to_class_template)
+      << (NestedNameSpecifier*) SS.getScopeRep() << Name << SS.getRange();
+    Diag(Temp->getLocation(), diag::note_referenced_class_template);
+    return ExprError();
+  }
+
+  return BuildTemplateIdExpr(SS, R, /* ADL */ false, TemplateArgs);
+}
+
+/// \brief Form a dependent template name.
+///
+/// This action forms a dependent template name given the template
+/// name and its (presumably dependent) scope specifier. For
+/// example, given "MetaFun::template apply", the scope specifier \p
+/// SS will be "MetaFun::", \p TemplateKWLoc contains the location
+/// of the "template" keyword, and "apply" is the \p Name.
+Sema::TemplateTy
+Sema::ActOnDependentTemplateName(SourceLocation TemplateKWLoc,
+                                 const CXXScopeSpec &SS,
+                                 UnqualifiedId &Name,
+                                 TypeTy *ObjectType,
+                                 bool EnteringContext) {
+  DeclContext *LookupCtx = 0;
+  if (SS.isSet())
+    LookupCtx = computeDeclContext(SS, EnteringContext);
+  if (!LookupCtx && ObjectType)
+    LookupCtx = computeDeclContext(QualType::getFromOpaquePtr(ObjectType));
+  if (LookupCtx) {
+    // C++0x [temp.names]p5:
+    //   If a name prefixed by the keyword template is not the name of
+    //   a template, the program is ill-formed. [Note: the keyword
+    //   template may not be applied to non-template members of class
+    //   templates. -end note ] [ Note: as is the case with the
+    //   typename prefix, the template prefix is allowed in cases
+    //   where it is not strictly necessary; i.e., when the
+    //   nested-name-specifier or the expression on the left of the ->
+    //   or . is not dependent on a template-parameter, or the use
+    //   does not appear in the scope of a template. -end note]
+    //
+    // Note: C++03 was more strict here, because it banned the use of
+    // the "template" keyword prior to a template-name that was not a
+    // dependent name. C++ DR468 relaxed this requirement (the
+    // "template" keyword is now permitted). We follow the C++0x
+    // rules, even in C++03 mode, retroactively applying the DR.
+    TemplateTy Template;
+    TemplateNameKind TNK = isTemplateName(0, SS, Name, ObjectType,
+                                          EnteringContext, Template);
+    if (TNK == TNK_Non_template && LookupCtx->isDependentContext() &&
+        isa<CXXRecordDecl>(LookupCtx) &&
+        cast<CXXRecordDecl>(LookupCtx)->hasAnyDependentBases()) {
+      // This is a dependent template.
+    } else if (TNK == TNK_Non_template) {
+      Diag(Name.getSourceRange().getBegin(), 
+           diag::err_template_kw_refers_to_non_template)
+        << GetNameFromUnqualifiedId(Name)
+        << Name.getSourceRange();
+      return TemplateTy();
+    } else {
+      // We found something; return it.
+      return Template;
+    }
+  }
+
+  NestedNameSpecifier *Qualifier
+    = static_cast<NestedNameSpecifier *>(SS.getScopeRep());
+  
+  switch (Name.getKind()) {
+  case UnqualifiedId::IK_Identifier:
+    return TemplateTy::make(Context.getDependentTemplateName(Qualifier, 
+                                                             Name.Identifier));
+    
+  case UnqualifiedId::IK_OperatorFunctionId:
+    return TemplateTy::make(Context.getDependentTemplateName(Qualifier,
+                                             Name.OperatorFunctionId.Operator));
+
+  case UnqualifiedId::IK_LiteralOperatorId:
+    assert(false && "We don't support these; Parse shouldn't have allowed propagation");
+
+  default:
+    break;
+  }
+  
+  Diag(Name.getSourceRange().getBegin(), 
+       diag::err_template_kw_refers_to_non_template)
+    << GetNameFromUnqualifiedId(Name)
+    << Name.getSourceRange();
+  return TemplateTy();
+}
+
+bool Sema::CheckTemplateTypeArgument(TemplateTypeParmDecl *Param,
+                                     const TemplateArgumentLoc &AL,
+                                     TemplateArgumentListBuilder &Converted) {
+  const TemplateArgument &Arg = AL.getArgument();
+
+  // Check template type parameter.
+  if (Arg.getKind() != TemplateArgument::Type) {
+    // C++ [temp.arg.type]p1:
+    //   A template-argument for a template-parameter which is a
+    //   type shall be a type-id.
+
+    // We have a template type parameter but the template argument
+    // is not a type.
+    SourceRange SR = AL.getSourceRange();
+    Diag(SR.getBegin(), diag::err_template_arg_must_be_type) << SR;
+    Diag(Param->getLocation(), diag::note_template_param_here);
+
+    return true;
+  }
+
+  if (CheckTemplateArgument(Param, AL.getTypeSourceInfo()))
+    return true;
+
+  // Add the converted template type argument.
+  Converted.Append(
+                 TemplateArgument(Context.getCanonicalType(Arg.getAsType())));
+  return false;
+}
+
+/// \brief Substitute template arguments into the default template argument for
+/// the given template type parameter.
+///
+/// \param SemaRef the semantic analysis object for which we are performing
+/// the substitution.
+///
+/// \param Template the template that we are synthesizing template arguments 
+/// for.
+///
+/// \param TemplateLoc the location of the template name that started the
+/// template-id we are checking.
+///
+/// \param RAngleLoc the location of the right angle bracket ('>') that
+/// terminates the template-id.
+///
+/// \param Param the template template parameter whose default we are
+/// substituting into.
+///
+/// \param Converted the list of template arguments provided for template
+/// parameters that precede \p Param in the template parameter list.
+///
+/// \returns the substituted template argument, or NULL if an error occurred.
+static TypeSourceInfo *
+SubstDefaultTemplateArgument(Sema &SemaRef,
+                             TemplateDecl *Template,
+                             SourceLocation TemplateLoc,
+                             SourceLocation RAngleLoc,
+                             TemplateTypeParmDecl *Param,
+                             TemplateArgumentListBuilder &Converted) {
+  TypeSourceInfo *ArgType = Param->getDefaultArgumentInfo();
+
+  // If the argument type is dependent, instantiate it now based
+  // on the previously-computed template arguments.
+  if (ArgType->getType()->isDependentType()) {
+    TemplateArgumentList TemplateArgs(SemaRef.Context, Converted,
+                                      /*TakeArgs=*/false);
+    
+    MultiLevelTemplateArgumentList AllTemplateArgs
+      = SemaRef.getTemplateInstantiationArgs(Template, &TemplateArgs);
+
+    Sema::InstantiatingTemplate Inst(SemaRef, TemplateLoc,
+                                     Template, Converted.getFlatArguments(),
+                                     Converted.flatSize(),
+                                     SourceRange(TemplateLoc, RAngleLoc));
+    
+    ArgType = SemaRef.SubstType(ArgType, AllTemplateArgs,
+                                Param->getDefaultArgumentLoc(),
+                                Param->getDeclName());
+  }
+
+  return ArgType;
+}
+
+/// \brief Substitute template arguments into the default template argument for
+/// the given non-type template parameter.
+///
+/// \param SemaRef the semantic analysis object for which we are performing
+/// the substitution.
+///
+/// \param Template the template that we are synthesizing template arguments 
+/// for.
+///
+/// \param TemplateLoc the location of the template name that started the
+/// template-id we are checking.
+///
+/// \param RAngleLoc the location of the right angle bracket ('>') that
+/// terminates the template-id.
+///
+/// \param Param the non-type template parameter whose default we are
+/// substituting into.
+///
+/// \param Converted the list of template arguments provided for template
+/// parameters that precede \p Param in the template parameter list.
+///
+/// \returns the substituted template argument, or NULL if an error occurred.
+static Sema::OwningExprResult
+SubstDefaultTemplateArgument(Sema &SemaRef,
+                             TemplateDecl *Template,
+                             SourceLocation TemplateLoc,
+                             SourceLocation RAngleLoc,
+                             NonTypeTemplateParmDecl *Param,
+                             TemplateArgumentListBuilder &Converted) {
+  TemplateArgumentList TemplateArgs(SemaRef.Context, Converted,
+                                    /*TakeArgs=*/false);
+    
+  MultiLevelTemplateArgumentList AllTemplateArgs
+    = SemaRef.getTemplateInstantiationArgs(Template, &TemplateArgs);
+    
+  Sema::InstantiatingTemplate Inst(SemaRef, TemplateLoc,
+                                   Template, Converted.getFlatArguments(),
+                                   Converted.flatSize(),
+                                   SourceRange(TemplateLoc, RAngleLoc));
+
+  return SemaRef.SubstExpr(Param->getDefaultArgument(), AllTemplateArgs);
+}
+
+/// \brief Substitute template arguments into the default template argument for
+/// the given template template parameter.
+///
+/// \param SemaRef the semantic analysis object for which we are performing
+/// the substitution.
+///
+/// \param Template the template that we are synthesizing template arguments 
+/// for.
+///
+/// \param TemplateLoc the location of the template name that started the
+/// template-id we are checking.
+///
+/// \param RAngleLoc the location of the right angle bracket ('>') that
+/// terminates the template-id.
+///
+/// \param Param the template template parameter whose default we are
+/// substituting into.
+///
+/// \param Converted the list of template arguments provided for template
+/// parameters that precede \p Param in the template parameter list.
+///
+/// \returns the substituted template argument, or NULL if an error occurred.
+static TemplateName
+SubstDefaultTemplateArgument(Sema &SemaRef,
+                             TemplateDecl *Template,
+                             SourceLocation TemplateLoc,
+                             SourceLocation RAngleLoc,
+                             TemplateTemplateParmDecl *Param,
+                             TemplateArgumentListBuilder &Converted) {
+  TemplateArgumentList TemplateArgs(SemaRef.Context, Converted,
+                                    /*TakeArgs=*/false);
+  
+  MultiLevelTemplateArgumentList AllTemplateArgs
+    = SemaRef.getTemplateInstantiationArgs(Template, &TemplateArgs);
+  
+  Sema::InstantiatingTemplate Inst(SemaRef, TemplateLoc,
+                                   Template, Converted.getFlatArguments(),
+                                   Converted.flatSize(),
+                                   SourceRange(TemplateLoc, RAngleLoc));
+  
+  return SemaRef.SubstTemplateName(
+                      Param->getDefaultArgument().getArgument().getAsTemplate(),
+                              Param->getDefaultArgument().getTemplateNameLoc(), 
+                                   AllTemplateArgs);
+}
+
+/// \brief If the given template parameter has a default template
+/// argument, substitute into that default template argument and
+/// return the corresponding template argument.
+TemplateArgumentLoc 
+Sema::SubstDefaultTemplateArgumentIfAvailable(TemplateDecl *Template,
+                                              SourceLocation TemplateLoc,
+                                              SourceLocation RAngleLoc,
+                                              Decl *Param,
+                                     TemplateArgumentListBuilder &Converted) {
+  if (TemplateTypeParmDecl *TypeParm = dyn_cast<TemplateTypeParmDecl>(Param)) {
+    if (!TypeParm->hasDefaultArgument())
+      return TemplateArgumentLoc();
+
+    TypeSourceInfo *DI = SubstDefaultTemplateArgument(*this, Template,
+                                                      TemplateLoc,
+                                                      RAngleLoc,
+                                                      TypeParm,
+                                                      Converted);
+    if (DI)
+      return TemplateArgumentLoc(TemplateArgument(DI->getType()), DI);
+
+    return TemplateArgumentLoc();
+  }
+
+  if (NonTypeTemplateParmDecl *NonTypeParm
+        = dyn_cast<NonTypeTemplateParmDecl>(Param)) {
+    if (!NonTypeParm->hasDefaultArgument())
+      return TemplateArgumentLoc();
+
+    OwningExprResult Arg = SubstDefaultTemplateArgument(*this, Template,
+                                                        TemplateLoc,
+                                                        RAngleLoc,
+                                                        NonTypeParm,
+                                                        Converted);
+    if (Arg.isInvalid())
+      return TemplateArgumentLoc();
+
+    Expr *ArgE = Arg.takeAs<Expr>();
+    return TemplateArgumentLoc(TemplateArgument(ArgE), ArgE);
+  }
+
+  TemplateTemplateParmDecl *TempTempParm
+    = cast<TemplateTemplateParmDecl>(Param);
+  if (!TempTempParm->hasDefaultArgument())
+    return TemplateArgumentLoc();
+
+  TemplateName TName = SubstDefaultTemplateArgument(*this, Template,
+                                                    TemplateLoc, 
+                                                    RAngleLoc,
+                                                    TempTempParm,
+                                                    Converted);
+  if (TName.isNull())
+    return TemplateArgumentLoc();
+
+  return TemplateArgumentLoc(TemplateArgument(TName), 
+                TempTempParm->getDefaultArgument().getTemplateQualifierRange(),
+                TempTempParm->getDefaultArgument().getTemplateNameLoc());
+}
+
+/// \brief Check that the given template argument corresponds to the given
+/// template parameter.
+bool Sema::CheckTemplateArgument(NamedDecl *Param,
+                                 const TemplateArgumentLoc &Arg,
+                                 TemplateDecl *Template,
+                                 SourceLocation TemplateLoc,
+                                 SourceLocation RAngleLoc,
+                                 TemplateArgumentListBuilder &Converted) {
+  // Check template type parameters.
+  if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(Param))
+    return CheckTemplateTypeArgument(TTP, Arg, Converted);
+  
+  // Check non-type template parameters.
+  if (NonTypeTemplateParmDecl *NTTP =dyn_cast<NonTypeTemplateParmDecl>(Param)) {    
+    // Do substitution on the type of the non-type template parameter
+    // with the template arguments we've seen thus far.
+    QualType NTTPType = NTTP->getType();
+    if (NTTPType->isDependentType()) {
+      // Do substitution on the type of the non-type template parameter.
+      InstantiatingTemplate Inst(*this, TemplateLoc, Template,
+                                 NTTP, Converted.getFlatArguments(),
+                                 Converted.flatSize(),
+                                 SourceRange(TemplateLoc, RAngleLoc));
+      
+      TemplateArgumentList TemplateArgs(Context, Converted,
+                                        /*TakeArgs=*/false);
+      NTTPType = SubstType(NTTPType,
+                           MultiLevelTemplateArgumentList(TemplateArgs),
+                           NTTP->getLocation(),
+                           NTTP->getDeclName());
+      // If that worked, check the non-type template parameter type
+      // for validity.
+      if (!NTTPType.isNull())
+        NTTPType = CheckNonTypeTemplateParameterType(NTTPType,
+                                                     NTTP->getLocation());
+      if (NTTPType.isNull())
+        return true;
+    }
+    
+    switch (Arg.getArgument().getKind()) {
+    case TemplateArgument::Null:
+      assert(false && "Should never see a NULL template argument here");
+      return true;
+      
+    case TemplateArgument::Expression: {
+      Expr *E = Arg.getArgument().getAsExpr();
+      TemplateArgument Result;
+      if (CheckTemplateArgument(NTTP, NTTPType, E, Result))
+        return true;
+      
+      Converted.Append(Result);
+      break;
+    }
+      
+    case TemplateArgument::Declaration:
+    case TemplateArgument::Integral:
+      // We've already checked this template argument, so just copy
+      // it to the list of converted arguments.
+      Converted.Append(Arg.getArgument());
+      break;
+      
+    case TemplateArgument::Template:
+      // We were given a template template argument. It may not be ill-formed;
+      // see below.
+      if (DependentTemplateName *DTN
+            = Arg.getArgument().getAsTemplate().getAsDependentTemplateName()) {
+        // We have a template argument such as \c T::template X, which we
+        // parsed as a template template argument. However, since we now
+        // know that we need a non-type template argument, convert this
+        // template name into an expression.          
+        Expr *E = DependentScopeDeclRefExpr::Create(Context,
+                                                    DTN->getQualifier(),
+                                               Arg.getTemplateQualifierRange(),
+                                                    DTN->getIdentifier(),
+                                                    Arg.getTemplateNameLoc());
+        
+        TemplateArgument Result;
+        if (CheckTemplateArgument(NTTP, NTTPType, E, Result))
+          return true;
+        
+        Converted.Append(Result);
+        break;
+      }
+      
+      // We have a template argument that actually does refer to a class
+      // template, template alias, or template template parameter, and
+      // therefore cannot be a non-type template argument.
+      Diag(Arg.getLocation(), diag::err_template_arg_must_be_expr)
+        << Arg.getSourceRange();
+      
+      Diag(Param->getLocation(), diag::note_template_param_here);
+      return true;
+      
+    case TemplateArgument::Type: {
+      // We have a non-type template parameter but the template
+      // argument is a type.
+      
+      // C++ [temp.arg]p2:
+      //   In a template-argument, an ambiguity between a type-id and
+      //   an expression is resolved to a type-id, regardless of the
+      //   form of the corresponding template-parameter.
+      //
+      // We warn specifically about this case, since it can be rather
+      // confusing for users.
+      QualType T = Arg.getArgument().getAsType();
+      SourceRange SR = Arg.getSourceRange();
+      if (T->isFunctionType())
+        Diag(SR.getBegin(), diag::err_template_arg_nontype_ambig) << SR << T;
+      else
+        Diag(SR.getBegin(), diag::err_template_arg_must_be_expr) << SR;
+      Diag(Param->getLocation(), diag::note_template_param_here);
+      return true;
+    }
+      
+    case TemplateArgument::Pack:
+      llvm_unreachable("Caller must expand template argument packs");
+      break;
+    }
+    
+    return false;
+  } 
+  
+  
+  // Check template template parameters.
+  TemplateTemplateParmDecl *TempParm = cast<TemplateTemplateParmDecl>(Param);
+    
+  // Substitute into the template parameter list of the template
+  // template parameter, since previously-supplied template arguments
+  // may appear within the template template parameter.
+  {
+    // Set up a template instantiation context.
+    LocalInstantiationScope Scope(*this);
+    InstantiatingTemplate Inst(*this, TemplateLoc, Template,
+                               TempParm, Converted.getFlatArguments(),
+                               Converted.flatSize(),
+                               SourceRange(TemplateLoc, RAngleLoc));
+    
+    TemplateArgumentList TemplateArgs(Context, Converted,
+                                      /*TakeArgs=*/false);
+    TempParm = cast_or_null<TemplateTemplateParmDecl>(
+                      SubstDecl(TempParm, CurContext, 
+                                MultiLevelTemplateArgumentList(TemplateArgs)));
+    if (!TempParm)
+      return true;
+    
+    // FIXME: TempParam is leaked.
+  }
+    
+  switch (Arg.getArgument().getKind()) {
+  case TemplateArgument::Null:
+    assert(false && "Should never see a NULL template argument here");
+    return true;
+    
+  case TemplateArgument::Template:
+    if (CheckTemplateArgument(TempParm, Arg))
+      return true;
+      
+    Converted.Append(Arg.getArgument());
+    break;
+    
+  case TemplateArgument::Expression:
+  case TemplateArgument::Type:
+    // We have a template template parameter but the template
+    // argument does not refer to a template.
+    Diag(Arg.getLocation(), diag::err_template_arg_must_be_template);
+    return true;
+      
+  case TemplateArgument::Declaration:
+    llvm_unreachable(
+                       "Declaration argument with template template parameter");
+    break;
+  case TemplateArgument::Integral:
+    llvm_unreachable(
+                          "Integral argument with template template parameter");
+    break;
+    
+  case TemplateArgument::Pack:
+    llvm_unreachable("Caller must expand template argument packs");
+    break;
+  }
+  
+  return false;
+}
+
+/// \brief Check that the given template argument list is well-formed
+/// for specializing the given template.
+bool Sema::CheckTemplateArgumentList(TemplateDecl *Template,
+                                     SourceLocation TemplateLoc,
+                                const TemplateArgumentListInfo &TemplateArgs,
+                                     bool PartialTemplateArgs,
+                                     TemplateArgumentListBuilder &Converted) {
+  TemplateParameterList *Params = Template->getTemplateParameters();
+  unsigned NumParams = Params->size();
+  unsigned NumArgs = TemplateArgs.size();
+  bool Invalid = false;
+
+  SourceLocation RAngleLoc = TemplateArgs.getRAngleLoc();
+
+  bool HasParameterPack =
+    NumParams > 0 && Params->getParam(NumParams - 1)->isTemplateParameterPack();
+
+  if ((NumArgs > NumParams && !HasParameterPack) ||
+      (NumArgs < Params->getMinRequiredArguments() &&
+       !PartialTemplateArgs)) {
+    // FIXME: point at either the first arg beyond what we can handle,
+    // or the '>', depending on whether we have too many or too few
+    // arguments.
+    SourceRange Range;
+    if (NumArgs > NumParams)
+      Range = SourceRange(TemplateArgs[NumParams].getLocation(), RAngleLoc);
+    Diag(TemplateLoc, diag::err_template_arg_list_different_arity)
+      << (NumArgs > NumParams)
+      << (isa<ClassTemplateDecl>(Template)? 0 :
+          isa<FunctionTemplateDecl>(Template)? 1 :
+          isa<TemplateTemplateParmDecl>(Template)? 2 : 3)
+      << Template << Range;
+    Diag(Template->getLocation(), diag::note_template_decl_here)
+      << Params->getSourceRange();
+    Invalid = true;
+  }
+
+  // C++ [temp.arg]p1:
+  //   [...] The type and form of each template-argument specified in
+  //   a template-id shall match the type and form specified for the
+  //   corresponding parameter declared by the template in its
+  //   template-parameter-list.
+  unsigned ArgIdx = 0;
+  for (TemplateParameterList::iterator Param = Params->begin(),
+                                       ParamEnd = Params->end();
+       Param != ParamEnd; ++Param, ++ArgIdx) {
+    if (ArgIdx > NumArgs && PartialTemplateArgs)
+      break;
+
+    // If we have a template parameter pack, check every remaining template
+    // argument against that template parameter pack.
+    if ((*Param)->isTemplateParameterPack()) {
+      Converted.BeginPack();
+      for (; ArgIdx < NumArgs; ++ArgIdx) {
+        if (CheckTemplateArgument(*Param, TemplateArgs[ArgIdx], Template,
+                                  TemplateLoc, RAngleLoc, Converted)) {
+          Invalid = true;
+          break;
+        }
+      }
+      Converted.EndPack();
+      continue;
+    }
+    
+    if (ArgIdx < NumArgs) {
+      // Check the template argument we were given.
+      if (CheckTemplateArgument(*Param, TemplateArgs[ArgIdx], Template, 
+                                TemplateLoc, RAngleLoc, Converted))
+        return true;
+      
+      continue;
+    }
+    
+    // We have a default template argument that we will use.
+    TemplateArgumentLoc Arg;
+    
+    // Retrieve the default template argument from the template
+    // parameter. For each kind of template parameter, we substitute the
+    // template arguments provided thus far and any "outer" template arguments
+    // (when the template parameter was part of a nested template) into 
+    // the default argument.
+    if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(*Param)) {
+      if (!TTP->hasDefaultArgument()) {
+        assert((Invalid || PartialTemplateArgs) && "Missing default argument");
+        break;
+      }
+
+      TypeSourceInfo *ArgType = SubstDefaultTemplateArgument(*this, 
+                                                             Template,
+                                                             TemplateLoc,
+                                                             RAngleLoc,
+                                                             TTP,
+                                                             Converted);
+      if (!ArgType)
+        return true;
+                                                             
+      Arg = TemplateArgumentLoc(TemplateArgument(ArgType->getType()),
+                                ArgType);
+    } else if (NonTypeTemplateParmDecl *NTTP
+                 = dyn_cast<NonTypeTemplateParmDecl>(*Param)) {
+      if (!NTTP->hasDefaultArgument()) {
+        assert((Invalid || PartialTemplateArgs) && "Missing default argument");
+        break;
+      }
+
+      Sema::OwningExprResult E = SubstDefaultTemplateArgument(*this, Template,
+                                                              TemplateLoc, 
+                                                              RAngleLoc, 
+                                                              NTTP, 
+                                                              Converted);
+      if (E.isInvalid())
+        return true;
+
+      Expr *Ex = E.takeAs<Expr>();
+      Arg = TemplateArgumentLoc(TemplateArgument(Ex), Ex);
+    } else {
+      TemplateTemplateParmDecl *TempParm
+        = cast<TemplateTemplateParmDecl>(*Param);
+
+      if (!TempParm->hasDefaultArgument()) {
+        assert((Invalid || PartialTemplateArgs) && "Missing default argument");
+        break;
+      }
+
+      TemplateName Name = SubstDefaultTemplateArgument(*this, Template,
+                                                       TemplateLoc, 
+                                                       RAngleLoc, 
+                                                       TempParm,
+                                                       Converted);
+      if (Name.isNull())
+        return true;
+      
+      Arg = TemplateArgumentLoc(TemplateArgument(Name), 
+                  TempParm->getDefaultArgument().getTemplateQualifierRange(),
+                  TempParm->getDefaultArgument().getTemplateNameLoc());
+    }
+    
+    // Introduce an instantiation record that describes where we are using
+    // the default template argument.
+    InstantiatingTemplate Instantiating(*this, RAngleLoc, Template, *Param,
+                                        Converted.getFlatArguments(),
+                                        Converted.flatSize(),
+                                        SourceRange(TemplateLoc, RAngleLoc));    
+    
+    // Check the default template argument.
+    if (CheckTemplateArgument(*Param, Arg, Template, TemplateLoc,
+                              RAngleLoc, Converted))
+      return true;
+  }
+
+  return Invalid;
+}
+
+/// \brief Check a template argument against its corresponding
+/// template type parameter.
+///
+/// This routine implements the semantics of C++ [temp.arg.type]. It
+/// returns true if an error occurred, and false otherwise.
+bool Sema::CheckTemplateArgument(TemplateTypeParmDecl *Param,
+                                 TypeSourceInfo *ArgInfo) {
+  assert(ArgInfo && "invalid TypeSourceInfo");
+  QualType Arg = ArgInfo->getType();
+
+  // C++ [temp.arg.type]p2:
+  //   A local type, a type with no linkage, an unnamed type or a type
+  //   compounded from any of these types shall not be used as a
+  //   template-argument for a template type-parameter.
+  //
+  // FIXME: Perform the recursive and no-linkage type checks.
+  const TagType *Tag = 0;
+  if (const EnumType *EnumT = Arg->getAs<EnumType>())
+    Tag = EnumT;
+  else if (const RecordType *RecordT = Arg->getAs<RecordType>())
+    Tag = RecordT;
+  if (Tag && Tag->getDecl()->getDeclContext()->isFunctionOrMethod()) {
+    SourceRange SR = ArgInfo->getTypeLoc().getFullSourceRange();
+    return Diag(SR.getBegin(), diag::err_template_arg_local_type)
+      << QualType(Tag, 0) << SR;
+  } else if (Tag && !Tag->getDecl()->getDeclName() &&
+           !Tag->getDecl()->getTypedefForAnonDecl()) {
+    SourceRange SR = ArgInfo->getTypeLoc().getFullSourceRange();
+    Diag(SR.getBegin(), diag::err_template_arg_unnamed_type) << SR;
+    Diag(Tag->getDecl()->getLocation(), diag::note_template_unnamed_type_here);
+    return true;
+  } else if (Context.hasSameUnqualifiedType(Arg, Context.OverloadTy)) {
+    SourceRange SR = ArgInfo->getTypeLoc().getFullSourceRange();
+    return Diag(SR.getBegin(), diag::err_template_arg_overload_type) << SR;
+  }
+
+  return false;
+}
+
+/// \brief Checks whether the given template argument is the address
+/// of an object or function according to C++ [temp.arg.nontype]p1.
+bool Sema::CheckTemplateArgumentAddressOfObjectOrFunction(Expr *Arg,
+                                                          NamedDecl *&Entity) {
+  bool Invalid = false;
+
+  // See through any implicit casts we added to fix the type.
+  while (ImplicitCastExpr *Cast = dyn_cast<ImplicitCastExpr>(Arg))
+    Arg = Cast->getSubExpr();
+
+  // C++0x allows nullptr, and there's no further checking to be done for that.
+  if (Arg->getType()->isNullPtrType())
+    return false;
+
+  // C++ [temp.arg.nontype]p1:
+  //
+  //   A template-argument for a non-type, non-template
+  //   template-parameter shall be one of: [...]
+  //
+  //     -- the address of an object or function with external
+  //        linkage, including function templates and function
+  //        template-ids but excluding non-static class members,
+  //        expressed as & id-expression where the & is optional if
+  //        the name refers to a function or array, or if the
+  //        corresponding template-parameter is a reference; or
+  DeclRefExpr *DRE = 0;
+
+  // Ignore (and complain about) any excess parentheses.
+  while (ParenExpr *Parens = dyn_cast<ParenExpr>(Arg)) {
+    if (!Invalid) {
+      Diag(Arg->getSourceRange().getBegin(),
+           diag::err_template_arg_extra_parens)
+        << Arg->getSourceRange();
+      Invalid = true;
+    }
+
+    Arg = Parens->getSubExpr();
+  }
+
+  if (UnaryOperator *UnOp = dyn_cast<UnaryOperator>(Arg)) {
+    if (UnOp->getOpcode() == UnaryOperator::AddrOf)
+      DRE = dyn_cast<DeclRefExpr>(UnOp->getSubExpr());
+  } else
+    DRE = dyn_cast<DeclRefExpr>(Arg);
+
+  if (!DRE)
+    return Diag(Arg->getSourceRange().getBegin(),
+                diag::err_template_arg_not_decl_ref)
+      << Arg->getSourceRange();
+
+  // Stop checking the precise nature of the argument if it is value dependent,
+  // it should be checked when instantiated.
+  if (Arg->isValueDependent())
+    return false;
+
+  if (!isa<ValueDecl>(DRE->getDecl()))
+    return Diag(Arg->getSourceRange().getBegin(),
+                diag::err_template_arg_not_object_or_func_form)
+      << Arg->getSourceRange();
+
+  // Cannot refer to non-static data members
+  if (FieldDecl *Field = dyn_cast<FieldDecl>(DRE->getDecl()))
+    return Diag(Arg->getSourceRange().getBegin(), diag::err_template_arg_field)
+      << Field << Arg->getSourceRange();
+
+  // Cannot refer to non-static member functions
+  if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(DRE->getDecl()))
+    if (!Method->isStatic())
+      return Diag(Arg->getSourceRange().getBegin(),
+                  diag::err_template_arg_method)
+        << Method << Arg->getSourceRange();
+
+  // Functions must have external linkage.
+  if (FunctionDecl *Func = dyn_cast<FunctionDecl>(DRE->getDecl())) {
+    if (!isExternalLinkage(Func->getLinkage())) {
+      Diag(Arg->getSourceRange().getBegin(),
+           diag::err_template_arg_function_not_extern)
+        << Func << Arg->getSourceRange();
+      Diag(Func->getLocation(), diag::note_template_arg_internal_object)
+        << true;
+      return true;
+    }
+
+    // Okay: we've named a function with external linkage.
+    Entity = Func;
+    return Invalid;
+  }
+
+  if (VarDecl *Var = dyn_cast<VarDecl>(DRE->getDecl())) {
+    if (!isExternalLinkage(Var->getLinkage())) {
+      Diag(Arg->getSourceRange().getBegin(),
+           diag::err_template_arg_object_not_extern)
+        << Var << Arg->getSourceRange();
+      Diag(Var->getLocation(), diag::note_template_arg_internal_object)
+        << true;
+      return true;
+    }
+
+    // Okay: we've named an object with external linkage
+    Entity = Var;
+    return Invalid;
+  }
+
+  // We found something else, but we don't know specifically what it is.
+  Diag(Arg->getSourceRange().getBegin(),
+       diag::err_template_arg_not_object_or_func)
+      << Arg->getSourceRange();
+  Diag(DRE->getDecl()->getLocation(),
+       diag::note_template_arg_refers_here);
+  return true;
+}
+
+/// \brief Checks whether the given template argument is a pointer to
+/// member constant according to C++ [temp.arg.nontype]p1.
+bool Sema::CheckTemplateArgumentPointerToMember(Expr *Arg, 
+                                                TemplateArgument &Converted) {
+  bool Invalid = false;
+
+  // See through any implicit casts we added to fix the type.
+  while (ImplicitCastExpr *Cast = dyn_cast<ImplicitCastExpr>(Arg))
+    Arg = Cast->getSubExpr();
+
+  // C++0x allows nullptr, and there's no further checking to be done for that.
+  if (Arg->getType()->isNullPtrType())
+    return false;
+
+  // C++ [temp.arg.nontype]p1:
+  //
+  //   A template-argument for a non-type, non-template
+  //   template-parameter shall be one of: [...]
+  //
+  //     -- a pointer to member expressed as described in 5.3.1.
+  DeclRefExpr *DRE = 0;
+
+  // Ignore (and complain about) any excess parentheses.
+  while (ParenExpr *Parens = dyn_cast<ParenExpr>(Arg)) {
+    if (!Invalid) {
+      Diag(Arg->getSourceRange().getBegin(),
+           diag::err_template_arg_extra_parens)
+        << Arg->getSourceRange();
+      Invalid = true;
+    }
+
+    Arg = Parens->getSubExpr();
+  }
+
+  // A pointer-to-member constant written &Class::member.
+  if (UnaryOperator *UnOp = dyn_cast<UnaryOperator>(Arg)) {
+    if (UnOp->getOpcode() == UnaryOperator::AddrOf) {
+      DRE = dyn_cast<DeclRefExpr>(UnOp->getSubExpr());
+      if (DRE && !DRE->getQualifier())
+        DRE = 0;
+    }
+  } 
+  // A constant of pointer-to-member type.
+  else if ((DRE = dyn_cast<DeclRefExpr>(Arg))) {
+    if (ValueDecl *VD = dyn_cast<ValueDecl>(DRE->getDecl())) {
+      if (VD->getType()->isMemberPointerType()) {
+        if (isa<NonTypeTemplateParmDecl>(VD) ||
+            (isa<VarDecl>(VD) && 
+             Context.getCanonicalType(VD->getType()).isConstQualified())) {
+          if (Arg->isTypeDependent() || Arg->isValueDependent())
+            Converted = TemplateArgument(Arg->Retain());
+          else
+            Converted = TemplateArgument(VD->getCanonicalDecl());
+          return Invalid;
+        }
+      }
+    }
+    
+    DRE = 0;
+  }
+  
+  if (!DRE)
+    return Diag(Arg->getSourceRange().getBegin(),
+                diag::err_template_arg_not_pointer_to_member_form)
+      << Arg->getSourceRange();
+
+  if (isa<FieldDecl>(DRE->getDecl()) || isa<CXXMethodDecl>(DRE->getDecl())) {
+    assert((isa<FieldDecl>(DRE->getDecl()) ||
+            !cast<CXXMethodDecl>(DRE->getDecl())->isStatic()) &&
+           "Only non-static member pointers can make it here");
+
+    // Okay: this is the address of a non-static member, and therefore
+    // a member pointer constant.
+    if (Arg->isTypeDependent() || Arg->isValueDependent())
+      Converted = TemplateArgument(Arg->Retain());
+    else
+      Converted = TemplateArgument(DRE->getDecl()->getCanonicalDecl());
+    return Invalid;
+  }
+
+  // We found something else, but we don't know specifically what it is.
+  Diag(Arg->getSourceRange().getBegin(),
+       diag::err_template_arg_not_pointer_to_member_form)
+      << Arg->getSourceRange();
+  Diag(DRE->getDecl()->getLocation(),
+       diag::note_template_arg_refers_here);
+  return true;
+}
+
+/// \brief Check a template argument against its corresponding
+/// non-type template parameter.
+///
+/// This routine implements the semantics of C++ [temp.arg.nontype].
+/// It returns true if an error occurred, and false otherwise. \p
+/// InstantiatedParamType is the type of the non-type template
+/// parameter after it has been instantiated.
+///
+/// If no error was detected, Converted receives the converted template argument.
+bool Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
+                                 QualType InstantiatedParamType, Expr *&Arg,
+                                 TemplateArgument &Converted) {
+  SourceLocation StartLoc = Arg->getSourceRange().getBegin();
+
+  // If either the parameter has a dependent type or the argument is
+  // type-dependent, there's nothing we can check now.
+  // FIXME: Add template argument to Converted!
+  if (InstantiatedParamType->isDependentType() || Arg->isTypeDependent()) {
+    // FIXME: Produce a cloned, canonical expression?
+    Converted = TemplateArgument(Arg);
+    return false;
+  }
+
+  // C++ [temp.arg.nontype]p5:
+  //   The following conversions are performed on each expression used
+  //   as a non-type template-argument. If a non-type
+  //   template-argument cannot be converted to the type of the
+  //   corresponding template-parameter then the program is
+  //   ill-formed.
+  //
+  //     -- for a non-type template-parameter of integral or
+  //        enumeration type, integral promotions (4.5) and integral
+  //        conversions (4.7) are applied.
+  QualType ParamType = InstantiatedParamType;
+  QualType ArgType = Arg->getType();
+  if (ParamType->isIntegralType() || ParamType->isEnumeralType()) {
+    // C++ [temp.arg.nontype]p1:
+    //   A template-argument for a non-type, non-template
+    //   template-parameter shall be one of:
+    //
+    //     -- an integral constant-expression of integral or enumeration
+    //        type; or
+    //     -- the name of a non-type template-parameter; or
+    SourceLocation NonConstantLoc;
+    llvm::APSInt Value;
+    if (!ArgType->isIntegralType() && !ArgType->isEnumeralType()) {
+      Diag(Arg->getSourceRange().getBegin(),
+           diag::err_template_arg_not_integral_or_enumeral)
+        << ArgType << Arg->getSourceRange();
+      Diag(Param->getLocation(), diag::note_template_param_here);
+      return true;
+    } else if (!Arg->isValueDependent() &&
+               !Arg->isIntegerConstantExpr(Value, Context, &NonConstantLoc)) {
+      Diag(NonConstantLoc, diag::err_template_arg_not_ice)
+        << ArgType << Arg->getSourceRange();
+      return true;
+    }
+
+    // FIXME: We need some way to more easily get the unqualified form
+    // of the types without going all the way to the
+    // canonical type.
+    if (Context.getCanonicalType(ParamType).getCVRQualifiers())
+      ParamType = Context.getCanonicalType(ParamType).getUnqualifiedType();
+    if (Context.getCanonicalType(ArgType).getCVRQualifiers())
+      ArgType = Context.getCanonicalType(ArgType).getUnqualifiedType();
+
+    // Try to convert the argument to the parameter's type.
+    if (Context.hasSameType(ParamType, ArgType)) {
+      // Okay: no conversion necessary
+    } else if (IsIntegralPromotion(Arg, ArgType, ParamType) ||
+               !ParamType->isEnumeralType()) {
+      // This is an integral promotion or conversion.
+      ImpCastExprToType(Arg, ParamType, CastExpr::CK_IntegralCast);
+    } else {
+      // We can't perform this conversion.
+      Diag(Arg->getSourceRange().getBegin(),
+           diag::err_template_arg_not_convertible)
+        << Arg->getType() << InstantiatedParamType << Arg->getSourceRange();
+      Diag(Param->getLocation(), diag::note_template_param_here);
+      return true;
+    }
+
+    QualType IntegerType = Context.getCanonicalType(ParamType);
+    if (const EnumType *Enum = IntegerType->getAs<EnumType>())
+      IntegerType = Context.getCanonicalType(Enum->getDecl()->getIntegerType());
+
+    if (!Arg->isValueDependent()) {
+      // Check that an unsigned parameter does not receive a negative
+      // value.
+      if (IntegerType->isUnsignedIntegerType()
+          && (Value.isSigned() && Value.isNegative())) {
+        Diag(Arg->getSourceRange().getBegin(), diag::err_template_arg_negative)
+          << Value.toString(10) << Param->getType()
+          << Arg->getSourceRange();
+        Diag(Param->getLocation(), diag::note_template_param_here);
+        return true;
+      }
+
+      // Check that we don't overflow the template parameter type.
+      unsigned AllowedBits = Context.getTypeSize(IntegerType);
+      unsigned RequiredBits;
+      if (IntegerType->isUnsignedIntegerType())
+        RequiredBits = Value.getActiveBits();
+      else if (Value.isUnsigned())
+        RequiredBits = Value.getActiveBits() + 1;
+      else
+        RequiredBits = Value.getMinSignedBits();
+      if (RequiredBits > AllowedBits) {
+        Diag(Arg->getSourceRange().getBegin(),
+             diag::err_template_arg_too_large)
+          << Value.toString(10) << Param->getType()
+          << Arg->getSourceRange();
+        Diag(Param->getLocation(), diag::note_template_param_here);
+        return true;
+      }
+
+      if (Value.getBitWidth() != AllowedBits)
+        Value.extOrTrunc(AllowedBits);
+      Value.setIsSigned(IntegerType->isSignedIntegerType());
+    }
+
+    // Add the value of this argument to the list of converted
+    // arguments. We use the bitwidth and signedness of the template
+    // parameter.
+    if (Arg->isValueDependent()) {
+      // The argument is value-dependent. Create a new
+      // TemplateArgument with the converted expression.
+      Converted = TemplateArgument(Arg);
+      return false;
+    }
+
+    Converted = TemplateArgument(Value,
+                                 ParamType->isEnumeralType() ? ParamType
+                                                             : IntegerType);
+    return false;
+  }
+
+  // Handle pointer-to-function, reference-to-function, and
+  // pointer-to-member-function all in (roughly) the same way.
+  if (// -- For a non-type template-parameter of type pointer to
+      //    function, only the function-to-pointer conversion (4.3) is
+      //    applied. If the template-argument represents a set of
+      //    overloaded functions (or a pointer to such), the matching
+      //    function is selected from the set (13.4).
+      // In C++0x, any std::nullptr_t value can be converted.
+      (ParamType->isPointerType() &&
+       ParamType->getAs<PointerType>()->getPointeeType()->isFunctionType()) ||
+      // -- For a non-type template-parameter of type reference to
+      //    function, no conversions apply. If the template-argument
+      //    represents a set of overloaded functions, the matching
+      //    function is selected from the set (13.4).
+      (ParamType->isReferenceType() &&
+       ParamType->getAs<ReferenceType>()->getPointeeType()->isFunctionType()) ||
+      // -- For a non-type template-parameter of type pointer to
+      //    member function, no conversions apply. If the
+      //    template-argument represents a set of overloaded member
+      //    functions, the matching member function is selected from
+      //    the set (13.4).
+      // Again, C++0x allows a std::nullptr_t value.
+      (ParamType->isMemberPointerType() &&
+       ParamType->getAs<MemberPointerType>()->getPointeeType()
+         ->isFunctionType())) {
+    if (Context.hasSameUnqualifiedType(ArgType,
+                                       ParamType.getNonReferenceType())) {
+      // We don't have to do anything: the types already match.
+    } else if (ArgType->isNullPtrType() && (ParamType->isPointerType() ||
+                 ParamType->isMemberPointerType())) {
+      ArgType = ParamType;
+      if (ParamType->isMemberPointerType())
+        ImpCastExprToType(Arg, ParamType, CastExpr::CK_NullToMemberPointer);
+      else
+        ImpCastExprToType(Arg, ParamType, CastExpr::CK_BitCast);
+    } else if (ArgType->isFunctionType() && ParamType->isPointerType()) {
+      ArgType = Context.getPointerType(ArgType);
+      ImpCastExprToType(Arg, ArgType, CastExpr::CK_FunctionToPointerDecay);
+    } else if (FunctionDecl *Fn
+                 = ResolveAddressOfOverloadedFunction(Arg, ParamType, true)) {
+      if (DiagnoseUseOfDecl(Fn, Arg->getSourceRange().getBegin()))
+        return true;
+
+      Arg = FixOverloadedFunctionReference(Arg, Fn);
+      ArgType = Arg->getType();
+      if (ArgType->isFunctionType() && ParamType->isPointerType()) {
+        ArgType = Context.getPointerType(Arg->getType());
+        ImpCastExprToType(Arg, ArgType, CastExpr::CK_FunctionToPointerDecay);
+      }
+    }
+
+    if (!Context.hasSameUnqualifiedType(ArgType,
+                                        ParamType.getNonReferenceType())) {
+      // We can't perform this conversion.
+      Diag(Arg->getSourceRange().getBegin(),
+           diag::err_template_arg_not_convertible)
+        << Arg->getType() << InstantiatedParamType << Arg->getSourceRange();
+      Diag(Param->getLocation(), diag::note_template_param_here);
+      return true;
+    }
+
+    if (ParamType->isMemberPointerType())
+      return CheckTemplateArgumentPointerToMember(Arg, Converted);
+
+    NamedDecl *Entity = 0;
+    if (CheckTemplateArgumentAddressOfObjectOrFunction(Arg, Entity))
+      return true;
+
+    if (Arg->isValueDependent()) {
+      Converted = TemplateArgument(Arg);
+    } else {
+      if (Entity)
+        Entity = cast<NamedDecl>(Entity->getCanonicalDecl());
+      Converted = TemplateArgument(Entity);
+    }
+    return false;
+  }
+
+  if (ParamType->isPointerType()) {
+    //   -- for a non-type template-parameter of type pointer to
+    //      object, qualification conversions (4.4) and the
+    //      array-to-pointer conversion (4.2) are applied.
+    // C++0x also allows a value of std::nullptr_t.
+    assert(ParamType->getAs<PointerType>()->getPointeeType()->isObjectType() &&
+           "Only object pointers allowed here");
+
+    if (ArgType->isNullPtrType()) {
+      ArgType = ParamType;
+      ImpCastExprToType(Arg, ParamType, CastExpr::CK_BitCast);
+    } else if (ArgType->isArrayType()) {
+      ArgType = Context.getArrayDecayedType(ArgType);
+      ImpCastExprToType(Arg, ArgType, CastExpr::CK_ArrayToPointerDecay);
+    }
+
+    if (IsQualificationConversion(ArgType, ParamType)) {
+      ArgType = ParamType;
+      ImpCastExprToType(Arg, ParamType, CastExpr::CK_NoOp);
+    }
+
+    if (!Context.hasSameUnqualifiedType(ArgType, ParamType)) {
+      // We can't perform this conversion.
+      Diag(Arg->getSourceRange().getBegin(),
+           diag::err_template_arg_not_convertible)
+        << Arg->getType() << InstantiatedParamType << Arg->getSourceRange();
+      Diag(Param->getLocation(), diag::note_template_param_here);
+      return true;
+    }
+
+    NamedDecl *Entity = 0;
+    if (CheckTemplateArgumentAddressOfObjectOrFunction(Arg, Entity))
+      return true;
+
+    if (Arg->isValueDependent()) {
+      Converted = TemplateArgument(Arg);
+    } else {
+      if (Entity)
+        Entity = cast<NamedDecl>(Entity->getCanonicalDecl());
+      Converted = TemplateArgument(Entity);
+    }
+    return false;
+  }
+
+  if (const ReferenceType *ParamRefType = ParamType->getAs<ReferenceType>()) {
+    //   -- For a non-type template-parameter of type reference to
+    //      object, no conversions apply. The type referred to by the
+    //      reference may be more cv-qualified than the (otherwise
+    //      identical) type of the template-argument. The
+    //      template-parameter is bound directly to the
+    //      template-argument, which must be an lvalue.
+    assert(ParamRefType->getPointeeType()->isObjectType() &&
+           "Only object references allowed here");
+
+    QualType ReferredType = ParamRefType->getPointeeType();
+    if (!Context.hasSameUnqualifiedType(ReferredType, ArgType)) {
+      Diag(Arg->getSourceRange().getBegin(),
+           diag::err_template_arg_no_ref_bind)
+        << InstantiatedParamType << Arg->getType()
+        << Arg->getSourceRange();
+      Diag(Param->getLocation(), diag::note_template_param_here);
+      return true;
+    }
+
+    unsigned ParamQuals
+      = Context.getCanonicalType(ReferredType).getCVRQualifiers();
+    unsigned ArgQuals = Context.getCanonicalType(ArgType).getCVRQualifiers();
+
+    if ((ParamQuals | ArgQuals) != ParamQuals) {
+      Diag(Arg->getSourceRange().getBegin(),
+           diag::err_template_arg_ref_bind_ignores_quals)
+        << InstantiatedParamType << Arg->getType()
+        << Arg->getSourceRange();
+      Diag(Param->getLocation(), diag::note_template_param_here);
+      return true;
+    }
+
+    NamedDecl *Entity = 0;
+    if (CheckTemplateArgumentAddressOfObjectOrFunction(Arg, Entity))
+      return true;
+
+    if (Arg->isValueDependent()) {
+      Converted = TemplateArgument(Arg);
+    } else {
+      Entity = cast<NamedDecl>(Entity->getCanonicalDecl());
+      Converted = TemplateArgument(Entity);
+    }
+    return false;
+  }
+
+  //     -- For a non-type template-parameter of type pointer to data
+  //        member, qualification conversions (4.4) are applied.
+  // C++0x allows std::nullptr_t values.
+  assert(ParamType->isMemberPointerType() && "Only pointers to members remain");
+
+  if (Context.hasSameUnqualifiedType(ParamType, ArgType)) {
+    // Types match exactly: nothing more to do here.
+  } else if (ArgType->isNullPtrType()) {
+    ImpCastExprToType(Arg, ParamType, CastExpr::CK_NullToMemberPointer);
+  } else if (IsQualificationConversion(ArgType, ParamType)) {
+    ImpCastExprToType(Arg, ParamType, CastExpr::CK_NoOp);
+  } else {
+    // We can't perform this conversion.
+    Diag(Arg->getSourceRange().getBegin(),
+         diag::err_template_arg_not_convertible)
+      << Arg->getType() << InstantiatedParamType << Arg->getSourceRange();
+    Diag(Param->getLocation(), diag::note_template_param_here);
+    return true;
+  }
+
+  return CheckTemplateArgumentPointerToMember(Arg, Converted);
+}
+
+/// \brief Check a template argument against its corresponding
+/// template template parameter.
+///
+/// This routine implements the semantics of C++ [temp.arg.template].
+/// It returns true if an error occurred, and false otherwise.
+bool Sema::CheckTemplateArgument(TemplateTemplateParmDecl *Param,
+                                 const TemplateArgumentLoc &Arg) {
+  TemplateName Name = Arg.getArgument().getAsTemplate();
+  TemplateDecl *Template = Name.getAsTemplateDecl();
+  if (!Template) {
+    // Any dependent template name is fine.
+    assert(Name.isDependent() && "Non-dependent template isn't a declaration?");
+    return false;
+  }
+
+  // C++ [temp.arg.template]p1:
+  //   A template-argument for a template template-parameter shall be
+  //   the name of a class template, expressed as id-expression. Only
+  //   primary class templates are considered when matching the
+  //   template template argument with the corresponding parameter;
+  //   partial specializations are not considered even if their
+  //   parameter lists match that of the template template parameter.
+  //
+  // Note that we also allow template template parameters here, which
+  // will happen when we are dealing with, e.g., class template
+  // partial specializations.
+  if (!isa<ClassTemplateDecl>(Template) &&
+      !isa<TemplateTemplateParmDecl>(Template)) {
+    assert(isa<FunctionTemplateDecl>(Template) &&
+           "Only function templates are possible here");
+    Diag(Arg.getLocation(), diag::err_template_arg_not_class_template);
+    Diag(Template->getLocation(), diag::note_template_arg_refers_here_func)
+      << Template;
+  }
+
+  return !TemplateParameterListsAreEqual(Template->getTemplateParameters(),
+                                         Param->getTemplateParameters(),
+                                         true, 
+                                         TPL_TemplateTemplateArgumentMatch,
+                                         Arg.getLocation());
+}
+
+/// \brief Determine whether the given template parameter lists are
+/// equivalent.
+///
+/// \param New  The new template parameter list, typically written in the
+/// source code as part of a new template declaration.
+///
+/// \param Old  The old template parameter list, typically found via
+/// name lookup of the template declared with this template parameter
+/// list.
+///
+/// \param Complain  If true, this routine will produce a diagnostic if
+/// the template parameter lists are not equivalent.
+///
+/// \param Kind describes how we are to match the template parameter lists.
+///
+/// \param TemplateArgLoc If this source location is valid, then we
+/// are actually checking the template parameter list of a template
+/// argument (New) against the template parameter list of its
+/// corresponding template template parameter (Old). We produce
+/// slightly different diagnostics in this scenario.
+///
+/// \returns True if the template parameter lists are equal, false
+/// otherwise.
+bool
+Sema::TemplateParameterListsAreEqual(TemplateParameterList *New,
+                                     TemplateParameterList *Old,
+                                     bool Complain,
+                                     TemplateParameterListEqualKind Kind,
+                                     SourceLocation TemplateArgLoc) {
+  if (Old->size() != New->size()) {
+    if (Complain) {
+      unsigned NextDiag = diag::err_template_param_list_different_arity;
+      if (TemplateArgLoc.isValid()) {
+        Diag(TemplateArgLoc, diag::err_template_arg_template_params_mismatch);
+        NextDiag = diag::note_template_param_list_different_arity;
+      }
+      Diag(New->getTemplateLoc(), NextDiag)
+          << (New->size() > Old->size())
+          << (Kind != TPL_TemplateMatch)
+          << SourceRange(New->getTemplateLoc(), New->getRAngleLoc());
+      Diag(Old->getTemplateLoc(), diag::note_template_prev_declaration)
+        << (Kind != TPL_TemplateMatch)
+        << SourceRange(Old->getTemplateLoc(), Old->getRAngleLoc());
+    }
+
+    return false;
+  }
+
+  for (TemplateParameterList::iterator OldParm = Old->begin(),
+         OldParmEnd = Old->end(), NewParm = New->begin();
+       OldParm != OldParmEnd; ++OldParm, ++NewParm) {
+    if ((*OldParm)->getKind() != (*NewParm)->getKind()) {
+      if (Complain) {
+        unsigned NextDiag = diag::err_template_param_different_kind;
+        if (TemplateArgLoc.isValid()) {
+          Diag(TemplateArgLoc, diag::err_template_arg_template_params_mismatch);
+          NextDiag = diag::note_template_param_different_kind;
+        }
+        Diag((*NewParm)->getLocation(), NextDiag)
+          << (Kind != TPL_TemplateMatch);
+        Diag((*OldParm)->getLocation(), diag::note_template_prev_declaration)
+          << (Kind != TPL_TemplateMatch);
+      }
+      return false;
+    }
+
+    if (isa<TemplateTypeParmDecl>(*OldParm)) {
+      // Okay; all template type parameters are equivalent (since we
+      // know we're at the same index).
+    } else if (NonTypeTemplateParmDecl *OldNTTP
+                 = dyn_cast<NonTypeTemplateParmDecl>(*OldParm)) {
+      // The types of non-type template parameters must agree.
+      NonTypeTemplateParmDecl *NewNTTP
+        = cast<NonTypeTemplateParmDecl>(*NewParm);
+      
+      // If we are matching a template template argument to a template
+      // template parameter and one of the non-type template parameter types
+      // is dependent, then we must wait until template instantiation time
+      // to actually compare the arguments.
+      if (Kind == TPL_TemplateTemplateArgumentMatch &&
+          (OldNTTP->getType()->isDependentType() ||
+           NewNTTP->getType()->isDependentType()))
+        continue;
+      
+      if (Context.getCanonicalType(OldNTTP->getType()) !=
+            Context.getCanonicalType(NewNTTP->getType())) {
+        if (Complain) {
+          unsigned NextDiag = diag::err_template_nontype_parm_different_type;
+          if (TemplateArgLoc.isValid()) {
+            Diag(TemplateArgLoc,
+                 diag::err_template_arg_template_params_mismatch);
+            NextDiag = diag::note_template_nontype_parm_different_type;
+          }
+          Diag(NewNTTP->getLocation(), NextDiag)
+            << NewNTTP->getType()
+            << (Kind != TPL_TemplateMatch);
+          Diag(OldNTTP->getLocation(),
+               diag::note_template_nontype_parm_prev_declaration)
+            << OldNTTP->getType();
+        }
+        return false;
+      }
+    } else {
+      // The template parameter lists of template template
+      // parameters must agree.
+      assert(isa<TemplateTemplateParmDecl>(*OldParm) &&
+             "Only template template parameters handled here");
+      TemplateTemplateParmDecl *OldTTP
+        = cast<TemplateTemplateParmDecl>(*OldParm);
+      TemplateTemplateParmDecl *NewTTP
+        = cast<TemplateTemplateParmDecl>(*NewParm);
+      if (!TemplateParameterListsAreEqual(NewTTP->getTemplateParameters(),
+                                          OldTTP->getTemplateParameters(),
+                                          Complain,
+              (Kind == TPL_TemplateMatch? TPL_TemplateTemplateParmMatch : Kind),
+                                          TemplateArgLoc))
+        return false;
+    }
+  }
+
+  return true;
+}
+
+/// \brief Check whether a template can be declared within this scope.
+///
+/// If the template declaration is valid in this scope, returns
+/// false. Otherwise, issues a diagnostic and returns true.
+bool
+Sema::CheckTemplateDeclScope(Scope *S, TemplateParameterList *TemplateParams) {
+  // Find the nearest enclosing declaration scope.
+  while ((S->getFlags() & Scope::DeclScope) == 0 ||
+         (S->getFlags() & Scope::TemplateParamScope) != 0)
+    S = S->getParent();
+
+  // C++ [temp]p2:
+  //   A template-declaration can appear only as a namespace scope or
+  //   class scope declaration.
+  DeclContext *Ctx = static_cast<DeclContext *>(S->getEntity());
+  if (Ctx && isa<LinkageSpecDecl>(Ctx) &&
+      cast<LinkageSpecDecl>(Ctx)->getLanguage() != LinkageSpecDecl::lang_cxx)
+    return Diag(TemplateParams->getTemplateLoc(), diag::err_template_linkage)
+             << TemplateParams->getSourceRange();
+
+  while (Ctx && isa<LinkageSpecDecl>(Ctx))
+    Ctx = Ctx->getParent();
+
+  if (Ctx && (Ctx->isFileContext() || Ctx->isRecord()))
+    return false;
+
+  return Diag(TemplateParams->getTemplateLoc(),
+              diag::err_template_outside_namespace_or_class_scope)
+    << TemplateParams->getSourceRange();
+}
+
+/// \brief Determine what kind of template specialization the given declaration
+/// is.
+static TemplateSpecializationKind getTemplateSpecializationKind(NamedDecl *D) {
+  if (!D)
+    return TSK_Undeclared;
+  
+  if (CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(D))
+    return Record->getTemplateSpecializationKind();
+  if (FunctionDecl *Function = dyn_cast<FunctionDecl>(D))
+    return Function->getTemplateSpecializationKind();
+  if (VarDecl *Var = dyn_cast<VarDecl>(D))
+    return Var->getTemplateSpecializationKind();
+  
+  return TSK_Undeclared;
+}
+
+/// \brief Check whether a specialization is well-formed in the current 
+/// context.
+///
+/// This routine determines whether a template specialization can be declared
+/// in the current context (C++ [temp.expl.spec]p2).
+///
+/// \param S the semantic analysis object for which this check is being
+/// performed.
+///
+/// \param Specialized the entity being specialized or instantiated, which
+/// may be a kind of template (class template, function template, etc.) or
+/// a member of a class template (member function, static data member, 
+/// member class).
+///
+/// \param PrevDecl the previous declaration of this entity, if any.
+///
+/// \param Loc the location of the explicit specialization or instantiation of
+/// this entity.
+///
+/// \param IsPartialSpecialization whether this is a partial specialization of
+/// a class template.
+///
+/// \returns true if there was an error that we cannot recover from, false
+/// otherwise.
+static bool CheckTemplateSpecializationScope(Sema &S,
+                                             NamedDecl *Specialized,
+                                             NamedDecl *PrevDecl,
+                                             SourceLocation Loc,
+                                             bool IsPartialSpecialization) {
+  // Keep these "kind" numbers in sync with the %select statements in the
+  // various diagnostics emitted by this routine.
+  int EntityKind = 0;
+  bool isTemplateSpecialization = false;
+  if (isa<ClassTemplateDecl>(Specialized)) {
+    EntityKind = IsPartialSpecialization? 1 : 0;
+    isTemplateSpecialization = true;
+  } else if (isa<FunctionTemplateDecl>(Specialized)) {
+    EntityKind = 2;
+    isTemplateSpecialization = true;
+  } else if (isa<CXXMethodDecl>(Specialized))
+    EntityKind = 3;
+  else if (isa<VarDecl>(Specialized))
+    EntityKind = 4;
+  else if (isa<RecordDecl>(Specialized))
+    EntityKind = 5;
+  else {
+    S.Diag(Loc, diag::err_template_spec_unknown_kind);
+    S.Diag(Specialized->getLocation(), diag::note_specialized_entity);
+    return true;
+  }
+
+  // C++ [temp.expl.spec]p2:
+  //   An explicit specialization shall be declared in the namespace
+  //   of which the template is a member, or, for member templates, in
+  //   the namespace of which the enclosing class or enclosing class
+  //   template is a member. An explicit specialization of a member
+  //   function, member class or static data member of a class
+  //   template shall be declared in the namespace of which the class
+  //   template is a member. Such a declaration may also be a
+  //   definition. If the declaration is not a definition, the
+  //   specialization may be defined later in the name- space in which
+  //   the explicit specialization was declared, or in a namespace
+  //   that encloses the one in which the explicit specialization was
+  //   declared.
+  if (S.CurContext->getLookupContext()->isFunctionOrMethod()) {
+    S.Diag(Loc, diag::err_template_spec_decl_function_scope)
+      << Specialized;
+    return true;
+  }
+
+  if (S.CurContext->isRecord() && !IsPartialSpecialization) {
+    S.Diag(Loc, diag::err_template_spec_decl_class_scope)
+      << Specialized;
+    return true;
+  }
+  
+  // C++ [temp.class.spec]p6:
+  //   A class template partial specialization may be declared or redeclared
+  //   in any namespace scope in which its definition may be defined (14.5.1 
+  //   and 14.5.2).  
+  bool ComplainedAboutScope = false;
+  DeclContext *SpecializedContext 
+    = Specialized->getDeclContext()->getEnclosingNamespaceContext();
+  DeclContext *DC = S.CurContext->getEnclosingNamespaceContext();
+  if ((!PrevDecl || 
+       getTemplateSpecializationKind(PrevDecl) == TSK_Undeclared ||
+       getTemplateSpecializationKind(PrevDecl) == TSK_ImplicitInstantiation)){
+    // There is no prior declaration of this entity, so this
+    // specialization must be in the same context as the template
+    // itself.
+    if (!DC->Equals(SpecializedContext)) {
+      if (isa<TranslationUnitDecl>(SpecializedContext))
+        S.Diag(Loc, diag::err_template_spec_decl_out_of_scope_global)
+        << EntityKind << Specialized;
+      else if (isa<NamespaceDecl>(SpecializedContext))
+        S.Diag(Loc, diag::err_template_spec_decl_out_of_scope)
+        << EntityKind << Specialized
+        << cast<NamedDecl>(SpecializedContext);
+      
+      S.Diag(Specialized->getLocation(), diag::note_specialized_entity);
+      ComplainedAboutScope = true;
+    }
+  }
+  
+  // Make sure that this redeclaration (or definition) occurs in an enclosing 
+  // namespace.
+  // Note that HandleDeclarator() performs this check for explicit 
+  // specializations of function templates, static data members, and member
+  // functions, so we skip the check here for those kinds of entities.
+  // FIXME: HandleDeclarator's diagnostics aren't quite as good, though.
+  // Should we refactor that check, so that it occurs later?
+  if (!ComplainedAboutScope && !DC->Encloses(SpecializedContext) &&
+      !(isa<FunctionTemplateDecl>(Specialized) || isa<VarDecl>(Specialized) ||
+        isa<FunctionDecl>(Specialized))) {
+    if (isa<TranslationUnitDecl>(SpecializedContext))
+      S.Diag(Loc, diag::err_template_spec_redecl_global_scope)
+        << EntityKind << Specialized;
+    else if (isa<NamespaceDecl>(SpecializedContext))
+      S.Diag(Loc, diag::err_template_spec_redecl_out_of_scope)
+        << EntityKind << Specialized
+        << cast<NamedDecl>(SpecializedContext);
+  
+    S.Diag(Specialized->getLocation(), diag::note_specialized_entity);
+  }
+  
+  // FIXME: check for specialization-after-instantiation errors and such.
+  
+  return false;
+}
+                                             
+/// \brief Check the non-type template arguments of a class template
+/// partial specialization according to C++ [temp.class.spec]p9.
+///
+/// \param TemplateParams the template parameters of the primary class
+/// template.
+///
+/// \param TemplateArg the template arguments of the class template
+/// partial specialization.
+///
+/// \param MirrorsPrimaryTemplate will be set true if the class
+/// template partial specialization arguments are identical to the
+/// implicit template arguments of the primary template. This is not
+/// necessarily an error (C++0x), and it is left to the caller to diagnose
+/// this condition when it is an error.
+///
+/// \returns true if there was an error, false otherwise.
+bool Sema::CheckClassTemplatePartialSpecializationArgs(
+                                        TemplateParameterList *TemplateParams,
+                             const TemplateArgumentListBuilder &TemplateArgs,
+                                        bool &MirrorsPrimaryTemplate) {
+  // FIXME: the interface to this function will have to change to
+  // accommodate variadic templates.
+  MirrorsPrimaryTemplate = true;
+
+  const TemplateArgument *ArgList = TemplateArgs.getFlatArguments();
+
+  for (unsigned I = 0, N = TemplateParams->size(); I != N; ++I) {
+    // Determine whether the template argument list of the partial
+    // specialization is identical to the implicit argument list of
+    // the primary template. The caller may need to diagnostic this as
+    // an error per C++ [temp.class.spec]p9b3.
+    if (MirrorsPrimaryTemplate) {
+      if (TemplateTypeParmDecl *TTP
+            = dyn_cast<TemplateTypeParmDecl>(TemplateParams->getParam(I))) {
+        if (Context.getCanonicalType(Context.getTypeDeclType(TTP)) !=
+              Context.getCanonicalType(ArgList[I].getAsType()))
+          MirrorsPrimaryTemplate = false;
+      } else if (TemplateTemplateParmDecl *TTP
+                   = dyn_cast<TemplateTemplateParmDecl>(
+                                                 TemplateParams->getParam(I))) {
+        TemplateName Name = ArgList[I].getAsTemplate();
+        TemplateTemplateParmDecl *ArgDecl
+          = dyn_cast_or_null<TemplateTemplateParmDecl>(Name.getAsTemplateDecl());
+        if (!ArgDecl ||
+            ArgDecl->getIndex() != TTP->getIndex() ||
+            ArgDecl->getDepth() != TTP->getDepth())
+          MirrorsPrimaryTemplate = false;
+      }
+    }
+
+    NonTypeTemplateParmDecl *Param
+      = dyn_cast<NonTypeTemplateParmDecl>(TemplateParams->getParam(I));
+    if (!Param) {
+      continue;
+    }
+
+    Expr *ArgExpr = ArgList[I].getAsExpr();
+    if (!ArgExpr) {
+      MirrorsPrimaryTemplate = false;
+      continue;
+    }
+
+    // C++ [temp.class.spec]p8:
+    //   A non-type argument is non-specialized if it is the name of a
+    //   non-type parameter. All other non-type arguments are
+    //   specialized.
+    //
+    // Below, we check the two conditions that only apply to
+    // specialized non-type arguments, so skip any non-specialized
+    // arguments.
+    if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(ArgExpr))
+      if (NonTypeTemplateParmDecl *NTTP
+            = dyn_cast<NonTypeTemplateParmDecl>(DRE->getDecl())) {
+        if (MirrorsPrimaryTemplate &&
+            (Param->getIndex() != NTTP->getIndex() ||
+             Param->getDepth() != NTTP->getDepth()))
+          MirrorsPrimaryTemplate = false;
+
+        continue;
+      }
+
+    // C++ [temp.class.spec]p9:
+    //   Within the argument list of a class template partial
+    //   specialization, the following restrictions apply:
+    //     -- A partially specialized non-type argument expression
+    //        shall not involve a template parameter of the partial
+    //        specialization except when the argument expression is a
+    //        simple identifier.
+    if (ArgExpr->isTypeDependent() || ArgExpr->isValueDependent()) {
+      Diag(ArgExpr->getLocStart(),
+           diag::err_dependent_non_type_arg_in_partial_spec)
+        << ArgExpr->getSourceRange();
+      return true;
+    }
+
+    //     -- The type of a template parameter corresponding to a
+    //        specialized non-type argument shall not be dependent on a
+    //        parameter of the specialization.
+    if (Param->getType()->isDependentType()) {
+      Diag(ArgExpr->getLocStart(),
+           diag::err_dependent_typed_non_type_arg_in_partial_spec)
+        << Param->getType()
+        << ArgExpr->getSourceRange();
+      Diag(Param->getLocation(), diag::note_template_param_here);
+      return true;
+    }
+
+    MirrorsPrimaryTemplate = false;
+  }
+
+  return false;
+}
+
+Sema::DeclResult
+Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec,
+                                       TagUseKind TUK,
+                                       SourceLocation KWLoc,
+                                       const CXXScopeSpec &SS,
+                                       TemplateTy TemplateD,
+                                       SourceLocation TemplateNameLoc,
+                                       SourceLocation LAngleLoc,
+                                       ASTTemplateArgsPtr TemplateArgsIn,
+                                       SourceLocation RAngleLoc,
+                                       AttributeList *Attr,
+                               MultiTemplateParamsArg TemplateParameterLists) {
+  assert(TUK != TUK_Reference && "References are not specializations");
+
+  // Find the class template we're specializing
+  TemplateName Name = TemplateD.getAsVal<TemplateName>();
+  ClassTemplateDecl *ClassTemplate
+    = dyn_cast_or_null<ClassTemplateDecl>(Name.getAsTemplateDecl());
+
+  if (!ClassTemplate) {
+    Diag(TemplateNameLoc, diag::err_not_class_template_specialization)
+      << (Name.getAsTemplateDecl() && 
+          isa<TemplateTemplateParmDecl>(Name.getAsTemplateDecl()));
+    return true;
+  }
+
+  bool isExplicitSpecialization = false;
+  bool isPartialSpecialization = false;
+
+  // Check the validity of the template headers that introduce this
+  // template.
+  // FIXME: We probably shouldn't complain about these headers for
+  // friend declarations.
+  TemplateParameterList *TemplateParams
+    = MatchTemplateParametersToScopeSpecifier(TemplateNameLoc, SS,
+                        (TemplateParameterList**)TemplateParameterLists.get(),
+                                              TemplateParameterLists.size(),
+                                              isExplicitSpecialization);
+  if (TemplateParams && TemplateParams->size() > 0) {
+    isPartialSpecialization = true;
+
+    // C++ [temp.class.spec]p10:
+    //   The template parameter list of a specialization shall not
+    //   contain default template argument values.
+    for (unsigned I = 0, N = TemplateParams->size(); I != N; ++I) {
+      Decl *Param = TemplateParams->getParam(I);
+      if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(Param)) {
+        if (TTP->hasDefaultArgument()) {
+          Diag(TTP->getDefaultArgumentLoc(),
+               diag::err_default_arg_in_partial_spec);
+          TTP->removeDefaultArgument();
+        }
+      } else if (NonTypeTemplateParmDecl *NTTP
+                   = dyn_cast<NonTypeTemplateParmDecl>(Param)) {
+        if (Expr *DefArg = NTTP->getDefaultArgument()) {
+          Diag(NTTP->getDefaultArgumentLoc(),
+               diag::err_default_arg_in_partial_spec)
+            << DefArg->getSourceRange();
+          NTTP->setDefaultArgument(0);
+          DefArg->Destroy(Context);
+        }
+      } else {
+        TemplateTemplateParmDecl *TTP = cast<TemplateTemplateParmDecl>(Param);
+        if (TTP->hasDefaultArgument()) {
+          Diag(TTP->getDefaultArgument().getLocation(),
+               diag::err_default_arg_in_partial_spec)
+            << TTP->getDefaultArgument().getSourceRange();
+          TTP->setDefaultArgument(TemplateArgumentLoc());
+        }
+      }
+    }
+  } else if (TemplateParams) {
+    if (TUK == TUK_Friend)
+      Diag(KWLoc, diag::err_template_spec_friend)
+        << CodeModificationHint::CreateRemoval(
+                                SourceRange(TemplateParams->getTemplateLoc(),
+                                            TemplateParams->getRAngleLoc()))
+        << SourceRange(LAngleLoc, RAngleLoc);
+    else
+      isExplicitSpecialization = true;
+  } else if (TUK != TUK_Friend) {
+    Diag(KWLoc, diag::err_template_spec_needs_header)
+      << CodeModificationHint::CreateInsertion(KWLoc, "template<> ");
+    isExplicitSpecialization = true;
+  }
+
+  // Check that the specialization uses the same tag kind as the
+  // original template.
+  TagDecl::TagKind Kind;
+  switch (TagSpec) {
+  default: assert(0 && "Unknown tag type!");
+  case DeclSpec::TST_struct: Kind = TagDecl::TK_struct; break;
+  case DeclSpec::TST_union:  Kind = TagDecl::TK_union; break;
+  case DeclSpec::TST_class:  Kind = TagDecl::TK_class; break;
+  }
+  if (!isAcceptableTagRedeclaration(ClassTemplate->getTemplatedDecl(),
+                                    Kind, KWLoc,
+                                    *ClassTemplate->getIdentifier())) {
+    Diag(KWLoc, diag::err_use_with_wrong_tag)
+      << ClassTemplate
+      << CodeModificationHint::CreateReplacement(KWLoc,
+                            ClassTemplate->getTemplatedDecl()->getKindName());
+    Diag(ClassTemplate->getTemplatedDecl()->getLocation(),
+         diag::note_previous_use);
+    Kind = ClassTemplate->getTemplatedDecl()->getTagKind();
+  }
+
+  // Translate the parser's template argument list in our AST format.
+  TemplateArgumentListInfo TemplateArgs;
+  TemplateArgs.setLAngleLoc(LAngleLoc);
+  TemplateArgs.setRAngleLoc(RAngleLoc);
+  translateTemplateArguments(TemplateArgsIn, TemplateArgs);
+
+  // Check that the template argument list is well-formed for this
+  // template.
+  TemplateArgumentListBuilder Converted(ClassTemplate->getTemplateParameters(),
+                                        TemplateArgs.size());
+  if (CheckTemplateArgumentList(ClassTemplate, TemplateNameLoc,
+                                TemplateArgs, false, Converted))
+    return true;
+
+  assert((Converted.structuredSize() ==
+            ClassTemplate->getTemplateParameters()->size()) &&
+         "Converted template argument list is too short!");
+
+  // Find the class template (partial) specialization declaration that
+  // corresponds to these arguments.
+  llvm::FoldingSetNodeID ID;
+  if (isPartialSpecialization) {
+    bool MirrorsPrimaryTemplate;
+    if (CheckClassTemplatePartialSpecializationArgs(
+                                         ClassTemplate->getTemplateParameters(),
+                                         Converted, MirrorsPrimaryTemplate))
+      return true;
+
+    if (MirrorsPrimaryTemplate) {
+      // C++ [temp.class.spec]p9b3:
+      //
+      //   -- The argument list of the specialization shall not be identical
+      //      to the implicit argument list of the primary template.
+      Diag(TemplateNameLoc, diag::err_partial_spec_args_match_primary_template)
+        << (TUK == TUK_Definition)
+        << CodeModificationHint::CreateRemoval(SourceRange(LAngleLoc,
+                                                           RAngleLoc));
+      return CheckClassTemplate(S, TagSpec, TUK, KWLoc, SS,
+                                ClassTemplate->getIdentifier(),
+                                TemplateNameLoc,
+                                Attr,
+                                TemplateParams,
+                                AS_none);
+    }
+
+    // FIXME: Diagnose friend partial specializations
+
+    if (!Name.isDependent() && 
+        !TemplateSpecializationType::anyDependentTemplateArguments(
+                                             TemplateArgs.getArgumentArray(), 
+                                                         TemplateArgs.size())) {
+      Diag(TemplateNameLoc, diag::err_partial_spec_fully_specialized)
+        << ClassTemplate->getDeclName();
+      isPartialSpecialization = false;
+    } else {
+      // FIXME: Template parameter list matters, too
+      ClassTemplatePartialSpecializationDecl::Profile(ID,
+                                                  Converted.getFlatArguments(),
+                                                      Converted.flatSize(),
+                                                      Context);
+    }
+  }
+  
+  if (!isPartialSpecialization)
+    ClassTemplateSpecializationDecl::Profile(ID,
+                                             Converted.getFlatArguments(),
+                                             Converted.flatSize(),
+                                             Context);
+  void *InsertPos = 0;
+  ClassTemplateSpecializationDecl *PrevDecl = 0;
+
+  if (isPartialSpecialization)
+    PrevDecl
+      = ClassTemplate->getPartialSpecializations().FindNodeOrInsertPos(ID,
+                                                                    InsertPos);
+  else
+    PrevDecl
+      = ClassTemplate->getSpecializations().FindNodeOrInsertPos(ID, InsertPos);
+
+  ClassTemplateSpecializationDecl *Specialization = 0;
+
+  // Check whether we can declare a class template specialization in
+  // the current scope.
+  if (TUK != TUK_Friend &&
+      CheckTemplateSpecializationScope(*this, ClassTemplate, PrevDecl, 
+                                       TemplateNameLoc, 
+                                       isPartialSpecialization))
+    return true;
+  
+  // The canonical type
+  QualType CanonType;
+  if (PrevDecl && 
+      (PrevDecl->getSpecializationKind() == TSK_Undeclared ||
+               TUK == TUK_Friend)) {
+    // Since the only prior class template specialization with these
+    // arguments was referenced but not declared, or we're only
+    // referencing this specialization as a friend, reuse that
+    // declaration node as our own, updating its source location to
+    // reflect our new declaration.
+    Specialization = PrevDecl;
+    Specialization->setLocation(TemplateNameLoc);
+    PrevDecl = 0;
+    CanonType = Context.getTypeDeclType(Specialization);
+  } else if (isPartialSpecialization) {
+    // Build the canonical type that describes the converted template
+    // arguments of the class template partial specialization.
+    TemplateName CanonTemplate = Context.getCanonicalTemplateName(Name);
+    CanonType = Context.getTemplateSpecializationType(CanonTemplate,
+                                                  Converted.getFlatArguments(),
+                                                  Converted.flatSize());
+
+    // Create a new class template partial specialization declaration node.
+    ClassTemplatePartialSpecializationDecl *PrevPartial
+      = cast_or_null<ClassTemplatePartialSpecializationDecl>(PrevDecl);
+    ClassTemplatePartialSpecializationDecl *Partial
+      = ClassTemplatePartialSpecializationDecl::Create(Context,
+                                             ClassTemplate->getDeclContext(),
+                                                       TemplateNameLoc,
+                                                       TemplateParams,
+                                                       ClassTemplate,
+                                                       Converted,
+                                                       TemplateArgs,
+                                                       PrevPartial);
+
+    if (PrevPartial) {
+      ClassTemplate->getPartialSpecializations().RemoveNode(PrevPartial);
+      ClassTemplate->getPartialSpecializations().GetOrInsertNode(Partial);
+    } else {
+      ClassTemplate->getPartialSpecializations().InsertNode(Partial, InsertPos);
+    }
+    Specialization = Partial;
+
+    // If we are providing an explicit specialization of a member class 
+    // template specialization, make a note of that.
+    if (PrevPartial && PrevPartial->getInstantiatedFromMember())
+      PrevPartial->setMemberSpecialization();
+    
+    // Check that all of the template parameters of the class template
+    // partial specialization are deducible from the template
+    // arguments. If not, this class template partial specialization
+    // will never be used.
+    llvm::SmallVector<bool, 8> DeducibleParams;
+    DeducibleParams.resize(TemplateParams->size());
+    MarkUsedTemplateParameters(Partial->getTemplateArgs(), true, 
+                               TemplateParams->getDepth(),
+                               DeducibleParams);
+    unsigned NumNonDeducible = 0;
+    for (unsigned I = 0, N = DeducibleParams.size(); I != N; ++I)
+      if (!DeducibleParams[I])
+        ++NumNonDeducible;
+
+    if (NumNonDeducible) {
+      Diag(TemplateNameLoc, diag::warn_partial_specs_not_deducible)
+        << (NumNonDeducible > 1)
+        << SourceRange(TemplateNameLoc, RAngleLoc);
+      for (unsigned I = 0, N = DeducibleParams.size(); I != N; ++I) {
+        if (!DeducibleParams[I]) {
+          NamedDecl *Param = cast<NamedDecl>(TemplateParams->getParam(I));
+          if (Param->getDeclName())
+            Diag(Param->getLocation(),
+                 diag::note_partial_spec_unused_parameter)
+              << Param->getDeclName();
+          else
+            Diag(Param->getLocation(),
+                 diag::note_partial_spec_unused_parameter)
+              << std::string("<anonymous>");
+        }
+      }
+    }
+  } else {
+    // Create a new class template specialization declaration node for
+    // this explicit specialization or friend declaration.
+    Specialization
+      = ClassTemplateSpecializationDecl::Create(Context,
+                                             ClassTemplate->getDeclContext(),
+                                                TemplateNameLoc,
+                                                ClassTemplate,
+                                                Converted,
+                                                PrevDecl);
+
+    if (PrevDecl) {
+      ClassTemplate->getSpecializations().RemoveNode(PrevDecl);
+      ClassTemplate->getSpecializations().GetOrInsertNode(Specialization);
+    } else {
+      ClassTemplate->getSpecializations().InsertNode(Specialization,
+                                                     InsertPos);
+    }
+
+    CanonType = Context.getTypeDeclType(Specialization);
+  }
+
+  // C++ [temp.expl.spec]p6:
+  //   If a template, a member template or the member of a class template is
+  //   explicitly specialized then that specialization shall be declared 
+  //   before the first use of that specialization that would cause an implicit
+  //   instantiation to take place, in every translation unit in which such a 
+  //   use occurs; no diagnostic is required.
+  if (PrevDecl && PrevDecl->getPointOfInstantiation().isValid()) {
+    SourceRange Range(TemplateNameLoc, RAngleLoc);
+    Diag(TemplateNameLoc, diag::err_specialization_after_instantiation)
+      << Context.getTypeDeclType(Specialization) << Range;
+
+    Diag(PrevDecl->getPointOfInstantiation(), 
+         diag::note_instantiation_required_here)
+      << (PrevDecl->getTemplateSpecializationKind() 
+                                                != TSK_ImplicitInstantiation);
+    return true;
+  }
+  
+  // If this is not a friend, note that this is an explicit specialization.
+  if (TUK != TUK_Friend)
+    Specialization->setSpecializationKind(TSK_ExplicitSpecialization);
+
+  // Check that this isn't a redefinition of this specialization.
+  if (TUK == TUK_Definition) {
+    if (RecordDecl *Def = Specialization->getDefinition(Context)) {
+      SourceRange Range(TemplateNameLoc, RAngleLoc);
+      Diag(TemplateNameLoc, diag::err_redefinition)
+        << Context.getTypeDeclType(Specialization) << Range;
+      Diag(Def->getLocation(), diag::note_previous_definition);
+      Specialization->setInvalidDecl();
+      return true;
+    }
+  }
+
+  // Build the fully-sugared type for this class template
+  // specialization as the user wrote in the specialization
+  // itself. This means that we'll pretty-print the type retrieved
+  // from the specialization's declaration the way that the user
+  // actually wrote the specialization, rather than formatting the
+  // name based on the "canonical" representation used to store the
+  // template arguments in the specialization.
+  QualType WrittenTy
+    = Context.getTemplateSpecializationType(Name, TemplateArgs, CanonType);
+  if (TUK != TUK_Friend)
+    Specialization->setTypeAsWritten(WrittenTy);
+  TemplateArgsIn.release();
+
+  // C++ [temp.expl.spec]p9:
+  //   A template explicit specialization is in the scope of the
+  //   namespace in which the template was defined.
+  //
+  // We actually implement this paragraph where we set the semantic
+  // context (in the creation of the ClassTemplateSpecializationDecl),
+  // but we also maintain the lexical context where the actual
+  // definition occurs.
+  Specialization->setLexicalDeclContext(CurContext);
+
+  // We may be starting the definition of this specialization.
+  if (TUK == TUK_Definition)
+    Specialization->startDefinition();
+
+  if (TUK == TUK_Friend) {
+    FriendDecl *Friend = FriendDecl::Create(Context, CurContext,
+                                            TemplateNameLoc,
+                                            WrittenTy.getTypePtr(),
+                                            /*FIXME:*/KWLoc);
+    Friend->setAccess(AS_public);
+    CurContext->addDecl(Friend);
+  } else {
+    // Add the specialization into its lexical context, so that it can
+    // be seen when iterating through the list of declarations in that
+    // context. However, specializations are not found by name lookup.
+    CurContext->addDecl(Specialization);
+  }
+  return DeclPtrTy::make(Specialization);
+}
+
+Sema::DeclPtrTy
+Sema::ActOnTemplateDeclarator(Scope *S,
+                              MultiTemplateParamsArg TemplateParameterLists,
+                              Declarator &D) {
+  return HandleDeclarator(S, D, move(TemplateParameterLists), false);
+}
+
+Sema::DeclPtrTy
+Sema::ActOnStartOfFunctionTemplateDef(Scope *FnBodyScope,
+                               MultiTemplateParamsArg TemplateParameterLists,
+                                      Declarator &D) {
+  assert(getCurFunctionDecl() == 0 && "Function parsing confused");
+  assert(D.getTypeObject(0).Kind == DeclaratorChunk::Function &&
+         "Not a function declarator!");
+  DeclaratorChunk::FunctionTypeInfo &FTI = D.getTypeObject(0).Fun;
+
+  if (FTI.hasPrototype) {
+    // FIXME: Diagnose arguments without names in C.
+  }
+
+  Scope *ParentScope = FnBodyScope->getParent();
+
+  DeclPtrTy DP = HandleDeclarator(ParentScope, D,
+                                  move(TemplateParameterLists),
+                                  /*IsFunctionDefinition=*/true);
+  if (FunctionTemplateDecl *FunctionTemplate
+        = dyn_cast_or_null<FunctionTemplateDecl>(DP.getAs<Decl>()))
+    return ActOnStartOfFunctionDef(FnBodyScope,
+                      DeclPtrTy::make(FunctionTemplate->getTemplatedDecl()));
+  if (FunctionDecl *Function = dyn_cast_or_null<FunctionDecl>(DP.getAs<Decl>()))
+    return ActOnStartOfFunctionDef(FnBodyScope, DeclPtrTy::make(Function));
+  return DeclPtrTy();
+}
+
+/// \brief Diagnose cases where we have an explicit template specialization 
+/// before/after an explicit template instantiation, producing diagnostics
+/// for those cases where they are required and determining whether the 
+/// new specialization/instantiation will have any effect.
+///
+/// \param NewLoc the location of the new explicit specialization or 
+/// instantiation.
+///
+/// \param NewTSK the kind of the new explicit specialization or instantiation.
+///
+/// \param PrevDecl the previous declaration of the entity.
+///
+/// \param PrevTSK the kind of the old explicit specialization or instantiatin.
+///
+/// \param PrevPointOfInstantiation if valid, indicates where the previus 
+/// declaration was instantiated (either implicitly or explicitly).
+///
+/// \param SuppressNew will be set to true to indicate that the new 
+/// specialization or instantiation has no effect and should be ignored.
+///
+/// \returns true if there was an error that should prevent the introduction of
+/// the new declaration into the AST, false otherwise.
+bool
+Sema::CheckSpecializationInstantiationRedecl(SourceLocation NewLoc,
+                                             TemplateSpecializationKind NewTSK,
+                                             NamedDecl *PrevDecl,
+                                             TemplateSpecializationKind PrevTSK,
+                                        SourceLocation PrevPointOfInstantiation,
+                                             bool &SuppressNew) {
+  SuppressNew = false;
+  
+  switch (NewTSK) {
+  case TSK_Undeclared:
+  case TSK_ImplicitInstantiation:
+    assert(false && "Don't check implicit instantiations here");
+    return false;
+    
+  case TSK_ExplicitSpecialization:
+    switch (PrevTSK) {
+    case TSK_Undeclared:
+    case TSK_ExplicitSpecialization:
+      // Okay, we're just specializing something that is either already 
+      // explicitly specialized or has merely been mentioned without any
+      // instantiation.
+      return false;
+
+    case TSK_ImplicitInstantiation:
+      if (PrevPointOfInstantiation.isInvalid()) {
+        // The declaration itself has not actually been instantiated, so it is
+        // still okay to specialize it.
+        return false;
+      }
+      // Fall through
+        
+    case TSK_ExplicitInstantiationDeclaration:
+    case TSK_ExplicitInstantiationDefinition:
+      assert((PrevTSK == TSK_ImplicitInstantiation || 
+              PrevPointOfInstantiation.isValid()) && 
+             "Explicit instantiation without point of instantiation?");
+        
+      // C++ [temp.expl.spec]p6:
+      //   If a template, a member template or the member of a class template 
+      //   is explicitly specialized then that specialization shall be declared
+      //   before the first use of that specialization that would cause an 
+      //   implicit instantiation to take place, in every translation unit in
+      //   which such a use occurs; no diagnostic is required.
+      Diag(NewLoc, diag::err_specialization_after_instantiation)
+        << PrevDecl;
+      Diag(PrevPointOfInstantiation, diag::note_instantiation_required_here)
+        << (PrevTSK != TSK_ImplicitInstantiation);
+      
+      return true;
+    }
+    break;
+      
+  case TSK_ExplicitInstantiationDeclaration:
+    switch (PrevTSK) {
+    case TSK_ExplicitInstantiationDeclaration:
+      // This explicit instantiation declaration is redundant (that's okay).
+      SuppressNew = true;
+      return false;
+        
+    case TSK_Undeclared:
+    case TSK_ImplicitInstantiation:
+      // We're explicitly instantiating something that may have already been
+      // implicitly instantiated; that's fine.
+      return false;
+        
+    case TSK_ExplicitSpecialization:
+      // C++0x [temp.explicit]p4:
+      //   For a given set of template parameters, if an explicit instantiation
+      //   of a template appears after a declaration of an explicit 
+      //   specialization for that template, the explicit instantiation has no
+      //   effect.
+      return false;
+        
+    case TSK_ExplicitInstantiationDefinition:
+      // C++0x [temp.explicit]p10:
+      //   If an entity is the subject of both an explicit instantiation 
+      //   declaration and an explicit instantiation definition in the same 
+      //   translation unit, the definition shall follow the declaration.
+      Diag(NewLoc, 
+           diag::err_explicit_instantiation_declaration_after_definition);
+      Diag(PrevPointOfInstantiation, 
+           diag::note_explicit_instantiation_definition_here);
+      assert(PrevPointOfInstantiation.isValid() &&
+             "Explicit instantiation without point of instantiation?");
+      SuppressNew = true;
+      return false;
+    }
+    break;
+      
+  case TSK_ExplicitInstantiationDefinition:
+    switch (PrevTSK) {
+    case TSK_Undeclared:
+    case TSK_ImplicitInstantiation:
+      // We're explicitly instantiating something that may have already been
+      // implicitly instantiated; that's fine.
+      return false;
+        
+    case TSK_ExplicitSpecialization:
+      // C++ DR 259, C++0x [temp.explicit]p4:
+      //   For a given set of template parameters, if an explicit
+      //   instantiation of a template appears after a declaration of
+      //   an explicit specialization for that template, the explicit
+      //   instantiation has no effect.
+      //
+      // In C++98/03 mode, we only give an extension warning here, because it 
+      // is not not harmful to try to explicitly instantiate something that
+      // has been explicitly specialized.
+      if (!getLangOptions().CPlusPlus0x) {
+        Diag(NewLoc, diag::ext_explicit_instantiation_after_specialization)
+          << PrevDecl;
+        Diag(PrevDecl->getLocation(),
+             diag::note_previous_template_specialization);
+      }
+      SuppressNew = true;
+      return false;
+        
+    case TSK_ExplicitInstantiationDeclaration:
+      // We're explicity instantiating a definition for something for which we
+      // were previously asked to suppress instantiations. That's fine. 
+      return false;
+        
+    case TSK_ExplicitInstantiationDefinition:
+      // C++0x [temp.spec]p5:
+      //   For a given template and a given set of template-arguments,
+      //     - an explicit instantiation definition shall appear at most once
+      //       in a program,
+      Diag(NewLoc, diag::err_explicit_instantiation_duplicate)
+        << PrevDecl;
+      Diag(PrevPointOfInstantiation, 
+           diag::note_previous_explicit_instantiation);
+      SuppressNew = true;
+      return false;        
+    }
+    break;
+  }
+  
+  assert(false && "Missing specialization/instantiation case?");
+         
+  return false;
+}
+
+/// \brief Perform semantic analysis for the given function template 
+/// specialization.
+///
+/// This routine performs all of the semantic analysis required for an 
+/// explicit function template specialization. On successful completion,
+/// the function declaration \p FD will become a function template
+/// specialization.
+///
+/// \param FD the function declaration, which will be updated to become a
+/// function template specialization.
+///
+/// \param HasExplicitTemplateArgs whether any template arguments were
+/// explicitly provided.
+///
+/// \param LAngleLoc the location of the left angle bracket ('<'), if
+/// template arguments were explicitly provided.
+///
+/// \param ExplicitTemplateArgs the explicitly-provided template arguments, 
+/// if any.
+///
+/// \param NumExplicitTemplateArgs the number of explicitly-provided template
+/// arguments. This number may be zero even when HasExplicitTemplateArgs is
+/// true as in, e.g., \c void sort<>(char*, char*);
+///
+/// \param RAngleLoc the location of the right angle bracket ('>'), if
+/// template arguments were explicitly provided.
+/// 
+/// \param PrevDecl the set of declarations that 
+bool 
+Sema::CheckFunctionTemplateSpecialization(FunctionDecl *FD,
+                        const TemplateArgumentListInfo *ExplicitTemplateArgs,
+                                          LookupResult &Previous) {
+  // The set of function template specializations that could match this
+  // explicit function template specialization.
+  UnresolvedSet<8> Candidates;
+  
+  DeclContext *FDLookupContext = FD->getDeclContext()->getLookupContext();
+  for (LookupResult::iterator I = Previous.begin(), E = Previous.end();
+         I != E; ++I) {
+    NamedDecl *Ovl = (*I)->getUnderlyingDecl();
+    if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(Ovl)) {
+      // Only consider templates found within the same semantic lookup scope as 
+      // FD.
+      if (!FDLookupContext->Equals(Ovl->getDeclContext()->getLookupContext()))
+        continue;
+      
+      // C++ [temp.expl.spec]p11:
+      //   A trailing template-argument can be left unspecified in the 
+      //   template-id naming an explicit function template specialization 
+      //   provided it can be deduced from the function argument type.
+      // Perform template argument deduction to determine whether we may be
+      // specializing this template.
+      // FIXME: It is somewhat wasteful to build
+      TemplateDeductionInfo Info(Context, FD->getLocation());
+      FunctionDecl *Specialization = 0;
+      if (TemplateDeductionResult TDK
+            = DeduceTemplateArguments(FunTmpl, ExplicitTemplateArgs,
+                                      FD->getType(),
+                                      Specialization,
+                                      Info)) {
+        // FIXME: Template argument deduction failed; record why it failed, so
+        // that we can provide nifty diagnostics.
+        (void)TDK;
+        continue;
+      }
+      
+      // Record this candidate.
+      Candidates.addDecl(Specialization, I.getAccess());
+    }
+  }
+  
+  // Find the most specialized function template.
+  UnresolvedSetIterator Result
+    = getMostSpecialized(Candidates.begin(), Candidates.end(),
+                         TPOC_Other, FD->getLocation(),
+                  PartialDiagnostic(diag::err_function_template_spec_no_match) 
+                    << FD->getDeclName(),
+                  PartialDiagnostic(diag::err_function_template_spec_ambiguous)
+                    << FD->getDeclName() << (ExplicitTemplateArgs != 0),
+                  PartialDiagnostic(diag::note_function_template_spec_matched));
+  if (Result == Candidates.end())
+    return true;
+
+  // Ignore access information;  it doesn't figure into redeclaration checking.
+  FunctionDecl *Specialization = cast<FunctionDecl>(*Result);
+  
+  // FIXME: Check if the prior specialization has a point of instantiation.
+  // If so, we have run afoul of .
+  
+  // Check the scope of this explicit specialization.
+  if (CheckTemplateSpecializationScope(*this, 
+                                       Specialization->getPrimaryTemplate(),
+                                       Specialization, FD->getLocation(), 
+                                       false))
+    return true;
+
+  // C++ [temp.expl.spec]p6:
+  //   If a template, a member template or the member of a class template is
+  //   explicitly specialized then that specialization shall be declared 
+  //   before the first use of that specialization that would cause an implicit
+  //   instantiation to take place, in every translation unit in which such a 
+  //   use occurs; no diagnostic is required.
+  FunctionTemplateSpecializationInfo *SpecInfo
+    = Specialization->getTemplateSpecializationInfo();
+  assert(SpecInfo && "Function template specialization info missing?");
+  if (SpecInfo->getPointOfInstantiation().isValid()) {
+    Diag(FD->getLocation(), diag::err_specialization_after_instantiation)
+      << FD;
+    Diag(SpecInfo->getPointOfInstantiation(), 
+         diag::note_instantiation_required_here)
+      << (Specialization->getTemplateSpecializationKind() 
+                                                != TSK_ImplicitInstantiation);
+    return true;
+  }
+  
+  // Mark the prior declaration as an explicit specialization, so that later
+  // clients know that this is an explicit specialization.
+  SpecInfo->setTemplateSpecializationKind(TSK_ExplicitSpecialization);
+  
+  // Turn the given function declaration into a function template
+  // specialization, with the template arguments from the previous
+  // specialization.
+  FD->setFunctionTemplateSpecialization(Context, 
+                                        Specialization->getPrimaryTemplate(),
+                         new (Context) TemplateArgumentList(
+                             *Specialization->getTemplateSpecializationArgs()), 
+                                        /*InsertPos=*/0, 
+                                        TSK_ExplicitSpecialization);
+  
+  // The "previous declaration" for this function template specialization is
+  // the prior function template specialization.
+  Previous.clear();
+  Previous.addDecl(Specialization);
+  return false;
+}
+
+/// \brief Perform semantic analysis for the given non-template member
+/// specialization.
+///
+/// This routine performs all of the semantic analysis required for an 
+/// explicit member function specialization. On successful completion,
+/// the function declaration \p FD will become a member function
+/// specialization.
+///
+/// \param Member the member declaration, which will be updated to become a
+/// specialization.
+///
+/// \param Previous the set of declarations, one of which may be specialized
+/// by this function specialization;  the set will be modified to contain the
+/// redeclared member.
+bool 
+Sema::CheckMemberSpecialization(NamedDecl *Member, LookupResult &Previous) {
+  assert(!isa<TemplateDecl>(Member) && "Only for non-template members");
+         
+  // Try to find the member we are instantiating.
+  NamedDecl *Instantiation = 0;
+  NamedDecl *InstantiatedFrom = 0;
+  MemberSpecializationInfo *MSInfo = 0;
+
+  if (Previous.empty()) {
+    // Nowhere to look anyway.
+  } else if (FunctionDecl *Function = dyn_cast<FunctionDecl>(Member)) {
+    for (LookupResult::iterator I = Previous.begin(), E = Previous.end();
+           I != E; ++I) {
+      NamedDecl *D = (*I)->getUnderlyingDecl();
+      if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(D)) {
+        if (Context.hasSameType(Function->getType(), Method->getType())) {
+          Instantiation = Method;
+          InstantiatedFrom = Method->getInstantiatedFromMemberFunction();
+          MSInfo = Method->getMemberSpecializationInfo();
+          break;
+        }
+      }
+    }
+  } else if (isa<VarDecl>(Member)) {
+    VarDecl *PrevVar;
+    if (Previous.isSingleResult() &&
+        (PrevVar = dyn_cast<VarDecl>(Previous.getFoundDecl())))
+      if (PrevVar->isStaticDataMember()) {
+        Instantiation = PrevVar;
+        InstantiatedFrom = PrevVar->getInstantiatedFromStaticDataMember();
+        MSInfo = PrevVar->getMemberSpecializationInfo();
+      }
+  } else if (isa<RecordDecl>(Member)) {
+    CXXRecordDecl *PrevRecord;
+    if (Previous.isSingleResult() &&
+        (PrevRecord = dyn_cast<CXXRecordDecl>(Previous.getFoundDecl()))) {
+      Instantiation = PrevRecord;
+      InstantiatedFrom = PrevRecord->getInstantiatedFromMemberClass();
+      MSInfo = PrevRecord->getMemberSpecializationInfo();
+    }
+  }
+  
+  if (!Instantiation) {
+    // There is no previous declaration that matches. Since member
+    // specializations are always out-of-line, the caller will complain about
+    // this mismatch later.
+    return false;
+  }
+  
+  // Make sure that this is a specialization of a member.
+  if (!InstantiatedFrom) {
+    Diag(Member->getLocation(), diag::err_spec_member_not_instantiated)
+      << Member;
+    Diag(Instantiation->getLocation(), diag::note_specialized_decl);
+    return true;
+  }
+  
+  // C++ [temp.expl.spec]p6:
+  //   If a template, a member template or the member of a class template is
+  //   explicitly specialized then that spe- cialization shall be declared 
+  //   before the first use of that specialization that would cause an implicit
+  //   instantiation to take place, in every translation unit in which such a 
+  //   use occurs; no diagnostic is required.
+  assert(MSInfo && "Member specialization info missing?");
+  if (MSInfo->getPointOfInstantiation().isValid()) {
+    Diag(Member->getLocation(), diag::err_specialization_after_instantiation)
+      << Member;
+    Diag(MSInfo->getPointOfInstantiation(), 
+         diag::note_instantiation_required_here)
+      << (MSInfo->getTemplateSpecializationKind() != TSK_ImplicitInstantiation);
+    return true;
+  }
+  
+  // Check the scope of this explicit specialization.
+  if (CheckTemplateSpecializationScope(*this, 
+                                       InstantiatedFrom,
+                                       Instantiation, Member->getLocation(), 
+                                       false))
+    return true;
+
+  // Note that this is an explicit instantiation of a member.
+  // the original declaration to note that it is an explicit specialization
+  // (if it was previously an implicit instantiation). This latter step
+  // makes bookkeeping easier.
+  if (isa<FunctionDecl>(Member)) {
+    FunctionDecl *InstantiationFunction = cast<FunctionDecl>(Instantiation);
+    if (InstantiationFunction->getTemplateSpecializationKind() ==
+          TSK_ImplicitInstantiation) {
+      InstantiationFunction->setTemplateSpecializationKind(
+                                                  TSK_ExplicitSpecialization);
+      InstantiationFunction->setLocation(Member->getLocation());
+    }
+    
+    cast<FunctionDecl>(Member)->setInstantiationOfMemberFunction(
+                                        cast<CXXMethodDecl>(InstantiatedFrom),
+                                                  TSK_ExplicitSpecialization);
+  } else if (isa<VarDecl>(Member)) {
+    VarDecl *InstantiationVar = cast<VarDecl>(Instantiation);
+    if (InstantiationVar->getTemplateSpecializationKind() ==
+          TSK_ImplicitInstantiation) {
+      InstantiationVar->setTemplateSpecializationKind(
+                                                  TSK_ExplicitSpecialization);
+      InstantiationVar->setLocation(Member->getLocation());
+    }
+    
+    Context.setInstantiatedFromStaticDataMember(cast<VarDecl>(Member),
+                                                cast<VarDecl>(InstantiatedFrom),
+                                                TSK_ExplicitSpecialization);
+  } else {
+    assert(isa<CXXRecordDecl>(Member) && "Only member classes remain");
+    CXXRecordDecl *InstantiationClass = cast<CXXRecordDecl>(Instantiation);
+    if (InstantiationClass->getTemplateSpecializationKind() ==
+          TSK_ImplicitInstantiation) {
+      InstantiationClass->setTemplateSpecializationKind(
+                                                   TSK_ExplicitSpecialization);
+      InstantiationClass->setLocation(Member->getLocation());
+    }
+    
+    cast<CXXRecordDecl>(Member)->setInstantiationOfMemberClass(
+                                        cast<CXXRecordDecl>(InstantiatedFrom),
+                                                   TSK_ExplicitSpecialization);
+  }
+             
+  // Save the caller the trouble of having to figure out which declaration
+  // this specialization matches.
+  Previous.clear();
+  Previous.addDecl(Instantiation);
+  return false;
+}
+
+/// \brief Check the scope of an explicit instantiation.
+static void CheckExplicitInstantiationScope(Sema &S, NamedDecl *D,
+                                            SourceLocation InstLoc,
+                                            bool WasQualifiedName) {
+  DeclContext *ExpectedContext
+    = D->getDeclContext()->getEnclosingNamespaceContext()->getLookupContext();
+  DeclContext *CurContext = S.CurContext->getLookupContext();
+  
+  // C++0x [temp.explicit]p2:
+  //   An explicit instantiation shall appear in an enclosing namespace of its 
+  //   template.
+  //
+  // This is DR275, which we do not retroactively apply to C++98/03.
+  if (S.getLangOptions().CPlusPlus0x && 
+      !CurContext->Encloses(ExpectedContext)) {
+    if (NamespaceDecl *NS = dyn_cast<NamespaceDecl>(ExpectedContext))
+      S.Diag(InstLoc, diag::err_explicit_instantiation_out_of_scope)
+        << D << NS;
+    else
+      S.Diag(InstLoc, diag::err_explicit_instantiation_must_be_global)
+        << D;
+    S.Diag(D->getLocation(), diag::note_explicit_instantiation_here);
+    return;
+  }
+  
+  // C++0x [temp.explicit]p2:
+  //   If the name declared in the explicit instantiation is an unqualified 
+  //   name, the explicit instantiation shall appear in the namespace where 
+  //   its template is declared or, if that namespace is inline (7.3.1), any
+  //   namespace from its enclosing namespace set.
+  if (WasQualifiedName)
+    return;
+  
+  if (CurContext->Equals(ExpectedContext))
+    return;
+  
+  S.Diag(InstLoc, diag::err_explicit_instantiation_unqualified_wrong_namespace)
+    << D << ExpectedContext;
+  S.Diag(D->getLocation(), diag::note_explicit_instantiation_here);
+}
+
+/// \brief Determine whether the given scope specifier has a template-id in it.
+static bool ScopeSpecifierHasTemplateId(const CXXScopeSpec &SS) {
+  if (!SS.isSet())
+    return false;
+  
+  // C++0x [temp.explicit]p2:
+  //   If the explicit instantiation is for a member function, a member class 
+  //   or a static data member of a class template specialization, the name of
+  //   the class template specialization in the qualified-id for the member
+  //   name shall be a simple-template-id.
+  //
+  // C++98 has the same restriction, just worded differently.
+  for (NestedNameSpecifier *NNS = (NestedNameSpecifier *)SS.getScopeRep();
+       NNS; NNS = NNS->getPrefix())
+    if (Type *T = NNS->getAsType())
+      if (isa<TemplateSpecializationType>(T))
+        return true;
+
+  return false;
+}
+
+// Explicit instantiation of a class template specialization
+// FIXME: Implement extern template semantics
+Sema::DeclResult
+Sema::ActOnExplicitInstantiation(Scope *S,
+                                 SourceLocation ExternLoc,
+                                 SourceLocation TemplateLoc,
+                                 unsigned TagSpec,
+                                 SourceLocation KWLoc,
+                                 const CXXScopeSpec &SS,
+                                 TemplateTy TemplateD,
+                                 SourceLocation TemplateNameLoc,
+                                 SourceLocation LAngleLoc,
+                                 ASTTemplateArgsPtr TemplateArgsIn,
+                                 SourceLocation RAngleLoc,
+                                 AttributeList *Attr) {
+  // Find the class template we're specializing
+  TemplateName Name = TemplateD.getAsVal<TemplateName>();
+  ClassTemplateDecl *ClassTemplate
+    = cast<ClassTemplateDecl>(Name.getAsTemplateDecl());
+
+  // Check that the specialization uses the same tag kind as the
+  // original template.
+  TagDecl::TagKind Kind;
+  switch (TagSpec) {
+  default: assert(0 && "Unknown tag type!");
+  case DeclSpec::TST_struct: Kind = TagDecl::TK_struct; break;
+  case DeclSpec::TST_union:  Kind = TagDecl::TK_union; break;
+  case DeclSpec::TST_class:  Kind = TagDecl::TK_class; break;
+  }
+  if (!isAcceptableTagRedeclaration(ClassTemplate->getTemplatedDecl(),
+                                    Kind, KWLoc,
+                                    *ClassTemplate->getIdentifier())) {
+    Diag(KWLoc, diag::err_use_with_wrong_tag)
+      << ClassTemplate
+      << CodeModificationHint::CreateReplacement(KWLoc,
+                            ClassTemplate->getTemplatedDecl()->getKindName());
+    Diag(ClassTemplate->getTemplatedDecl()->getLocation(),
+         diag::note_previous_use);
+    Kind = ClassTemplate->getTemplatedDecl()->getTagKind();
+  }
+
+  // C++0x [temp.explicit]p2:
+  //   There are two forms of explicit instantiation: an explicit instantiation
+  //   definition and an explicit instantiation declaration. An explicit 
+  //   instantiation declaration begins with the extern keyword. [...]  
+  TemplateSpecializationKind TSK
+    = ExternLoc.isInvalid()? TSK_ExplicitInstantiationDefinition
+                           : TSK_ExplicitInstantiationDeclaration;
+  
+  // Translate the parser's template argument list in our AST format.
+  TemplateArgumentListInfo TemplateArgs(LAngleLoc, RAngleLoc);
+  translateTemplateArguments(TemplateArgsIn, TemplateArgs);
+
+  // Check that the template argument list is well-formed for this
+  // template.
+  TemplateArgumentListBuilder Converted(ClassTemplate->getTemplateParameters(),
+                                        TemplateArgs.size());
+  if (CheckTemplateArgumentList(ClassTemplate, TemplateNameLoc,
+                                TemplateArgs, false, Converted))
+    return true;
+
+  assert((Converted.structuredSize() ==
+            ClassTemplate->getTemplateParameters()->size()) &&
+         "Converted template argument list is too short!");
+
+  // Find the class template specialization declaration that
+  // corresponds to these arguments.
+  llvm::FoldingSetNodeID ID;
+  ClassTemplateSpecializationDecl::Profile(ID,
+                                           Converted.getFlatArguments(),
+                                           Converted.flatSize(),
+                                           Context);
+  void *InsertPos = 0;
+  ClassTemplateSpecializationDecl *PrevDecl
+    = ClassTemplate->getSpecializations().FindNodeOrInsertPos(ID, InsertPos);
+
+  // C++0x [temp.explicit]p2:
+  //   [...] An explicit instantiation shall appear in an enclosing
+  //   namespace of its template. [...]
+  //
+  // This is C++ DR 275.
+  CheckExplicitInstantiationScope(*this, ClassTemplate, TemplateNameLoc,
+                                  SS.isSet());
+  
+  ClassTemplateSpecializationDecl *Specialization = 0;
+
+  bool ReusedDecl = false;
+  if (PrevDecl) {
+    bool SuppressNew = false;
+    if (CheckSpecializationInstantiationRedecl(TemplateNameLoc, TSK,
+                                               PrevDecl, 
+                                              PrevDecl->getSpecializationKind(), 
+                                            PrevDecl->getPointOfInstantiation(),
+                                               SuppressNew))
+      return DeclPtrTy::make(PrevDecl);
+
+    if (SuppressNew)
+      return DeclPtrTy::make(PrevDecl);
+    
+    if (PrevDecl->getSpecializationKind() == TSK_ImplicitInstantiation ||
+        PrevDecl->getSpecializationKind() == TSK_Undeclared) {
+      // Since the only prior class template specialization with these
+      // arguments was referenced but not declared, reuse that
+      // declaration node as our own, updating its source location to
+      // reflect our new declaration.
+      Specialization = PrevDecl;
+      Specialization->setLocation(TemplateNameLoc);
+      PrevDecl = 0;
+      ReusedDecl = true;
+    }
+  }
+  
+  if (!Specialization) {
+    // Create a new class template specialization declaration node for
+    // this explicit specialization.
+    Specialization
+      = ClassTemplateSpecializationDecl::Create(Context,
+                                             ClassTemplate->getDeclContext(),
+                                                TemplateNameLoc,
+                                                ClassTemplate,
+                                                Converted, PrevDecl);
+
+    if (PrevDecl) {
+      // Remove the previous declaration from the folding set, since we want
+      // to introduce a new declaration.
+      ClassTemplate->getSpecializations().RemoveNode(PrevDecl);
+      ClassTemplate->getSpecializations().FindNodeOrInsertPos(ID, InsertPos);
+    } 
+    
+    // Insert the new specialization.
+    ClassTemplate->getSpecializations().InsertNode(Specialization, InsertPos);
+  }
+
+  // Build the fully-sugared type for this explicit instantiation as
+  // the user wrote in the explicit instantiation itself. This means
+  // that we'll pretty-print the type retrieved from the
+  // specialization's declaration the way that the user actually wrote
+  // the explicit instantiation, rather than formatting the name based
+  // on the "canonical" representation used to store the template
+  // arguments in the specialization.
+  QualType WrittenTy
+    = Context.getTemplateSpecializationType(Name, TemplateArgs,
+                                  Context.getTypeDeclType(Specialization));
+  Specialization->setTypeAsWritten(WrittenTy);
+  TemplateArgsIn.release();
+
+  if (!ReusedDecl) {
+    // Add the explicit instantiation into its lexical context. However,
+    // since explicit instantiations are never found by name lookup, we
+    // just put it into the declaration context directly.
+    Specialization->setLexicalDeclContext(CurContext);
+    CurContext->addDecl(Specialization);
+  }
+
+  // C++ [temp.explicit]p3:
+  //   A definition of a class template or class member template
+  //   shall be in scope at the point of the explicit instantiation of
+  //   the class template or class member template.
+  //
+  // This check comes when we actually try to perform the
+  // instantiation.
+  ClassTemplateSpecializationDecl *Def
+    = cast_or_null<ClassTemplateSpecializationDecl>(
+                                        Specialization->getDefinition(Context));
+  if (!Def)
+    InstantiateClassTemplateSpecialization(TemplateNameLoc, Specialization, TSK);
+  
+  // Instantiate the members of this class template specialization.
+  Def = cast_or_null<ClassTemplateSpecializationDecl>(
+                                       Specialization->getDefinition(Context));
+  if (Def)
+    InstantiateClassTemplateSpecializationMembers(TemplateNameLoc, Def, TSK);
+
+  return DeclPtrTy::make(Specialization);
+}
+
+// Explicit instantiation of a member class of a class template.
+Sema::DeclResult
+Sema::ActOnExplicitInstantiation(Scope *S,
+                                 SourceLocation ExternLoc,
+                                 SourceLocation TemplateLoc,
+                                 unsigned TagSpec,
+                                 SourceLocation KWLoc,
+                                 const CXXScopeSpec &SS,
+                                 IdentifierInfo *Name,
+                                 SourceLocation NameLoc,
+                                 AttributeList *Attr) {
+
+  bool Owned = false;
+  bool IsDependent = false;
+  DeclPtrTy TagD = ActOnTag(S, TagSpec, Action::TUK_Reference,
+                            KWLoc, SS, Name, NameLoc, Attr, AS_none,
+                            MultiTemplateParamsArg(*this, 0, 0),
+                            Owned, IsDependent);
+  assert(!IsDependent && "explicit instantiation of dependent name not yet handled");
+
+  if (!TagD)
+    return true;
+
+  TagDecl *Tag = cast<TagDecl>(TagD.getAs<Decl>());
+  if (Tag->isEnum()) {
+    Diag(TemplateLoc, diag::err_explicit_instantiation_enum)
+      << Context.getTypeDeclType(Tag);
+    return true;
+  }
+
+  if (Tag->isInvalidDecl())
+    return true;
+    
+  CXXRecordDecl *Record = cast<CXXRecordDecl>(Tag);
+  CXXRecordDecl *Pattern = Record->getInstantiatedFromMemberClass();
+  if (!Pattern) {
+    Diag(TemplateLoc, diag::err_explicit_instantiation_nontemplate_type)
+      << Context.getTypeDeclType(Record);
+    Diag(Record->getLocation(), diag::note_nontemplate_decl_here);
+    return true;
+  }
+
+  // C++0x [temp.explicit]p2:
+  //   If the explicit instantiation is for a class or member class, the 
+  //   elaborated-type-specifier in the declaration shall include a 
+  //   simple-template-id.
+  //
+  // C++98 has the same restriction, just worded differently.
+  if (!ScopeSpecifierHasTemplateId(SS))
+    Diag(TemplateLoc, diag::err_explicit_instantiation_without_qualified_id)
+      << Record << SS.getRange();
+           
+  // C++0x [temp.explicit]p2:
+  //   There are two forms of explicit instantiation: an explicit instantiation
+  //   definition and an explicit instantiation declaration. An explicit 
+  //   instantiation declaration begins with the extern keyword. [...]
+  TemplateSpecializationKind TSK
+    = ExternLoc.isInvalid()? TSK_ExplicitInstantiationDefinition
+                           : TSK_ExplicitInstantiationDeclaration;
+  
+  // C++0x [temp.explicit]p2:
+  //   [...] An explicit instantiation shall appear in an enclosing
+  //   namespace of its template. [...]
+  //
+  // This is C++ DR 275.
+  CheckExplicitInstantiationScope(*this, Record, NameLoc, true);
+  
+  // Verify that it is okay to explicitly instantiate here.
+  CXXRecordDecl *PrevDecl 
+    = cast_or_null<CXXRecordDecl>(Record->getPreviousDeclaration());
+  if (!PrevDecl && Record->getDefinition(Context))
+    PrevDecl = Record;
+  if (PrevDecl) {
+    MemberSpecializationInfo *MSInfo = PrevDecl->getMemberSpecializationInfo();
+    bool SuppressNew = false;
+    assert(MSInfo && "No member specialization information?");
+    if (CheckSpecializationInstantiationRedecl(TemplateLoc, TSK, 
+                                               PrevDecl,
+                                        MSInfo->getTemplateSpecializationKind(),
+                                             MSInfo->getPointOfInstantiation(), 
+                                               SuppressNew))
+      return true;
+    if (SuppressNew)
+      return TagD;
+  }
+  
+  CXXRecordDecl *RecordDef
+    = cast_or_null<CXXRecordDecl>(Record->getDefinition(Context));
+  if (!RecordDef) {
+    // C++ [temp.explicit]p3:
+    //   A definition of a member class of a class template shall be in scope 
+    //   at the point of an explicit instantiation of the member class.
+    CXXRecordDecl *Def 
+      = cast_or_null<CXXRecordDecl>(Pattern->getDefinition(Context));
+    if (!Def) {
+      Diag(TemplateLoc, diag::err_explicit_instantiation_undefined_member)
+        << 0 << Record->getDeclName() << Record->getDeclContext();
+      Diag(Pattern->getLocation(), diag::note_forward_declaration)
+        << Pattern;
+      return true;
+    } else {
+      if (InstantiateClass(NameLoc, Record, Def,
+                           getTemplateInstantiationArgs(Record),
+                           TSK))
+        return true;
+
+      RecordDef = cast_or_null<CXXRecordDecl>(Record->getDefinition(Context));
+      if (!RecordDef)
+        return true;
+    }
+  } 
+  
+  // Instantiate all of the members of the class.
+  InstantiateClassMembers(NameLoc, RecordDef,
+                          getTemplateInstantiationArgs(Record), TSK);
+
+  // FIXME: We don't have any representation for explicit instantiations of
+  // member classes. Such a representation is not needed for compilation, but it
+  // should be available for clients that want to see all of the declarations in
+  // the source code.
+  return TagD;
+}
+
+Sema::DeclResult Sema::ActOnExplicitInstantiation(Scope *S,
+                                                  SourceLocation ExternLoc,
+                                                  SourceLocation TemplateLoc,
+                                                  Declarator &D) {
+  // Explicit instantiations always require a name.
+  DeclarationName Name = GetNameForDeclarator(D);
+  if (!Name) {
+    if (!D.isInvalidType())
+      Diag(D.getDeclSpec().getSourceRange().getBegin(),
+           diag::err_explicit_instantiation_requires_name)
+        << D.getDeclSpec().getSourceRange()
+        << D.getSourceRange();
+    
+    return true;
+  }
+
+  // The scope passed in may not be a decl scope.  Zip up the scope tree until
+  // we find one that is.
+  while ((S->getFlags() & Scope::DeclScope) == 0 ||
+         (S->getFlags() & Scope::TemplateParamScope) != 0)
+    S = S->getParent();
+
+  // Determine the type of the declaration.
+  QualType R = GetTypeForDeclarator(D, S, 0);
+  if (R.isNull())
+    return true;
+  
+  if (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_typedef) {
+    // Cannot explicitly instantiate a typedef.
+    Diag(D.getIdentifierLoc(), diag::err_explicit_instantiation_of_typedef)
+      << Name;
+    return true;
+  }
+
+  // C++0x [temp.explicit]p1:
+  //   [...] An explicit instantiation of a function template shall not use the
+  //   inline or constexpr specifiers.
+  // Presumably, this also applies to member functions of class templates as
+  // well.
+  if (D.getDeclSpec().isInlineSpecified() && getLangOptions().CPlusPlus0x)
+    Diag(D.getDeclSpec().getInlineSpecLoc(), 
+         diag::err_explicit_instantiation_inline)
+      <<CodeModificationHint::CreateRemoval(D.getDeclSpec().getInlineSpecLoc());
+  
+  // FIXME: check for constexpr specifier.
+  
+  // C++0x [temp.explicit]p2:
+  //   There are two forms of explicit instantiation: an explicit instantiation
+  //   definition and an explicit instantiation declaration. An explicit 
+  //   instantiation declaration begins with the extern keyword. [...]  
+  TemplateSpecializationKind TSK
+    = ExternLoc.isInvalid()? TSK_ExplicitInstantiationDefinition
+                           : TSK_ExplicitInstantiationDeclaration;
+    
+  LookupResult Previous(*this, Name, D.getIdentifierLoc(), LookupOrdinaryName);
+  LookupParsedName(Previous, S, &D.getCXXScopeSpec());
+
+  if (!R->isFunctionType()) {
+    // C++ [temp.explicit]p1:
+    //   A [...] static data member of a class template can be explicitly 
+    //   instantiated from the member definition associated with its class 
+    //   template.
+    if (Previous.isAmbiguous())
+      return true;
+    
+    VarDecl *Prev = Previous.getAsSingle<VarDecl>();
+    if (!Prev || !Prev->isStaticDataMember()) {
+      // We expect to see a data data member here.
+      Diag(D.getIdentifierLoc(), diag::err_explicit_instantiation_not_known)
+        << Name;
+      for (LookupResult::iterator P = Previous.begin(), PEnd = Previous.end();
+           P != PEnd; ++P)
+        Diag((*P)->getLocation(), diag::note_explicit_instantiation_here);
+      return true;
+    }
+    
+    if (!Prev->getInstantiatedFromStaticDataMember()) {
+      // FIXME: Check for explicit specialization?
+      Diag(D.getIdentifierLoc(), 
+           diag::err_explicit_instantiation_data_member_not_instantiated)
+        << Prev;
+      Diag(Prev->getLocation(), diag::note_explicit_instantiation_here);
+      // FIXME: Can we provide a note showing where this was declared?
+      return true;
+    }
+    
+    // C++0x [temp.explicit]p2:
+    //   If the explicit instantiation is for a member function, a member class 
+    //   or a static data member of a class template specialization, the name of
+    //   the class template specialization in the qualified-id for the member
+    //   name shall be a simple-template-id.
+    //
+    // C++98 has the same restriction, just worded differently.
+    if (!ScopeSpecifierHasTemplateId(D.getCXXScopeSpec()))
+      Diag(D.getIdentifierLoc(), 
+           diag::err_explicit_instantiation_without_qualified_id)
+        << Prev << D.getCXXScopeSpec().getRange();
+    
+    // Check the scope of this explicit instantiation.
+    CheckExplicitInstantiationScope(*this, Prev, D.getIdentifierLoc(), true);
+    
+    // Verify that it is okay to explicitly instantiate here.
+    MemberSpecializationInfo *MSInfo = Prev->getMemberSpecializationInfo();
+    assert(MSInfo && "Missing static data member specialization info?");
+    bool SuppressNew = false;
+    if (CheckSpecializationInstantiationRedecl(D.getIdentifierLoc(), TSK, Prev,
+                                        MSInfo->getTemplateSpecializationKind(),
+                                              MSInfo->getPointOfInstantiation(), 
+                                               SuppressNew))
+      return true;
+    if (SuppressNew)
+      return DeclPtrTy();
+    
+    // Instantiate static data member.
+    Prev->setTemplateSpecializationKind(TSK, D.getIdentifierLoc());
+    if (TSK == TSK_ExplicitInstantiationDefinition)
+      InstantiateStaticDataMemberDefinition(D.getIdentifierLoc(), Prev, false,
+                                            /*DefinitionRequired=*/true);
+    
+    // FIXME: Create an ExplicitInstantiation node?
+    return DeclPtrTy();
+  }
+  
+  // If the declarator is a template-id, translate the parser's template 
+  // argument list into our AST format.
+  bool HasExplicitTemplateArgs = false;
+  TemplateArgumentListInfo TemplateArgs;
+  if (D.getName().getKind() == UnqualifiedId::IK_TemplateId) {
+    TemplateIdAnnotation *TemplateId = D.getName().TemplateId;
+    TemplateArgs.setLAngleLoc(TemplateId->LAngleLoc);
+    TemplateArgs.setRAngleLoc(TemplateId->RAngleLoc);
+    ASTTemplateArgsPtr TemplateArgsPtr(*this,
+                                       TemplateId->getTemplateArgs(),
+                                       TemplateId->NumArgs);
+    translateTemplateArguments(TemplateArgsPtr, TemplateArgs);
+    HasExplicitTemplateArgs = true;
+    TemplateArgsPtr.release();
+  }
+    
+  // C++ [temp.explicit]p1:
+  //   A [...] function [...] can be explicitly instantiated from its template. 
+  //   A member function [...] of a class template can be explicitly 
+  //  instantiated from the member definition associated with its class 
+  //  template.
+  UnresolvedSet<8> Matches;
+  for (LookupResult::iterator P = Previous.begin(), PEnd = Previous.end();
+       P != PEnd; ++P) {
+    NamedDecl *Prev = *P;
+    if (!HasExplicitTemplateArgs) {
+      if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(Prev)) {
+        if (Context.hasSameUnqualifiedType(Method->getType(), R)) {
+          Matches.clear();
+
+          Matches.addDecl(Method, P.getAccess());
+          if (Method->getTemplateSpecializationKind() == TSK_Undeclared)
+            break;
+        }
+      }
+    }
+    
+    FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(Prev);
+    if (!FunTmpl)
+      continue;
+
+    TemplateDeductionInfo Info(Context, D.getIdentifierLoc());
+    FunctionDecl *Specialization = 0;
+    if (TemplateDeductionResult TDK
+          = DeduceTemplateArguments(FunTmpl, 
+                               (HasExplicitTemplateArgs ? &TemplateArgs : 0),
+                                    R, Specialization, Info)) {
+      // FIXME: Keep track of almost-matches?
+      (void)TDK;
+      continue;
+    }
+    
+    Matches.addDecl(Specialization, P.getAccess());
+  }
+  
+  // Find the most specialized function template specialization.
+  UnresolvedSetIterator Result
+    = getMostSpecialized(Matches.begin(), Matches.end(), TPOC_Other, 
+                         D.getIdentifierLoc(), 
+          PartialDiagnostic(diag::err_explicit_instantiation_not_known) << Name,
+          PartialDiagnostic(diag::err_explicit_instantiation_ambiguous) << Name,
+                PartialDiagnostic(diag::note_explicit_instantiation_candidate));
+
+  if (Result == Matches.end())
+    return true;
+
+  // Ignore access control bits, we don't need them for redeclaration checking.
+  FunctionDecl *Specialization = cast<FunctionDecl>(*Result);
+  
+  if (Specialization->getTemplateSpecializationKind() == TSK_Undeclared) {
+    Diag(D.getIdentifierLoc(), 
+         diag::err_explicit_instantiation_member_function_not_instantiated)
+      << Specialization
+      << (Specialization->getTemplateSpecializationKind() ==
+          TSK_ExplicitSpecialization);
+    Diag(Specialization->getLocation(), diag::note_explicit_instantiation_here);
+    return true;
+  } 
+  
+  FunctionDecl *PrevDecl = Specialization->getPreviousDeclaration();
+  if (!PrevDecl && Specialization->isThisDeclarationADefinition())
+    PrevDecl = Specialization;
+
+  if (PrevDecl) {
+    bool SuppressNew = false;
+    if (CheckSpecializationInstantiationRedecl(D.getIdentifierLoc(), TSK,
+                                               PrevDecl, 
+                                     PrevDecl->getTemplateSpecializationKind(), 
+                                          PrevDecl->getPointOfInstantiation(),
+                                               SuppressNew))
+      return true;
+    
+    // FIXME: We may still want to build some representation of this
+    // explicit specialization.
+    if (SuppressNew)
+      return DeclPtrTy();
+  }
+
+  Specialization->setTemplateSpecializationKind(TSK, D.getIdentifierLoc());
+  
+  if (TSK == TSK_ExplicitInstantiationDefinition)
+    InstantiateFunctionDefinition(D.getIdentifierLoc(), Specialization, 
+                                  false, /*DefinitionRequired=*/true);
+ 
+  // C++0x [temp.explicit]p2:
+  //   If the explicit instantiation is for a member function, a member class 
+  //   or a static data member of a class template specialization, the name of
+  //   the class template specialization in the qualified-id for the member
+  //   name shall be a simple-template-id.
+  //
+  // C++98 has the same restriction, just worded differently.
+  FunctionTemplateDecl *FunTmpl = Specialization->getPrimaryTemplate();
+  if (D.getName().getKind() != UnqualifiedId::IK_TemplateId && !FunTmpl &&
+      D.getCXXScopeSpec().isSet() && 
+      !ScopeSpecifierHasTemplateId(D.getCXXScopeSpec()))
+    Diag(D.getIdentifierLoc(), 
+         diag::err_explicit_instantiation_without_qualified_id)
+    << Specialization << D.getCXXScopeSpec().getRange();
+  
+  CheckExplicitInstantiationScope(*this,
+                   FunTmpl? (NamedDecl *)FunTmpl 
+                          : Specialization->getInstantiatedFromMemberFunction(),
+                                  D.getIdentifierLoc(), 
+                                  D.getCXXScopeSpec().isSet());
+  
+  // FIXME: Create some kind of ExplicitInstantiationDecl here.
+  return DeclPtrTy();
+}
+
+Sema::TypeResult
+Sema::ActOnDependentTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
+                        const CXXScopeSpec &SS, IdentifierInfo *Name,
+                        SourceLocation TagLoc, SourceLocation NameLoc) {
+  // This has to hold, because SS is expected to be defined.
+  assert(Name && "Expected a name in a dependent tag");
+
+  NestedNameSpecifier *NNS
+    = static_cast<NestedNameSpecifier *>(SS.getScopeRep());
+  if (!NNS)
+    return true;
+
+  QualType T = CheckTypenameType(NNS, *Name, SourceRange(TagLoc, NameLoc));
+  if (T.isNull())
+    return true;
+
+  TagDecl::TagKind TagKind = TagDecl::getTagKindForTypeSpec(TagSpec);
+  QualType ElabType = Context.getElaboratedType(T, TagKind);
+
+  return ElabType.getAsOpaquePtr();
+}
+
+Sema::TypeResult
+Sema::ActOnTypenameType(SourceLocation TypenameLoc, const CXXScopeSpec &SS,
+                        const IdentifierInfo &II, SourceLocation IdLoc) {
+  NestedNameSpecifier *NNS
+    = static_cast<NestedNameSpecifier *>(SS.getScopeRep());
+  if (!NNS)
+    return true;
+
+  QualType T = CheckTypenameType(NNS, II, SourceRange(TypenameLoc, IdLoc));
+  if (T.isNull())
+    return true;
+  return T.getAsOpaquePtr();
+}
+
+Sema::TypeResult
+Sema::ActOnTypenameType(SourceLocation TypenameLoc, const CXXScopeSpec &SS,
+                        SourceLocation TemplateLoc, TypeTy *Ty) {
+  QualType T = GetTypeFromParser(Ty);
+  NestedNameSpecifier *NNS
+    = static_cast<NestedNameSpecifier *>(SS.getScopeRep());
+  const TemplateSpecializationType *TemplateId
+    = T->getAs<TemplateSpecializationType>();
+  assert(TemplateId && "Expected a template specialization type");
+
+  if (computeDeclContext(SS, false)) {
+    // If we can compute a declaration context, then the "typename"
+    // keyword was superfluous. Just build a QualifiedNameType to keep
+    // track of the nested-name-specifier.
+
+    // FIXME: Note that the QualifiedNameType had the "typename" keyword!
+    return Context.getQualifiedNameType(NNS, T).getAsOpaquePtr();
+  }
+
+  return Context.getTypenameType(NNS, TemplateId).getAsOpaquePtr();
+}
+
+/// \brief Build the type that describes a C++ typename specifier,
+/// e.g., "typename T::type".
+QualType
+Sema::CheckTypenameType(NestedNameSpecifier *NNS, const IdentifierInfo &II,
+                        SourceRange Range) {
+  CXXRecordDecl *CurrentInstantiation = 0;
+  if (NNS->isDependent()) {
+    CurrentInstantiation = getCurrentInstantiationOf(NNS);
+
+    // If the nested-name-specifier does not refer to the current
+    // instantiation, then build a typename type.
+    if (!CurrentInstantiation)
+      return Context.getTypenameType(NNS, &II);
+
+    // The nested-name-specifier refers to the current instantiation, so the
+    // "typename" keyword itself is superfluous. In C++03, the program is
+    // actually ill-formed. However, DR 382 (in C++0x CD1) allows such
+    // extraneous "typename" keywords, and we retroactively apply this DR to
+    // C++03 code.
+  }
+
+  DeclContext *Ctx = 0;
+
+  if (CurrentInstantiation)
+    Ctx = CurrentInstantiation;
+  else {
+    CXXScopeSpec SS;
+    SS.setScopeRep(NNS);
+    SS.setRange(Range);
+    if (RequireCompleteDeclContext(SS))
+      return QualType();
+
+    Ctx = computeDeclContext(SS);
+  }
+  assert(Ctx && "No declaration context?");
+
+  DeclarationName Name(&II);
+  LookupResult Result(*this, Name, Range.getEnd(), LookupOrdinaryName);
+  LookupQualifiedName(Result, Ctx);
+  unsigned DiagID = 0;
+  Decl *Referenced = 0;
+  switch (Result.getResultKind()) {
+  case LookupResult::NotFound:
+    DiagID = diag::err_typename_nested_not_found;
+    break;
+      
+  case LookupResult::NotFoundInCurrentInstantiation:
+    // Okay, it's a member of an unknown instantiation.
+    return Context.getTypenameType(NNS, &II);
+
+  case LookupResult::Found:
+    if (TypeDecl *Type = dyn_cast<TypeDecl>(Result.getFoundDecl())) {
+      // We found a type. Build a QualifiedNameType, since the
+      // typename-specifier was just sugar. FIXME: Tell
+      // QualifiedNameType that it has a "typename" prefix.
+      return Context.getQualifiedNameType(NNS, Context.getTypeDeclType(Type));
+    }
+
+    DiagID = diag::err_typename_nested_not_type;
+    Referenced = Result.getFoundDecl();
+    break;
+
+  case LookupResult::FoundUnresolvedValue:
+    llvm_unreachable("unresolved using decl in non-dependent context");
+    return QualType();
+
+  case LookupResult::FoundOverloaded:
+    DiagID = diag::err_typename_nested_not_type;
+    Referenced = *Result.begin();
+    break;
+
+  case LookupResult::Ambiguous:
+    return QualType();
+  }
+
+  // If we get here, it's because name lookup did not find a
+  // type. Emit an appropriate diagnostic and return an error.
+  Diag(Range.getEnd(), DiagID) << Range << Name << Ctx;
+  if (Referenced)
+    Diag(Referenced->getLocation(), diag::note_typename_refers_here)
+      << Name;
+  return QualType();
+}
+
+namespace {
+  // See Sema::RebuildTypeInCurrentInstantiation
+  class CurrentInstantiationRebuilder
+    : public TreeTransform<CurrentInstantiationRebuilder> {
+    SourceLocation Loc;
+    DeclarationName Entity;
+
+  public:
+    CurrentInstantiationRebuilder(Sema &SemaRef,
+                                  SourceLocation Loc,
+                                  DeclarationName Entity)
+    : TreeTransform<CurrentInstantiationRebuilder>(SemaRef),
+      Loc(Loc), Entity(Entity) { }
+
+    /// \brief Determine whether the given type \p T has already been
+    /// transformed.
+    ///
+    /// For the purposes of type reconstruction, a type has already been
+    /// transformed if it is NULL or if it is not dependent.
+    bool AlreadyTransformed(QualType T) {
+      return T.isNull() || !T->isDependentType();
+    }
+
+    /// \brief Returns the location of the entity whose type is being
+    /// rebuilt.
+    SourceLocation getBaseLocation() { return Loc; }
+
+    /// \brief Returns the name of the entity whose type is being rebuilt.
+    DeclarationName getBaseEntity() { return Entity; }
+
+    /// \brief Sets the "base" location and entity when that
+    /// information is known based on another transformation.
+    void setBase(SourceLocation Loc, DeclarationName Entity) {
+      this->Loc = Loc;
+      this->Entity = Entity;
+    }
+      
+    /// \brief Transforms an expression by returning the expression itself
+    /// (an identity function).
+    ///
+    /// FIXME: This is completely unsafe; we will need to actually clone the
+    /// expressions.
+    Sema::OwningExprResult TransformExpr(Expr *E) {
+      return getSema().Owned(E);
+    }
+
+    /// \brief Transforms a typename type by determining whether the type now
+    /// refers to a member of the current instantiation, and then
+    /// type-checking and building a QualifiedNameType (when possible).
+    QualType TransformTypenameType(TypeLocBuilder &TLB, TypenameTypeLoc TL);
+  };
+}
+
+QualType
+CurrentInstantiationRebuilder::TransformTypenameType(TypeLocBuilder &TLB,
+                                                     TypenameTypeLoc TL) {
+  TypenameType *T = TL.getTypePtr();
+
+  NestedNameSpecifier *NNS
+    = TransformNestedNameSpecifier(T->getQualifier(),
+                              /*FIXME:*/SourceRange(getBaseLocation()));
+  if (!NNS)
+    return QualType();
+
+  // If the nested-name-specifier did not change, and we cannot compute the
+  // context corresponding to the nested-name-specifier, then this
+  // typename type will not change; exit early.
+  CXXScopeSpec SS;
+  SS.setRange(SourceRange(getBaseLocation()));
+  SS.setScopeRep(NNS);
+
+  QualType Result;
+  if (NNS == T->getQualifier() && getSema().computeDeclContext(SS) == 0)
+    Result = QualType(T, 0);
+
+  // Rebuild the typename type, which will probably turn into a
+  // QualifiedNameType.
+  else if (const TemplateSpecializationType *TemplateId = T->getTemplateId()) {
+    QualType NewTemplateId
+      = TransformType(QualType(TemplateId, 0));
+    if (NewTemplateId.isNull())
+      return QualType();
+
+    if (NNS == T->getQualifier() &&
+        NewTemplateId == QualType(TemplateId, 0))
+      Result = QualType(T, 0);
+    else
+      Result = getDerived().RebuildTypenameType(NNS, NewTemplateId);
+  } else
+    Result = getDerived().RebuildTypenameType(NNS, T->getIdentifier(),
+                                              SourceRange(TL.getNameLoc()));
+
+  TypenameTypeLoc NewTL = TLB.push<TypenameTypeLoc>(Result);
+  NewTL.setNameLoc(TL.getNameLoc());
+  return Result;
+}
+
+/// \brief Rebuilds a type within the context of the current instantiation.
+///
+/// The type \p T is part of the type of an out-of-line member definition of
+/// a class template (or class template partial specialization) that was parsed
+/// and constructed before we entered the scope of the class template (or
+/// partial specialization thereof). This routine will rebuild that type now
+/// that we have entered the declarator's scope, which may produce different
+/// canonical types, e.g.,
+///
+/// \code
+/// template<typename T>
+/// struct X {
+///   typedef T* pointer;
+///   pointer data();
+/// };
+///
+/// template<typename T>
+/// typename X<T>::pointer X<T>::data() { ... }
+/// \endcode
+///
+/// Here, the type "typename X<T>::pointer" will be created as a TypenameType,
+/// since we do not know that we can look into X<T> when we parsed the type.
+/// This function will rebuild the type, performing the lookup of "pointer"
+/// in X<T> and returning a QualifiedNameType whose canonical type is the same
+/// as the canonical type of T*, allowing the return types of the out-of-line
+/// definition and the declaration to match.
+QualType Sema::RebuildTypeInCurrentInstantiation(QualType T, SourceLocation Loc,
+                                                 DeclarationName Name) {
+  if (T.isNull() || !T->isDependentType())
+    return T;
+
+  CurrentInstantiationRebuilder Rebuilder(*this, Loc, Name);
+  return Rebuilder.TransformType(T);
+}
+
+/// \brief Produces a formatted string that describes the binding of
+/// template parameters to template arguments.
+std::string
+Sema::getTemplateArgumentBindingsText(const TemplateParameterList *Params,
+                                      const TemplateArgumentList &Args) {
+  // FIXME: For variadic templates, we'll need to get the structured list.
+  return getTemplateArgumentBindingsText(Params, Args.getFlatArgumentList(),
+                                         Args.flat_size());
+}
+
+std::string
+Sema::getTemplateArgumentBindingsText(const TemplateParameterList *Params,
+                                      const TemplateArgument *Args,
+                                      unsigned NumArgs) {
+  std::string Result;
+
+  if (!Params || Params->size() == 0 || NumArgs == 0)
+    return Result;
+  
+  for (unsigned I = 0, N = Params->size(); I != N; ++I) {
+    if (I >= NumArgs)
+      break;
+    
+    if (I == 0)
+      Result += "[with ";
+    else
+      Result += ", ";
+    
+    if (const IdentifierInfo *Id = Params->getParam(I)->getIdentifier()) {
+      Result += Id->getName();
+    } else {
+      Result += '$';
+      Result += llvm::utostr(I);
+    }
+    
+    Result += " = ";
+    
+    switch (Args[I].getKind()) {
+      case TemplateArgument::Null:
+        Result += "<no value>";
+        break;
+        
+      case TemplateArgument::Type: {
+        std::string TypeStr;
+        Args[I].getAsType().getAsStringInternal(TypeStr, 
+                                                Context.PrintingPolicy);
+        Result += TypeStr;
+        break;
+      }
+        
+      case TemplateArgument::Declaration: {
+        bool Unnamed = true;
+        if (NamedDecl *ND = dyn_cast_or_null<NamedDecl>(Args[I].getAsDecl())) {
+          if (ND->getDeclName()) {
+            Unnamed = false;
+            Result += ND->getNameAsString();
+          }
+        }
+        
+        if (Unnamed) {
+          Result += "<anonymous>";
+        }
+        break;
+      }
+        
+      case TemplateArgument::Template: {
+        std::string Str;
+        llvm::raw_string_ostream OS(Str);
+        Args[I].getAsTemplate().print(OS, Context.PrintingPolicy);
+        Result += OS.str();
+        break;
+      }
+        
+      case TemplateArgument::Integral: {
+        Result += Args[I].getAsIntegral()->toString(10);
+        break;
+      }
+        
+      case TemplateArgument::Expression: {
+        assert(false && "No expressions in deduced template arguments!");
+        Result += "<expression>";
+        break;
+      }
+        
+      case TemplateArgument::Pack:
+        // FIXME: Format template argument packs
+        Result += "<template argument pack>";
+        break;        
+    }
+  }
+  
+  Result += ']';
+  return Result;
+}
diff --git a/lib/Sema/SemaTemplate.h b/lib/Sema/SemaTemplate.h
new file mode 100644
index 0000000..2bfb25a
--- /dev/null
+++ b/lib/Sema/SemaTemplate.h
@@ -0,0 +1,104 @@
+//===------- SemaTemplate.h - C++ Templates ---------------------*- C++ -*-===/
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//===----------------------------------------------------------------------===/
+//
+//  This file provides types used in the semantic analysis of C++ templates.
+//
+//===----------------------------------------------------------------------===/
+#ifndef LLVM_CLANG_SEMA_TEMPLATE_H
+#define LLVM_CLANG_SEMA_TEMPLATE_H
+
+#include "clang/AST/DeclTemplate.h"
+#include "llvm/ADT/SmallVector.h"
+#include <cassert>
+
+namespace clang {
+  /// \brief Data structure that captures multiple levels of template argument
+  /// lists for use in template instantiation.
+  ///
+  /// Multiple levels of template arguments occur when instantiating the 
+  /// definitions of member templates. For example:
+  ///
+  /// \code
+  /// template<typename T>
+  /// struct X {
+  ///   template<T Value>
+  ///   struct Y {
+  ///     void f();
+  ///   };
+  /// };
+  /// \endcode
+  ///
+  /// When instantiating X<int>::Y<17>::f, the multi-level template argument
+  /// list will contain a template argument list (int) at depth 0 and a
+  /// template argument list (17) at depth 1.
+  struct MultiLevelTemplateArgumentList {
+    /// \brief The template argument lists, stored from the innermost template
+    /// argument list (first) to the outermost template argument list (last).
+    llvm::SmallVector<const TemplateArgumentList *, 4> TemplateArgumentLists;
+    
+  public:
+    /// \brief Construct an empty set of template argument lists.
+    MultiLevelTemplateArgumentList() { }
+    
+    /// \brief Construct a single-level template argument list.
+    explicit 
+    MultiLevelTemplateArgumentList(const TemplateArgumentList &TemplateArgs) {
+      TemplateArgumentLists.push_back(&TemplateArgs);
+    }
+    
+    /// \brief Determine the number of levels in this template argument
+    /// list.
+    unsigned getNumLevels() const { return TemplateArgumentLists.size(); }
+    
+    /// \brief Retrieve the template argument at a given depth and index.
+    const TemplateArgument &operator()(unsigned Depth, unsigned Index) const {
+      assert(Depth < TemplateArgumentLists.size());
+      assert(Index < TemplateArgumentLists[getNumLevels() - Depth - 1]->size());
+      return TemplateArgumentLists[getNumLevels() - Depth - 1]->get(Index);
+    }
+    
+    /// \brief Determine whether there is a non-NULL template argument at the
+    /// given depth and index.
+    ///
+    /// There must exist a template argument list at the given depth.
+    bool hasTemplateArgument(unsigned Depth, unsigned Index) const {
+      assert(Depth < TemplateArgumentLists.size());
+      
+      if (Index >= TemplateArgumentLists[getNumLevels() - Depth - 1]->size())
+        return false;
+      
+      return !(*this)(Depth, Index).isNull();
+    }
+    
+    /// \brief Add a new outermost level to the multi-level template argument 
+    /// list.
+    void addOuterTemplateArguments(const TemplateArgumentList *TemplateArgs) {
+      TemplateArgumentLists.push_back(TemplateArgs);
+    }
+    
+    /// \brief Retrieve the innermost template argument list.
+    const TemplateArgumentList &getInnermost() const {
+      return *TemplateArgumentLists.front();
+    }
+  };
+  
+  /// \brief The context in which partial ordering of function templates occurs.
+  enum TemplatePartialOrderingContext {
+    /// \brief Partial ordering of function templates for a function call.
+    TPOC_Call,
+    /// \brief Partial ordering of function templates for a call to a 
+    /// conversion function.
+    TPOC_Conversion,
+    /// \brief Partial ordering of function templates in other contexts, e.g.,
+    /// taking the address of a function template or matching a function 
+    /// template specialization to a function template.
+    TPOC_Other
+  };
+}
+
+#endif // LLVM_CLANG_SEMA_TEMPLATE_H
diff --git a/lib/Sema/SemaTemplateDeduction.cpp b/lib/Sema/SemaTemplateDeduction.cpp
new file mode 100644
index 0000000..df4d4a8
--- /dev/null
+++ b/lib/Sema/SemaTemplateDeduction.cpp
@@ -0,0 +1,2509 @@
+//===------- SemaTemplateDeduction.cpp - Template Argument Deduction ------===/
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//===----------------------------------------------------------------------===/
+//
+//  This file implements C++ template argument deduction.
+//
+//===----------------------------------------------------------------------===/
+
+#include "Sema.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/DeclTemplate.h"
+#include "clang/AST/StmtVisitor.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/ExprCXX.h"
+#include "clang/Parse/DeclSpec.h"
+#include <algorithm>
+
+namespace clang {
+  /// \brief Various flags that control template argument deduction.
+  ///
+  /// These flags can be bitwise-OR'd together.
+  enum TemplateDeductionFlags {
+    /// \brief No template argument deduction flags, which indicates the
+    /// strictest results for template argument deduction (as used for, e.g.,
+    /// matching class template partial specializations).
+    TDF_None = 0,
+    /// \brief Within template argument deduction from a function call, we are
+    /// matching with a parameter type for which the original parameter was
+    /// a reference.
+    TDF_ParamWithReferenceType = 0x1,
+    /// \brief Within template argument deduction from a function call, we
+    /// are matching in a case where we ignore cv-qualifiers.
+    TDF_IgnoreQualifiers = 0x02,
+    /// \brief Within template argument deduction from a function call,
+    /// we are matching in a case where we can perform template argument
+    /// deduction from a template-id of a derived class of the argument type.
+    TDF_DerivedClass = 0x04,
+    /// \brief Allow non-dependent types to differ, e.g., when performing
+    /// template argument deduction from a function call where conversions
+    /// may apply.
+    TDF_SkipNonDependent = 0x08
+  };
+}
+
+using namespace clang;
+
+static Sema::TemplateDeductionResult
+DeduceTemplateArguments(Sema &S,
+                        TemplateParameterList *TemplateParams,
+                        const TemplateArgument &Param,
+                        const TemplateArgument &Arg,
+                        Sema::TemplateDeductionInfo &Info,
+                        llvm::SmallVectorImpl<TemplateArgument> &Deduced);
+
+/// \brief If the given expression is of a form that permits the deduction
+/// of a non-type template parameter, return the declaration of that
+/// non-type template parameter.
+static NonTypeTemplateParmDecl *getDeducedParameterFromExpr(Expr *E) {
+  if (ImplicitCastExpr *IC = dyn_cast<ImplicitCastExpr>(E))
+    E = IC->getSubExpr();
+
+  if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E))
+    return dyn_cast<NonTypeTemplateParmDecl>(DRE->getDecl());
+
+  return 0;
+}
+
+/// \brief Deduce the value of the given non-type template parameter
+/// from the given constant.
+static Sema::TemplateDeductionResult
+DeduceNonTypeTemplateArgument(Sema &S,
+                              NonTypeTemplateParmDecl *NTTP,
+                              llvm::APSInt Value,
+                              Sema::TemplateDeductionInfo &Info,
+                              llvm::SmallVectorImpl<TemplateArgument> &Deduced) {
+  assert(NTTP->getDepth() == 0 &&
+         "Cannot deduce non-type template argument with depth > 0");
+
+  if (Deduced[NTTP->getIndex()].isNull()) {
+    QualType T = NTTP->getType();
+
+    // FIXME: Make sure we didn't overflow our data type!
+    unsigned AllowedBits = S.Context.getTypeSize(T);
+    if (Value.getBitWidth() != AllowedBits)
+      Value.extOrTrunc(AllowedBits);
+    Value.setIsSigned(T->isSignedIntegerType());
+
+    Deduced[NTTP->getIndex()] = TemplateArgument(Value, T);
+    return Sema::TDK_Success;
+  }
+
+  assert(Deduced[NTTP->getIndex()].getKind() == TemplateArgument::Integral);
+
+  // If the template argument was previously deduced to a negative value,
+  // then our deduction fails.
+  const llvm::APSInt *PrevValuePtr = Deduced[NTTP->getIndex()].getAsIntegral();
+  if (PrevValuePtr->isNegative()) {
+    Info.Param = NTTP;
+    Info.FirstArg = Deduced[NTTP->getIndex()];
+    Info.SecondArg = TemplateArgument(Value, NTTP->getType());
+    return Sema::TDK_Inconsistent;
+  }
+
+  llvm::APSInt PrevValue = *PrevValuePtr;
+  if (Value.getBitWidth() > PrevValue.getBitWidth())
+    PrevValue.zext(Value.getBitWidth());
+  else if (Value.getBitWidth() < PrevValue.getBitWidth())
+    Value.zext(PrevValue.getBitWidth());
+
+  if (Value != PrevValue) {
+    Info.Param = NTTP;
+    Info.FirstArg = Deduced[NTTP->getIndex()];
+    Info.SecondArg = TemplateArgument(Value, NTTP->getType());
+    return Sema::TDK_Inconsistent;
+  }
+
+  return Sema::TDK_Success;
+}
+
+/// \brief Deduce the value of the given non-type template parameter
+/// from the given type- or value-dependent expression.
+///
+/// \returns true if deduction succeeded, false otherwise.
+static Sema::TemplateDeductionResult
+DeduceNonTypeTemplateArgument(Sema &S,
+                              NonTypeTemplateParmDecl *NTTP,
+                              Expr *Value,
+                              Sema::TemplateDeductionInfo &Info,
+                           llvm::SmallVectorImpl<TemplateArgument> &Deduced) {
+  assert(NTTP->getDepth() == 0 &&
+         "Cannot deduce non-type template argument with depth > 0");
+  assert((Value->isTypeDependent() || Value->isValueDependent()) &&
+         "Expression template argument must be type- or value-dependent.");
+
+  if (Deduced[NTTP->getIndex()].isNull()) {
+    // FIXME: Clone the Value?
+    Deduced[NTTP->getIndex()] = TemplateArgument(Value);
+    return Sema::TDK_Success;
+  }
+
+  if (Deduced[NTTP->getIndex()].getKind() == TemplateArgument::Integral) {
+    // Okay, we deduced a constant in one case and a dependent expression
+    // in another case. FIXME: Later, we will check that instantiating the
+    // dependent expression gives us the constant value.
+    return Sema::TDK_Success;
+  }
+
+  if (Deduced[NTTP->getIndex()].getKind() == TemplateArgument::Expression) {
+    // Compare the expressions for equality
+    llvm::FoldingSetNodeID ID1, ID2;
+    Deduced[NTTP->getIndex()].getAsExpr()->Profile(ID1, S.Context, true);
+    Value->Profile(ID2, S.Context, true);
+    if (ID1 == ID2)
+      return Sema::TDK_Success;
+   
+    // FIXME: Fill in argument mismatch information
+    return Sema::TDK_NonDeducedMismatch;
+  }
+
+  return Sema::TDK_Success;
+}
+
+/// \brief Deduce the value of the given non-type template parameter
+/// from the given declaration.
+///
+/// \returns true if deduction succeeded, false otherwise.
+static Sema::TemplateDeductionResult
+DeduceNonTypeTemplateArgument(Sema &S,
+                              NonTypeTemplateParmDecl *NTTP,
+                              Decl *D,
+                              Sema::TemplateDeductionInfo &Info,
+                              llvm::SmallVectorImpl<TemplateArgument> &Deduced) {
+  assert(NTTP->getDepth() == 0 &&
+         "Cannot deduce non-type template argument with depth > 0");
+  
+  if (Deduced[NTTP->getIndex()].isNull()) {
+    Deduced[NTTP->getIndex()] = TemplateArgument(D->getCanonicalDecl());
+    return Sema::TDK_Success;
+  }
+  
+  if (Deduced[NTTP->getIndex()].getKind() == TemplateArgument::Expression) {
+    // Okay, we deduced a declaration in one case and a dependent expression
+    // in another case.
+    return Sema::TDK_Success;
+  }
+  
+  if (Deduced[NTTP->getIndex()].getKind() == TemplateArgument::Declaration) {
+    // Compare the declarations for equality
+    if (Deduced[NTTP->getIndex()].getAsDecl()->getCanonicalDecl() ==
+          D->getCanonicalDecl())
+      return Sema::TDK_Success;
+    
+    // FIXME: Fill in argument mismatch information
+    return Sema::TDK_NonDeducedMismatch;
+  }
+  
+  return Sema::TDK_Success;
+}
+
+static Sema::TemplateDeductionResult
+DeduceTemplateArguments(Sema &S,
+                        TemplateParameterList *TemplateParams,
+                        TemplateName Param,
+                        TemplateName Arg,
+                        Sema::TemplateDeductionInfo &Info,
+                        llvm::SmallVectorImpl<TemplateArgument> &Deduced) {
+  TemplateDecl *ParamDecl = Param.getAsTemplateDecl();
+  if (!ParamDecl) {
+    // The parameter type is dependent and is not a template template parameter,
+    // so there is nothing that we can deduce.
+    return Sema::TDK_Success;
+  }
+  
+  if (TemplateTemplateParmDecl *TempParam
+        = dyn_cast<TemplateTemplateParmDecl>(ParamDecl)) {
+    // Bind the template template parameter to the given template name.
+    TemplateArgument &ExistingArg = Deduced[TempParam->getIndex()];
+    if (ExistingArg.isNull()) {
+      // This is the first deduction for this template template parameter.
+      ExistingArg = TemplateArgument(S.Context.getCanonicalTemplateName(Arg));
+      return Sema::TDK_Success;
+    }
+    
+    // Verify that the previous binding matches this deduction.
+    assert(ExistingArg.getKind() == TemplateArgument::Template);
+    if (S.Context.hasSameTemplateName(ExistingArg.getAsTemplate(), Arg))
+      return Sema::TDK_Success;
+    
+    // Inconsistent deduction.
+    Info.Param = TempParam;
+    Info.FirstArg = ExistingArg;
+    Info.SecondArg = TemplateArgument(Arg);
+    return Sema::TDK_Inconsistent;
+  }
+  
+  // Verify that the two template names are equivalent.
+  if (S.Context.hasSameTemplateName(Param, Arg))
+    return Sema::TDK_Success;
+  
+  // Mismatch of non-dependent template parameter to argument.
+  Info.FirstArg = TemplateArgument(Param);
+  Info.SecondArg = TemplateArgument(Arg);
+  return Sema::TDK_NonDeducedMismatch;
+}
+
+/// \brief Deduce the template arguments by comparing the template parameter
+/// type (which is a template-id) with the template argument type.
+///
+/// \param S the Sema
+///
+/// \param TemplateParams the template parameters that we are deducing
+///
+/// \param Param the parameter type
+///
+/// \param Arg the argument type
+///
+/// \param Info information about the template argument deduction itself
+///
+/// \param Deduced the deduced template arguments
+///
+/// \returns the result of template argument deduction so far. Note that a
+/// "success" result means that template argument deduction has not yet failed,
+/// but it may still fail, later, for other reasons.
+static Sema::TemplateDeductionResult
+DeduceTemplateArguments(Sema &S,
+                        TemplateParameterList *TemplateParams,
+                        const TemplateSpecializationType *Param,
+                        QualType Arg,
+                        Sema::TemplateDeductionInfo &Info,
+                        llvm::SmallVectorImpl<TemplateArgument> &Deduced) {
+  assert(Arg.isCanonical() && "Argument type must be canonical");
+
+  // Check whether the template argument is a dependent template-id.
+  if (const TemplateSpecializationType *SpecArg
+        = dyn_cast<TemplateSpecializationType>(Arg)) {
+    // Perform template argument deduction for the template name.
+    if (Sema::TemplateDeductionResult Result
+          = DeduceTemplateArguments(S, TemplateParams,
+                                    Param->getTemplateName(),
+                                    SpecArg->getTemplateName(),
+                                    Info, Deduced))
+      return Result;
+
+
+    // Perform template argument deduction on each template
+    // argument.
+    unsigned NumArgs = std::min(SpecArg->getNumArgs(), Param->getNumArgs());
+    for (unsigned I = 0; I != NumArgs; ++I)
+      if (Sema::TemplateDeductionResult Result
+            = DeduceTemplateArguments(S, TemplateParams,
+                                      Param->getArg(I),
+                                      SpecArg->getArg(I),
+                                      Info, Deduced))
+        return Result;
+
+    return Sema::TDK_Success;
+  }
+
+  // If the argument type is a class template specialization, we
+  // perform template argument deduction using its template
+  // arguments.
+  const RecordType *RecordArg = dyn_cast<RecordType>(Arg);
+  if (!RecordArg)
+    return Sema::TDK_NonDeducedMismatch;
+
+  ClassTemplateSpecializationDecl *SpecArg
+    = dyn_cast<ClassTemplateSpecializationDecl>(RecordArg->getDecl());
+  if (!SpecArg)
+    return Sema::TDK_NonDeducedMismatch;
+
+  // Perform template argument deduction for the template name.
+  if (Sema::TemplateDeductionResult Result
+        = DeduceTemplateArguments(S,
+                                  TemplateParams,
+                                  Param->getTemplateName(),
+                               TemplateName(SpecArg->getSpecializedTemplate()),
+                                  Info, Deduced))
+    return Result;
+
+  unsigned NumArgs = Param->getNumArgs();
+  const TemplateArgumentList &ArgArgs = SpecArg->getTemplateArgs();
+  if (NumArgs != ArgArgs.size())
+    return Sema::TDK_NonDeducedMismatch;
+
+  for (unsigned I = 0; I != NumArgs; ++I)
+    if (Sema::TemplateDeductionResult Result
+          = DeduceTemplateArguments(S, TemplateParams,
+                                    Param->getArg(I),
+                                    ArgArgs.get(I),
+                                    Info, Deduced))
+      return Result;
+
+  return Sema::TDK_Success;
+}
+
+/// \brief Deduce the template arguments by comparing the parameter type and
+/// the argument type (C++ [temp.deduct.type]).
+///
+/// \param S the semantic analysis object within which we are deducing
+///
+/// \param TemplateParams the template parameters that we are deducing
+///
+/// \param ParamIn the parameter type
+///
+/// \param ArgIn the argument type
+///
+/// \param Info information about the template argument deduction itself
+///
+/// \param Deduced the deduced template arguments
+///
+/// \param TDF bitwise OR of the TemplateDeductionFlags bits that describe
+/// how template argument deduction is performed.
+///
+/// \returns the result of template argument deduction so far. Note that a
+/// "success" result means that template argument deduction has not yet failed,
+/// but it may still fail, later, for other reasons.
+static Sema::TemplateDeductionResult
+DeduceTemplateArguments(Sema &S,
+                        TemplateParameterList *TemplateParams,
+                        QualType ParamIn, QualType ArgIn,
+                        Sema::TemplateDeductionInfo &Info,
+                        llvm::SmallVectorImpl<TemplateArgument> &Deduced,
+                        unsigned TDF) {
+  // We only want to look at the canonical types, since typedefs and
+  // sugar are not part of template argument deduction.
+  QualType Param = S.Context.getCanonicalType(ParamIn);
+  QualType Arg = S.Context.getCanonicalType(ArgIn);
+
+  // C++0x [temp.deduct.call]p4 bullet 1:
+  //   - If the original P is a reference type, the deduced A (i.e., the type
+  //     referred to by the reference) can be more cv-qualified than the
+  //     transformed A.
+  if (TDF & TDF_ParamWithReferenceType) {
+    Qualifiers Quals;
+    QualType UnqualParam = S.Context.getUnqualifiedArrayType(Param, Quals);
+    Quals.setCVRQualifiers(Quals.getCVRQualifiers() &
+                           Arg.getCVRQualifiersThroughArrayTypes());
+    Param = S.Context.getQualifiedType(UnqualParam, Quals);
+  }
+
+  // If the parameter type is not dependent, there is nothing to deduce.
+  if (!Param->isDependentType()) {
+    if (!(TDF & TDF_SkipNonDependent) && Param != Arg) {
+      
+      return Sema::TDK_NonDeducedMismatch;
+    }
+    
+    return Sema::TDK_Success;
+  }
+
+  // C++ [temp.deduct.type]p9:
+  //   A template type argument T, a template template argument TT or a
+  //   template non-type argument i can be deduced if P and A have one of
+  //   the following forms:
+  //
+  //     T
+  //     cv-list T
+  if (const TemplateTypeParmType *TemplateTypeParm
+        = Param->getAs<TemplateTypeParmType>()) {
+    unsigned Index = TemplateTypeParm->getIndex();
+    bool RecanonicalizeArg = false;
+
+    // If the argument type is an array type, move the qualifiers up to the
+    // top level, so they can be matched with the qualifiers on the parameter.
+    // FIXME: address spaces, ObjC GC qualifiers
+    if (isa<ArrayType>(Arg)) {
+      Qualifiers Quals;
+      Arg = S.Context.getUnqualifiedArrayType(Arg, Quals);
+      if (Quals) {
+        Arg = S.Context.getQualifiedType(Arg, Quals);
+        RecanonicalizeArg = true;
+      }
+    }
+
+    // The argument type can not be less qualified than the parameter
+    // type.
+    if (Param.isMoreQualifiedThan(Arg) && !(TDF & TDF_IgnoreQualifiers)) {
+      Info.Param = cast<TemplateTypeParmDecl>(TemplateParams->getParam(Index));
+      Info.FirstArg = Deduced[Index];
+      Info.SecondArg = TemplateArgument(Arg);
+      return Sema::TDK_InconsistentQuals;
+    }
+
+    assert(TemplateTypeParm->getDepth() == 0 && "Can't deduce with depth > 0");
+    assert(Arg != S.Context.OverloadTy && "Unresolved overloaded function");
+    QualType DeducedType = Arg;
+    DeducedType.removeCVRQualifiers(Param.getCVRQualifiers());
+    if (RecanonicalizeArg)
+      DeducedType = S.Context.getCanonicalType(DeducedType);
+
+    if (Deduced[Index].isNull())
+      Deduced[Index] = TemplateArgument(DeducedType);
+    else {
+      // C++ [temp.deduct.type]p2:
+      //   [...] If type deduction cannot be done for any P/A pair, or if for
+      //   any pair the deduction leads to more than one possible set of
+      //   deduced values, or if different pairs yield different deduced
+      //   values, or if any template argument remains neither deduced nor
+      //   explicitly specified, template argument deduction fails.
+      if (Deduced[Index].getAsType() != DeducedType) {
+        Info.Param
+          = cast<TemplateTypeParmDecl>(TemplateParams->getParam(Index));
+        Info.FirstArg = Deduced[Index];
+        Info.SecondArg = TemplateArgument(Arg);
+        return Sema::TDK_Inconsistent;
+      }
+    }
+    return Sema::TDK_Success;
+  }
+
+  // Set up the template argument deduction information for a failure.
+  Info.FirstArg = TemplateArgument(ParamIn);
+  Info.SecondArg = TemplateArgument(ArgIn);
+
+  // Check the cv-qualifiers on the parameter and argument types.
+  if (!(TDF & TDF_IgnoreQualifiers)) {
+    if (TDF & TDF_ParamWithReferenceType) {
+      if (Param.isMoreQualifiedThan(Arg))
+        return Sema::TDK_NonDeducedMismatch;
+    } else {
+      if (Param.getCVRQualifiers() != Arg.getCVRQualifiers())
+        return Sema::TDK_NonDeducedMismatch;
+    }
+  }
+
+  switch (Param->getTypeClass()) {
+    // No deduction possible for these types
+    case Type::Builtin:
+      return Sema::TDK_NonDeducedMismatch;
+
+    //     T *
+    case Type::Pointer: {
+      const PointerType *PointerArg = Arg->getAs<PointerType>();
+      if (!PointerArg)
+        return Sema::TDK_NonDeducedMismatch;
+
+      unsigned SubTDF = TDF & (TDF_IgnoreQualifiers | TDF_DerivedClass);
+      return DeduceTemplateArguments(S, TemplateParams,
+                                   cast<PointerType>(Param)->getPointeeType(),
+                                     PointerArg->getPointeeType(),
+                                     Info, Deduced, SubTDF);
+    }
+
+    //     T &
+    case Type::LValueReference: {
+      const LValueReferenceType *ReferenceArg = Arg->getAs<LValueReferenceType>();
+      if (!ReferenceArg)
+        return Sema::TDK_NonDeducedMismatch;
+
+      return DeduceTemplateArguments(S, TemplateParams,
+                           cast<LValueReferenceType>(Param)->getPointeeType(),
+                                     ReferenceArg->getPointeeType(),
+                                     Info, Deduced, 0);
+    }
+
+    //     T && [C++0x]
+    case Type::RValueReference: {
+      const RValueReferenceType *ReferenceArg = Arg->getAs<RValueReferenceType>();
+      if (!ReferenceArg)
+        return Sema::TDK_NonDeducedMismatch;
+
+      return DeduceTemplateArguments(S, TemplateParams,
+                           cast<RValueReferenceType>(Param)->getPointeeType(),
+                                     ReferenceArg->getPointeeType(),
+                                     Info, Deduced, 0);
+    }
+
+    //     T [] (implied, but not stated explicitly)
+    case Type::IncompleteArray: {
+      const IncompleteArrayType *IncompleteArrayArg =
+        S.Context.getAsIncompleteArrayType(Arg);
+      if (!IncompleteArrayArg)
+        return Sema::TDK_NonDeducedMismatch;
+
+      return DeduceTemplateArguments(S, TemplateParams,
+                     S.Context.getAsIncompleteArrayType(Param)->getElementType(),
+                                     IncompleteArrayArg->getElementType(),
+                                     Info, Deduced, 0);
+    }
+
+    //     T [integer-constant]
+    case Type::ConstantArray: {
+      const ConstantArrayType *ConstantArrayArg =
+        S.Context.getAsConstantArrayType(Arg);
+      if (!ConstantArrayArg)
+        return Sema::TDK_NonDeducedMismatch;
+
+      const ConstantArrayType *ConstantArrayParm =
+        S.Context.getAsConstantArrayType(Param);
+      if (ConstantArrayArg->getSize() != ConstantArrayParm->getSize())
+        return Sema::TDK_NonDeducedMismatch;
+
+      return DeduceTemplateArguments(S, TemplateParams,
+                                     ConstantArrayParm->getElementType(),
+                                     ConstantArrayArg->getElementType(),
+                                     Info, Deduced, 0);
+    }
+
+    //     type [i]
+    case Type::DependentSizedArray: {
+      const ArrayType *ArrayArg = S.Context.getAsArrayType(Arg);
+      if (!ArrayArg)
+        return Sema::TDK_NonDeducedMismatch;
+
+      // Check the element type of the arrays
+      const DependentSizedArrayType *DependentArrayParm
+        = S.Context.getAsDependentSizedArrayType(Param);
+      if (Sema::TemplateDeductionResult Result
+            = DeduceTemplateArguments(S, TemplateParams,
+                                      DependentArrayParm->getElementType(),
+                                      ArrayArg->getElementType(),
+                                      Info, Deduced, 0))
+        return Result;
+
+      // Determine the array bound is something we can deduce.
+      NonTypeTemplateParmDecl *NTTP
+        = getDeducedParameterFromExpr(DependentArrayParm->getSizeExpr());
+      if (!NTTP)
+        return Sema::TDK_Success;
+
+      // We can perform template argument deduction for the given non-type
+      // template parameter.
+      assert(NTTP->getDepth() == 0 &&
+             "Cannot deduce non-type template argument at depth > 0");
+      if (const ConstantArrayType *ConstantArrayArg
+            = dyn_cast<ConstantArrayType>(ArrayArg)) {
+        llvm::APSInt Size(ConstantArrayArg->getSize());
+        return DeduceNonTypeTemplateArgument(S, NTTP, Size,
+                                             Info, Deduced);
+      }
+      if (const DependentSizedArrayType *DependentArrayArg
+            = dyn_cast<DependentSizedArrayType>(ArrayArg))
+        return DeduceNonTypeTemplateArgument(S, NTTP,
+                                             DependentArrayArg->getSizeExpr(),
+                                             Info, Deduced);
+
+      // Incomplete type does not match a dependently-sized array type
+      return Sema::TDK_NonDeducedMismatch;
+    }
+
+    //     type(*)(T)
+    //     T(*)()
+    //     T(*)(T)
+    case Type::FunctionProto: {
+      const FunctionProtoType *FunctionProtoArg =
+        dyn_cast<FunctionProtoType>(Arg);
+      if (!FunctionProtoArg)
+        return Sema::TDK_NonDeducedMismatch;
+
+      const FunctionProtoType *FunctionProtoParam =
+        cast<FunctionProtoType>(Param);
+
+      if (FunctionProtoParam->getTypeQuals() !=
+          FunctionProtoArg->getTypeQuals())
+        return Sema::TDK_NonDeducedMismatch;
+
+      if (FunctionProtoParam->getNumArgs() != FunctionProtoArg->getNumArgs())
+        return Sema::TDK_NonDeducedMismatch;
+
+      if (FunctionProtoParam->isVariadic() != FunctionProtoArg->isVariadic())
+        return Sema::TDK_NonDeducedMismatch;
+
+      // Check return types.
+      if (Sema::TemplateDeductionResult Result
+            = DeduceTemplateArguments(S, TemplateParams,
+                                      FunctionProtoParam->getResultType(),
+                                      FunctionProtoArg->getResultType(),
+                                      Info, Deduced, 0))
+        return Result;
+
+      for (unsigned I = 0, N = FunctionProtoParam->getNumArgs(); I != N; ++I) {
+        // Check argument types.
+        if (Sema::TemplateDeductionResult Result
+              = DeduceTemplateArguments(S, TemplateParams,
+                                        FunctionProtoParam->getArgType(I),
+                                        FunctionProtoArg->getArgType(I),
+                                        Info, Deduced, 0))
+          return Result;
+      }
+
+      return Sema::TDK_Success;
+    }
+
+    //     template-name<T> (where template-name refers to a class template)
+    //     template-name<i>
+    //     TT<T>
+    //     TT<i>
+    //     TT<>
+    case Type::TemplateSpecialization: {
+      const TemplateSpecializationType *SpecParam
+        = cast<TemplateSpecializationType>(Param);
+
+      // Try to deduce template arguments from the template-id.
+      Sema::TemplateDeductionResult Result
+        = DeduceTemplateArguments(S, TemplateParams, SpecParam, Arg,
+                                  Info, Deduced);
+
+      if (Result && (TDF & TDF_DerivedClass)) {
+        // C++ [temp.deduct.call]p3b3:
+        //   If P is a class, and P has the form template-id, then A can be a
+        //   derived class of the deduced A. Likewise, if P is a pointer to a
+        //   class of the form template-id, A can be a pointer to a derived
+        //   class pointed to by the deduced A.
+        //
+        // More importantly:
+        //   These alternatives are considered only if type deduction would
+        //   otherwise fail.
+        if (const RecordType *RecordT = Arg->getAs<RecordType>()) {
+          // We cannot inspect base classes as part of deduction when the type
+          // is incomplete, so either instantiate any templates necessary to
+          // complete the type, or skip over it if it cannot be completed.
+          if (S.RequireCompleteType(Info.getLocation(), Arg, 0))
+            return Result;
+
+          // Use data recursion to crawl through the list of base classes.
+          // Visited contains the set of nodes we have already visited, while
+          // ToVisit is our stack of records that we still need to visit.
+          llvm::SmallPtrSet<const RecordType *, 8> Visited;
+          llvm::SmallVector<const RecordType *, 8> ToVisit;
+          ToVisit.push_back(RecordT);
+          bool Successful = false;
+          while (!ToVisit.empty()) {
+            // Retrieve the next class in the inheritance hierarchy.
+            const RecordType *NextT = ToVisit.back();
+            ToVisit.pop_back();
+
+            // If we have already seen this type, skip it.
+            if (!Visited.insert(NextT))
+              continue;
+
+            // If this is a base class, try to perform template argument
+            // deduction from it.
+            if (NextT != RecordT) {
+              Sema::TemplateDeductionResult BaseResult
+                = DeduceTemplateArguments(S, TemplateParams, SpecParam,
+                                          QualType(NextT, 0), Info, Deduced);
+
+              // If template argument deduction for this base was successful,
+              // note that we had some success.
+              if (BaseResult == Sema::TDK_Success)
+                Successful = true;
+            }
+
+            // Visit base classes
+            CXXRecordDecl *Next = cast<CXXRecordDecl>(NextT->getDecl());
+            for (CXXRecordDecl::base_class_iterator Base = Next->bases_begin(),
+                                                 BaseEnd = Next->bases_end();
+                 Base != BaseEnd; ++Base) {
+              assert(Base->getType()->isRecordType() &&
+                     "Base class that isn't a record?");
+              ToVisit.push_back(Base->getType()->getAs<RecordType>());
+            }
+          }
+
+          if (Successful)
+            return Sema::TDK_Success;
+        }
+
+      }
+
+      return Result;
+    }
+
+    //     T type::*
+    //     T T::*
+    //     T (type::*)()
+    //     type (T::*)()
+    //     type (type::*)(T)
+    //     type (T::*)(T)
+    //     T (type::*)(T)
+    //     T (T::*)()
+    //     T (T::*)(T)
+    case Type::MemberPointer: {
+      const MemberPointerType *MemPtrParam = cast<MemberPointerType>(Param);
+      const MemberPointerType *MemPtrArg = dyn_cast<MemberPointerType>(Arg);
+      if (!MemPtrArg)
+        return Sema::TDK_NonDeducedMismatch;
+
+      if (Sema::TemplateDeductionResult Result
+            = DeduceTemplateArguments(S, TemplateParams,
+                                      MemPtrParam->getPointeeType(),
+                                      MemPtrArg->getPointeeType(),
+                                      Info, Deduced,
+                                      TDF & TDF_IgnoreQualifiers))
+        return Result;
+
+      return DeduceTemplateArguments(S, TemplateParams,
+                                     QualType(MemPtrParam->getClass(), 0),
+                                     QualType(MemPtrArg->getClass(), 0),
+                                     Info, Deduced, 0);
+    }
+
+    //     (clang extension)
+    //
+    //     type(^)(T)
+    //     T(^)()
+    //     T(^)(T)
+    case Type::BlockPointer: {
+      const BlockPointerType *BlockPtrParam = cast<BlockPointerType>(Param);
+      const BlockPointerType *BlockPtrArg = dyn_cast<BlockPointerType>(Arg);
+
+      if (!BlockPtrArg)
+        return Sema::TDK_NonDeducedMismatch;
+
+      return DeduceTemplateArguments(S, TemplateParams,
+                                     BlockPtrParam->getPointeeType(),
+                                     BlockPtrArg->getPointeeType(), Info,
+                                     Deduced, 0);
+    }
+
+    case Type::TypeOfExpr:
+    case Type::TypeOf:
+    case Type::Typename:
+      // No template argument deduction for these types
+      return Sema::TDK_Success;
+
+    default:
+      break;
+  }
+
+  // FIXME: Many more cases to go (to go).
+  return Sema::TDK_Success;
+}
+
+static Sema::TemplateDeductionResult
+DeduceTemplateArguments(Sema &S,
+                        TemplateParameterList *TemplateParams,
+                        const TemplateArgument &Param,
+                        const TemplateArgument &Arg,
+                        Sema::TemplateDeductionInfo &Info,
+                        llvm::SmallVectorImpl<TemplateArgument> &Deduced) {
+  switch (Param.getKind()) {
+  case TemplateArgument::Null:
+    assert(false && "Null template argument in parameter list");
+    break;
+
+  case TemplateArgument::Type:
+    if (Arg.getKind() == TemplateArgument::Type)
+      return DeduceTemplateArguments(S, TemplateParams, Param.getAsType(),
+                                     Arg.getAsType(), Info, Deduced, 0);
+    Info.FirstArg = Param;
+    Info.SecondArg = Arg;
+    return Sema::TDK_NonDeducedMismatch;
+      
+  case TemplateArgument::Template:
+    if (Arg.getKind() == TemplateArgument::Template)
+      return DeduceTemplateArguments(S, TemplateParams, 
+                                     Param.getAsTemplate(),
+                                     Arg.getAsTemplate(), Info, Deduced);
+    Info.FirstArg = Param;
+    Info.SecondArg = Arg;
+    return Sema::TDK_NonDeducedMismatch;
+      
+  case TemplateArgument::Declaration:
+    if (Arg.getKind() == TemplateArgument::Declaration &&
+        Param.getAsDecl()->getCanonicalDecl() ==
+          Arg.getAsDecl()->getCanonicalDecl())
+      return Sema::TDK_Success;
+      
+    Info.FirstArg = Param;
+    Info.SecondArg = Arg;
+    return Sema::TDK_NonDeducedMismatch;
+
+  case TemplateArgument::Integral:
+    if (Arg.getKind() == TemplateArgument::Integral) {
+      // FIXME: Zero extension + sign checking here?
+      if (*Param.getAsIntegral() == *Arg.getAsIntegral())
+        return Sema::TDK_Success;
+
+      Info.FirstArg = Param;
+      Info.SecondArg = Arg;
+      return Sema::TDK_NonDeducedMismatch;
+    }
+
+    if (Arg.getKind() == TemplateArgument::Expression) {
+      Info.FirstArg = Param;
+      Info.SecondArg = Arg;
+      return Sema::TDK_NonDeducedMismatch;
+    }
+
+    assert(false && "Type/value mismatch");
+    Info.FirstArg = Param;
+    Info.SecondArg = Arg;
+    return Sema::TDK_NonDeducedMismatch;
+
+  case TemplateArgument::Expression: {
+    if (NonTypeTemplateParmDecl *NTTP
+          = getDeducedParameterFromExpr(Param.getAsExpr())) {
+      if (Arg.getKind() == TemplateArgument::Integral)
+        // FIXME: Sign problems here
+        return DeduceNonTypeTemplateArgument(S, NTTP,
+                                             *Arg.getAsIntegral(),
+                                             Info, Deduced);
+      if (Arg.getKind() == TemplateArgument::Expression)
+        return DeduceNonTypeTemplateArgument(S, NTTP, Arg.getAsExpr(),
+                                             Info, Deduced);
+      if (Arg.getKind() == TemplateArgument::Declaration)
+        return DeduceNonTypeTemplateArgument(S, NTTP, Arg.getAsDecl(),
+                                             Info, Deduced);
+      
+      assert(false && "Type/value mismatch");
+      Info.FirstArg = Param;
+      Info.SecondArg = Arg;
+      return Sema::TDK_NonDeducedMismatch;
+    }
+
+    // Can't deduce anything, but that's okay.
+    return Sema::TDK_Success;
+  }
+  case TemplateArgument::Pack:
+    assert(0 && "FIXME: Implement!");
+    break;
+  }
+
+  return Sema::TDK_Success;
+}
+
+static Sema::TemplateDeductionResult
+DeduceTemplateArguments(Sema &S,
+                        TemplateParameterList *TemplateParams,
+                        const TemplateArgumentList &ParamList,
+                        const TemplateArgumentList &ArgList,
+                        Sema::TemplateDeductionInfo &Info,
+                        llvm::SmallVectorImpl<TemplateArgument> &Deduced) {
+  assert(ParamList.size() == ArgList.size());
+  for (unsigned I = 0, N = ParamList.size(); I != N; ++I) {
+    if (Sema::TemplateDeductionResult Result
+          = DeduceTemplateArguments(S, TemplateParams,
+                                    ParamList[I], ArgList[I],
+                                    Info, Deduced))
+      return Result;
+  }
+  return Sema::TDK_Success;
+}
+
+/// \brief Determine whether two template arguments are the same.
+static bool isSameTemplateArg(ASTContext &Context,
+                              const TemplateArgument &X,
+                              const TemplateArgument &Y) {
+  if (X.getKind() != Y.getKind())
+    return false;
+
+  switch (X.getKind()) {
+    case TemplateArgument::Null:
+      assert(false && "Comparing NULL template argument");
+      break;
+
+    case TemplateArgument::Type:
+      return Context.getCanonicalType(X.getAsType()) ==
+             Context.getCanonicalType(Y.getAsType());
+
+    case TemplateArgument::Declaration:
+      return X.getAsDecl()->getCanonicalDecl() ==
+             Y.getAsDecl()->getCanonicalDecl();
+
+    case TemplateArgument::Template:
+      return Context.getCanonicalTemplateName(X.getAsTemplate())
+               .getAsVoidPointer() ==
+             Context.getCanonicalTemplateName(Y.getAsTemplate())
+               .getAsVoidPointer();
+      
+    case TemplateArgument::Integral:
+      return *X.getAsIntegral() == *Y.getAsIntegral();
+
+    case TemplateArgument::Expression: {
+      llvm::FoldingSetNodeID XID, YID;
+      X.getAsExpr()->Profile(XID, Context, true);
+      Y.getAsExpr()->Profile(YID, Context, true);      
+      return XID == YID;
+    }
+
+    case TemplateArgument::Pack:
+      if (X.pack_size() != Y.pack_size())
+        return false;
+
+      for (TemplateArgument::pack_iterator XP = X.pack_begin(),
+                                        XPEnd = X.pack_end(),
+                                           YP = Y.pack_begin();
+           XP != XPEnd; ++XP, ++YP)
+        if (!isSameTemplateArg(Context, *XP, *YP))
+          return false;
+
+      return true;
+  }
+
+  return false;
+}
+
+/// \brief Helper function to build a TemplateParameter when we don't
+/// know its type statically.
+static TemplateParameter makeTemplateParameter(Decl *D) {
+  if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(D))
+    return TemplateParameter(TTP);
+  else if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(D))
+    return TemplateParameter(NTTP);
+
+  return TemplateParameter(cast<TemplateTemplateParmDecl>(D));
+}
+
+/// \brief Perform template argument deduction to determine whether
+/// the given template arguments match the given class template
+/// partial specialization per C++ [temp.class.spec.match].
+Sema::TemplateDeductionResult
+Sema::DeduceTemplateArguments(ClassTemplatePartialSpecializationDecl *Partial,
+                              const TemplateArgumentList &TemplateArgs,
+                              TemplateDeductionInfo &Info) {
+  // C++ [temp.class.spec.match]p2:
+  //   A partial specialization matches a given actual template
+  //   argument list if the template arguments of the partial
+  //   specialization can be deduced from the actual template argument
+  //   list (14.8.2).
+  SFINAETrap Trap(*this);
+  llvm::SmallVector<TemplateArgument, 4> Deduced;
+  Deduced.resize(Partial->getTemplateParameters()->size());
+  if (TemplateDeductionResult Result
+        = ::DeduceTemplateArguments(*this,
+                                    Partial->getTemplateParameters(),
+                                    Partial->getTemplateArgs(),
+                                    TemplateArgs, Info, Deduced))
+    return Result;
+
+  InstantiatingTemplate Inst(*this, Partial->getLocation(), Partial,
+                             Deduced.data(), Deduced.size());
+  if (Inst)
+    return TDK_InstantiationDepth;
+
+  // C++ [temp.deduct.type]p2:
+  //   [...] or if any template argument remains neither deduced nor
+  //   explicitly specified, template argument deduction fails.
+  TemplateArgumentListBuilder Builder(Partial->getTemplateParameters(),
+                                      Deduced.size());
+  for (unsigned I = 0, N = Deduced.size(); I != N; ++I) {
+    if (Deduced[I].isNull()) {
+      Decl *Param
+        = const_cast<NamedDecl *>(
+                                Partial->getTemplateParameters()->getParam(I));
+      if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(Param))
+        Info.Param = TTP;
+      else if (NonTypeTemplateParmDecl *NTTP
+                 = dyn_cast<NonTypeTemplateParmDecl>(Param))
+        Info.Param = NTTP;
+      else
+        Info.Param = cast<TemplateTemplateParmDecl>(Param);
+      return TDK_Incomplete;
+    }
+
+    Builder.Append(Deduced[I]);
+  }
+
+  // Form the template argument list from the deduced template arguments.
+  TemplateArgumentList *DeducedArgumentList
+    = new (Context) TemplateArgumentList(Context, Builder, /*TakeArgs=*/true);
+  Info.reset(DeducedArgumentList);
+
+  // Substitute the deduced template arguments into the template
+  // arguments of the class template partial specialization, and
+  // verify that the instantiated template arguments are both valid
+  // and are equivalent to the template arguments originally provided
+  // to the class template.
+  ClassTemplateDecl *ClassTemplate = Partial->getSpecializedTemplate();
+  const TemplateArgumentLoc *PartialTemplateArgs
+    = Partial->getTemplateArgsAsWritten();
+  unsigned N = Partial->getNumTemplateArgsAsWritten();
+
+  // Note that we don't provide the langle and rangle locations.
+  TemplateArgumentListInfo InstArgs;
+
+  for (unsigned I = 0; I != N; ++I) {
+    Decl *Param = const_cast<NamedDecl *>(
+                    ClassTemplate->getTemplateParameters()->getParam(I));
+    TemplateArgumentLoc InstArg;
+    if (Subst(PartialTemplateArgs[I], InstArg,
+              MultiLevelTemplateArgumentList(*DeducedArgumentList))) {
+      Info.Param = makeTemplateParameter(Param);
+      Info.FirstArg = PartialTemplateArgs[I].getArgument();
+      return TDK_SubstitutionFailure;
+    }
+    InstArgs.addArgument(InstArg);
+  }
+
+  TemplateArgumentListBuilder ConvertedInstArgs(
+                                  ClassTemplate->getTemplateParameters(), N);
+
+  if (CheckTemplateArgumentList(ClassTemplate, Partial->getLocation(),
+                                InstArgs, false, ConvertedInstArgs)) {
+    // FIXME: fail with more useful information?
+    return TDK_SubstitutionFailure;
+  }
+  
+  for (unsigned I = 0, E = ConvertedInstArgs.flatSize(); I != E; ++I) {
+    TemplateArgument InstArg = ConvertedInstArgs.getFlatArguments()[I];
+
+    Decl *Param = const_cast<NamedDecl *>(
+                    ClassTemplate->getTemplateParameters()->getParam(I));
+
+    if (InstArg.getKind() == TemplateArgument::Expression) {
+      // When the argument is an expression, check the expression result
+      // against the actual template parameter to get down to the canonical
+      // template argument.
+      Expr *InstExpr = InstArg.getAsExpr();
+      if (NonTypeTemplateParmDecl *NTTP
+            = dyn_cast<NonTypeTemplateParmDecl>(Param)) {
+        if (CheckTemplateArgument(NTTP, NTTP->getType(), InstExpr, InstArg)) {
+          Info.Param = makeTemplateParameter(Param);
+          Info.FirstArg = Partial->getTemplateArgs()[I];
+          return TDK_SubstitutionFailure;
+        }
+      }
+    }
+
+    if (!isSameTemplateArg(Context, TemplateArgs[I], InstArg)) {
+      Info.Param = makeTemplateParameter(Param);
+      Info.FirstArg = TemplateArgs[I];
+      Info.SecondArg = InstArg;
+      return TDK_NonDeducedMismatch;
+    }
+  }
+
+  if (Trap.hasErrorOccurred())
+    return TDK_SubstitutionFailure;
+
+  return TDK_Success;
+}
+
+/// \brief Determine whether the given type T is a simple-template-id type.
+static bool isSimpleTemplateIdType(QualType T) {
+  if (const TemplateSpecializationType *Spec
+        = T->getAs<TemplateSpecializationType>())
+    return Spec->getTemplateName().getAsTemplateDecl() != 0;
+
+  return false;
+}
+
+/// \brief Substitute the explicitly-provided template arguments into the
+/// given function template according to C++ [temp.arg.explicit].
+///
+/// \param FunctionTemplate the function template into which the explicit
+/// template arguments will be substituted.
+///
+/// \param ExplicitTemplateArguments the explicitly-specified template
+/// arguments.
+///
+/// \param Deduced the deduced template arguments, which will be populated
+/// with the converted and checked explicit template arguments.
+///
+/// \param ParamTypes will be populated with the instantiated function
+/// parameters.
+///
+/// \param FunctionType if non-NULL, the result type of the function template
+/// will also be instantiated and the pointed-to value will be updated with
+/// the instantiated function type.
+///
+/// \param Info if substitution fails for any reason, this object will be
+/// populated with more information about the failure.
+///
+/// \returns TDK_Success if substitution was successful, or some failure
+/// condition.
+Sema::TemplateDeductionResult
+Sema::SubstituteExplicitTemplateArguments(
+                                      FunctionTemplateDecl *FunctionTemplate,
+                        const TemplateArgumentListInfo &ExplicitTemplateArgs,
+                            llvm::SmallVectorImpl<TemplateArgument> &Deduced,
+                                 llvm::SmallVectorImpl<QualType> &ParamTypes,
+                                          QualType *FunctionType,
+                                          TemplateDeductionInfo &Info) {
+  FunctionDecl *Function = FunctionTemplate->getTemplatedDecl();
+  TemplateParameterList *TemplateParams
+    = FunctionTemplate->getTemplateParameters();
+
+  if (ExplicitTemplateArgs.size() == 0) {
+    // No arguments to substitute; just copy over the parameter types and
+    // fill in the function type.
+    for (FunctionDecl::param_iterator P = Function->param_begin(),
+                                   PEnd = Function->param_end();
+         P != PEnd;
+         ++P)
+      ParamTypes.push_back((*P)->getType());
+
+    if (FunctionType)
+      *FunctionType = Function->getType();
+    return TDK_Success;
+  }
+
+  // Substitution of the explicit template arguments into a function template
+  /// is a SFINAE context. Trap any errors that might occur.
+  SFINAETrap Trap(*this);
+
+  // C++ [temp.arg.explicit]p3:
+  //   Template arguments that are present shall be specified in the
+  //   declaration order of their corresponding template-parameters. The
+  //   template argument list shall not specify more template-arguments than
+  //   there are corresponding template-parameters.
+  TemplateArgumentListBuilder Builder(TemplateParams,
+                                      ExplicitTemplateArgs.size());
+
+  // Enter a new template instantiation context where we check the
+  // explicitly-specified template arguments against this function template,
+  // and then substitute them into the function parameter types.
+  InstantiatingTemplate Inst(*this, FunctionTemplate->getLocation(),
+                             FunctionTemplate, Deduced.data(), Deduced.size(),
+           ActiveTemplateInstantiation::ExplicitTemplateArgumentSubstitution);
+  if (Inst)
+    return TDK_InstantiationDepth;
+
+  if (CheckTemplateArgumentList(FunctionTemplate,
+                                SourceLocation(),
+                                ExplicitTemplateArgs,
+                                true,
+                                Builder) || Trap.hasErrorOccurred())
+    return TDK_InvalidExplicitArguments;
+
+  // Form the template argument list from the explicitly-specified
+  // template arguments.
+  TemplateArgumentList *ExplicitArgumentList
+    = new (Context) TemplateArgumentList(Context, Builder, /*TakeArgs=*/true);
+  Info.reset(ExplicitArgumentList);
+
+  // Instantiate the types of each of the function parameters given the
+  // explicitly-specified template arguments.
+  for (FunctionDecl::param_iterator P = Function->param_begin(),
+                                PEnd = Function->param_end();
+       P != PEnd;
+       ++P) {
+    QualType ParamType
+      = SubstType((*P)->getType(),
+                  MultiLevelTemplateArgumentList(*ExplicitArgumentList),
+                  (*P)->getLocation(), (*P)->getDeclName());
+    if (ParamType.isNull() || Trap.hasErrorOccurred())
+      return TDK_SubstitutionFailure;
+
+    ParamTypes.push_back(ParamType);
+  }
+
+  // If the caller wants a full function type back, instantiate the return
+  // type and form that function type.
+  if (FunctionType) {
+    // FIXME: exception-specifications?
+    const FunctionProtoType *Proto
+      = Function->getType()->getAs<FunctionProtoType>();
+    assert(Proto && "Function template does not have a prototype?");
+
+    QualType ResultType
+      = SubstType(Proto->getResultType(),
+                  MultiLevelTemplateArgumentList(*ExplicitArgumentList),
+                  Function->getTypeSpecStartLoc(),
+                  Function->getDeclName());
+    if (ResultType.isNull() || Trap.hasErrorOccurred())
+      return TDK_SubstitutionFailure;
+
+    *FunctionType = BuildFunctionType(ResultType,
+                                      ParamTypes.data(), ParamTypes.size(),
+                                      Proto->isVariadic(),
+                                      Proto->getTypeQuals(),
+                                      Function->getLocation(),
+                                      Function->getDeclName());
+    if (FunctionType->isNull() || Trap.hasErrorOccurred())
+      return TDK_SubstitutionFailure;
+  }
+
+  // C++ [temp.arg.explicit]p2:
+  //   Trailing template arguments that can be deduced (14.8.2) may be
+  //   omitted from the list of explicit template-arguments. If all of the
+  //   template arguments can be deduced, they may all be omitted; in this
+  //   case, the empty template argument list <> itself may also be omitted.
+  //
+  // Take all of the explicitly-specified arguments and put them into the
+  // set of deduced template arguments.
+  Deduced.reserve(TemplateParams->size());
+  for (unsigned I = 0, N = ExplicitArgumentList->size(); I != N; ++I)
+    Deduced.push_back(ExplicitArgumentList->get(I));
+
+  return TDK_Success;
+}
+
+/// \brief Finish template argument deduction for a function template,
+/// checking the deduced template arguments for completeness and forming
+/// the function template specialization.
+Sema::TemplateDeductionResult
+Sema::FinishTemplateArgumentDeduction(FunctionTemplateDecl *FunctionTemplate,
+                            llvm::SmallVectorImpl<TemplateArgument> &Deduced,
+                                      FunctionDecl *&Specialization,
+                                      TemplateDeductionInfo &Info) {
+  TemplateParameterList *TemplateParams
+    = FunctionTemplate->getTemplateParameters();
+
+  // Template argument deduction for function templates in a SFINAE context.
+  // Trap any errors that might occur.
+  SFINAETrap Trap(*this);
+
+  // Enter a new template instantiation context while we instantiate the
+  // actual function declaration.
+  InstantiatingTemplate Inst(*this, FunctionTemplate->getLocation(),
+                             FunctionTemplate, Deduced.data(), Deduced.size(),
+              ActiveTemplateInstantiation::DeducedTemplateArgumentSubstitution);
+  if (Inst)
+    return TDK_InstantiationDepth;
+
+  // C++ [temp.deduct.type]p2:
+  //   [...] or if any template argument remains neither deduced nor
+  //   explicitly specified, template argument deduction fails.
+  TemplateArgumentListBuilder Builder(TemplateParams, Deduced.size());
+  for (unsigned I = 0, N = Deduced.size(); I != N; ++I) {
+    if (!Deduced[I].isNull()) {
+      Builder.Append(Deduced[I]);
+      continue;
+    }
+
+    // Substitute into the default template argument, if available. 
+    NamedDecl *Param = FunctionTemplate->getTemplateParameters()->getParam(I);
+    TemplateArgumentLoc DefArg
+      = SubstDefaultTemplateArgumentIfAvailable(FunctionTemplate,
+                                              FunctionTemplate->getLocation(),
+                                  FunctionTemplate->getSourceRange().getEnd(),
+                                                Param,
+                                                Builder);
+
+    // If there was no default argument, deduction is incomplete.
+    if (DefArg.getArgument().isNull()) {
+      Info.Param = makeTemplateParameter(
+                         const_cast<NamedDecl *>(TemplateParams->getParam(I)));
+      return TDK_Incomplete;
+    }
+    
+    // Check whether we can actually use the default argument.
+    if (CheckTemplateArgument(Param, DefArg,
+                              FunctionTemplate,
+                              FunctionTemplate->getLocation(),
+                              FunctionTemplate->getSourceRange().getEnd(),
+                              Builder)) {
+      Info.Param = makeTemplateParameter(
+                         const_cast<NamedDecl *>(TemplateParams->getParam(I)));
+      return TDK_SubstitutionFailure;
+    }
+
+    // If we get here, we successfully used the default template argument.
+  }
+
+  // Form the template argument list from the deduced template arguments.
+  TemplateArgumentList *DeducedArgumentList
+    = new (Context) TemplateArgumentList(Context, Builder, /*TakeArgs=*/true);
+  Info.reset(DeducedArgumentList);
+
+  // Substitute the deduced template arguments into the function template
+  // declaration to produce the function template specialization.
+  Specialization = cast_or_null<FunctionDecl>(
+                      SubstDecl(FunctionTemplate->getTemplatedDecl(),
+                                FunctionTemplate->getDeclContext(),
+                         MultiLevelTemplateArgumentList(*DeducedArgumentList)));
+  if (!Specialization)
+    return TDK_SubstitutionFailure;
+
+  assert(Specialization->getPrimaryTemplate()->getCanonicalDecl() == 
+         FunctionTemplate->getCanonicalDecl());
+  
+  // If the template argument list is owned by the function template
+  // specialization, release it.
+  if (Specialization->getTemplateSpecializationArgs() == DeducedArgumentList)
+    Info.take();
+
+  // There may have been an error that did not prevent us from constructing a
+  // declaration. Mark the declaration invalid and return with a substitution
+  // failure.
+  if (Trap.hasErrorOccurred()) {
+    Specialization->setInvalidDecl(true);
+    return TDK_SubstitutionFailure;
+  }
+
+  return TDK_Success;
+}
+
+static QualType GetTypeOfFunction(ASTContext &Context,
+                                  bool isAddressOfOperand,
+                                  FunctionDecl *Fn) {
+  if (!isAddressOfOperand) return Fn->getType();
+  if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(Fn))
+    if (Method->isInstance())
+      return Context.getMemberPointerType(Fn->getType(),
+               Context.getTypeDeclType(Method->getParent()).getTypePtr());
+  return Context.getPointerType(Fn->getType());
+}
+
+/// Apply the deduction rules for overload sets.
+///
+/// \return the null type if this argument should be treated as an
+/// undeduced context
+static QualType
+ResolveOverloadForDeduction(Sema &S, TemplateParameterList *TemplateParams,
+                            Expr *Arg, QualType ParamType) {
+  llvm::PointerIntPair<OverloadExpr*,1> R = OverloadExpr::find(Arg);
+
+  bool isAddressOfOperand = bool(R.getInt());
+  OverloadExpr *Ovl = R.getPointer();
+
+  // If there were explicit template arguments, we can only find
+  // something via C++ [temp.arg.explicit]p3, i.e. if the arguments
+  // unambiguously name a full specialization.
+  if (Ovl->hasExplicitTemplateArgs()) {
+    // But we can still look for an explicit specialization.
+    if (FunctionDecl *ExplicitSpec
+          = S.ResolveSingleFunctionTemplateSpecialization(Ovl))
+      return GetTypeOfFunction(S.Context, isAddressOfOperand, ExplicitSpec);
+    return QualType();
+  }
+
+  // C++0x [temp.deduct.call]p6:
+  //   When P is a function type, pointer to function type, or pointer
+  //   to member function type:
+
+  if (!ParamType->isFunctionType() &&
+      !ParamType->isFunctionPointerType() &&
+      !ParamType->isMemberFunctionPointerType())
+    return QualType();
+
+  QualType Match;
+  for (UnresolvedSetIterator I = Ovl->decls_begin(),
+         E = Ovl->decls_end(); I != E; ++I) {
+    NamedDecl *D = (*I)->getUnderlyingDecl();
+
+    //   - If the argument is an overload set containing one or more
+    //     function templates, the parameter is treated as a
+    //     non-deduced context.
+    if (isa<FunctionTemplateDecl>(D))
+      return QualType();
+
+    FunctionDecl *Fn = cast<FunctionDecl>(D);
+    QualType ArgType = GetTypeOfFunction(S.Context, isAddressOfOperand, Fn);
+
+    //   - If the argument is an overload set (not containing function
+    //     templates), trial argument deduction is attempted using each
+    //     of the members of the set. If deduction succeeds for only one
+    //     of the overload set members, that member is used as the
+    //     argument value for the deduction. If deduction succeeds for
+    //     more than one member of the overload set the parameter is
+    //     treated as a non-deduced context.
+
+    // We do all of this in a fresh context per C++0x [temp.deduct.type]p2:
+    //   Type deduction is done independently for each P/A pair, and
+    //   the deduced template argument values are then combined.
+    // So we do not reject deductions which were made elsewhere.
+    llvm::SmallVector<TemplateArgument, 8> Deduced(TemplateParams->size());
+    Sema::TemplateDeductionInfo Info(S.Context, Ovl->getNameLoc());
+    unsigned TDF = 0;
+
+    Sema::TemplateDeductionResult Result
+      = DeduceTemplateArguments(S, TemplateParams,
+                                ParamType, ArgType,
+                                Info, Deduced, TDF);
+    if (Result) continue;
+    if (!Match.isNull()) return QualType();
+    Match = ArgType;
+  }
+
+  return Match;
+}
+
+/// \brief Perform template argument deduction from a function call
+/// (C++ [temp.deduct.call]).
+///
+/// \param FunctionTemplate the function template for which we are performing
+/// template argument deduction.
+///
+/// \param ExplicitTemplateArguments the explicit template arguments provided
+/// for this call.
+///
+/// \param Args the function call arguments
+///
+/// \param NumArgs the number of arguments in Args
+///
+/// \param Name the name of the function being called. This is only significant
+/// when the function template is a conversion function template, in which
+/// case this routine will also perform template argument deduction based on
+/// the function to which 
+///
+/// \param Specialization if template argument deduction was successful,
+/// this will be set to the function template specialization produced by
+/// template argument deduction.
+///
+/// \param Info the argument will be updated to provide additional information
+/// about template argument deduction.
+///
+/// \returns the result of template argument deduction.
+Sema::TemplateDeductionResult
+Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
+                          const TemplateArgumentListInfo *ExplicitTemplateArgs,
+                              Expr **Args, unsigned NumArgs,
+                              FunctionDecl *&Specialization,
+                              TemplateDeductionInfo &Info) {
+  FunctionDecl *Function = FunctionTemplate->getTemplatedDecl();
+
+  // C++ [temp.deduct.call]p1:
+  //   Template argument deduction is done by comparing each function template
+  //   parameter type (call it P) with the type of the corresponding argument
+  //   of the call (call it A) as described below.
+  unsigned CheckArgs = NumArgs;
+  if (NumArgs < Function->getMinRequiredArguments())
+    return TDK_TooFewArguments;
+  else if (NumArgs > Function->getNumParams()) {
+    const FunctionProtoType *Proto
+      = Function->getType()->getAs<FunctionProtoType>();
+    if (!Proto->isVariadic())
+      return TDK_TooManyArguments;
+
+    CheckArgs = Function->getNumParams();
+  }
+
+  // The types of the parameters from which we will perform template argument
+  // deduction.
+  TemplateParameterList *TemplateParams
+    = FunctionTemplate->getTemplateParameters();
+  llvm::SmallVector<TemplateArgument, 4> Deduced;
+  llvm::SmallVector<QualType, 4> ParamTypes;
+  if (ExplicitTemplateArgs) {
+    TemplateDeductionResult Result =
+      SubstituteExplicitTemplateArguments(FunctionTemplate,
+                                          *ExplicitTemplateArgs,
+                                          Deduced,
+                                          ParamTypes,
+                                          0,
+                                          Info);
+    if (Result)
+      return Result;
+  } else {
+    // Just fill in the parameter types from the function declaration.
+    for (unsigned I = 0; I != CheckArgs; ++I)
+      ParamTypes.push_back(Function->getParamDecl(I)->getType());
+  }
+
+  // Deduce template arguments from the function parameters.
+  Deduced.resize(TemplateParams->size());
+  for (unsigned I = 0; I != CheckArgs; ++I) {
+    QualType ParamType = ParamTypes[I];
+    QualType ArgType = Args[I]->getType();
+
+    // Overload sets usually make this parameter an undeduced
+    // context, but there are sometimes special circumstances.
+    if (ArgType == Context.OverloadTy) {
+      ArgType = ResolveOverloadForDeduction(*this, TemplateParams,
+                                            Args[I], ParamType);
+      if (ArgType.isNull())
+        continue;
+    }
+
+    // C++ [temp.deduct.call]p2:
+    //   If P is not a reference type:
+    QualType CanonParamType = Context.getCanonicalType(ParamType);
+    bool ParamWasReference = isa<ReferenceType>(CanonParamType);
+    if (!ParamWasReference) {
+      //   - If A is an array type, the pointer type produced by the
+      //     array-to-pointer standard conversion (4.2) is used in place of
+      //     A for type deduction; otherwise,
+      if (ArgType->isArrayType())
+        ArgType = Context.getArrayDecayedType(ArgType);
+      //   - If A is a function type, the pointer type produced by the
+      //     function-to-pointer standard conversion (4.3) is used in place
+      //     of A for type deduction; otherwise,
+      else if (ArgType->isFunctionType())
+        ArgType = Context.getPointerType(ArgType);
+      else {
+        // - If A is a cv-qualified type, the top level cv-qualifiers of A’s
+        //   type are ignored for type deduction.
+        QualType CanonArgType = Context.getCanonicalType(ArgType);
+        if (CanonArgType.getLocalCVRQualifiers())
+          ArgType = CanonArgType.getLocalUnqualifiedType();
+      }
+    }
+
+    // C++0x [temp.deduct.call]p3:
+    //   If P is a cv-qualified type, the top level cv-qualifiers of P’s type
+    //   are ignored for type deduction.
+    if (CanonParamType.getLocalCVRQualifiers())
+      ParamType = CanonParamType.getLocalUnqualifiedType();
+    if (const ReferenceType *ParamRefType = ParamType->getAs<ReferenceType>()) {
+      //   [...] If P is a reference type, the type referred to by P is used
+      //   for type deduction.
+      ParamType = ParamRefType->getPointeeType();
+
+      //   [...] If P is of the form T&&, where T is a template parameter, and
+      //   the argument is an lvalue, the type A& is used in place of A for
+      //   type deduction.
+      if (isa<RValueReferenceType>(ParamRefType) &&
+          ParamRefType->getAs<TemplateTypeParmType>() &&
+          Args[I]->isLvalue(Context) == Expr::LV_Valid)
+        ArgType = Context.getLValueReferenceType(ArgType);
+    }
+
+    // C++0x [temp.deduct.call]p4:
+    //   In general, the deduction process attempts to find template argument
+    //   values that will make the deduced A identical to A (after the type A
+    //   is transformed as described above). [...]
+    unsigned TDF = TDF_SkipNonDependent;
+
+    //     - If the original P is a reference type, the deduced A (i.e., the
+    //       type referred to by the reference) can be more cv-qualified than
+    //       the transformed A.
+    if (ParamWasReference)
+      TDF |= TDF_ParamWithReferenceType;
+    //     - The transformed A can be another pointer or pointer to member
+    //       type that can be converted to the deduced A via a qualification
+    //       conversion (4.4).
+    if (ArgType->isPointerType() || ArgType->isMemberPointerType())
+      TDF |= TDF_IgnoreQualifiers;
+    //     - If P is a class and P has the form simple-template-id, then the
+    //       transformed A can be a derived class of the deduced A. Likewise,
+    //       if P is a pointer to a class of the form simple-template-id, the
+    //       transformed A can be a pointer to a derived class pointed to by
+    //       the deduced A.
+    if (isSimpleTemplateIdType(ParamType) ||
+        (isa<PointerType>(ParamType) &&
+         isSimpleTemplateIdType(
+                              ParamType->getAs<PointerType>()->getPointeeType())))
+      TDF |= TDF_DerivedClass;
+
+    if (TemplateDeductionResult Result
+        = ::DeduceTemplateArguments(*this, TemplateParams,
+                                    ParamType, ArgType, Info, Deduced,
+                                    TDF))
+      return Result;
+
+    // FIXME: we need to check that the deduced A is the same as A,
+    // modulo the various allowed differences.
+  }
+
+  return FinishTemplateArgumentDeduction(FunctionTemplate, Deduced,
+                                         Specialization, Info);
+}
+
+/// \brief Deduce template arguments when taking the address of a function
+/// template (C++ [temp.deduct.funcaddr]) or matching a specialization to
+/// a template.
+///
+/// \param FunctionTemplate the function template for which we are performing
+/// template argument deduction.
+///
+/// \param ExplicitTemplateArguments the explicitly-specified template 
+/// arguments.
+///
+/// \param ArgFunctionType the function type that will be used as the
+/// "argument" type (A) when performing template argument deduction from the
+/// function template's function type. This type may be NULL, if there is no
+/// argument type to compare against, in C++0x [temp.arg.explicit]p3.
+///
+/// \param Specialization if template argument deduction was successful,
+/// this will be set to the function template specialization produced by
+/// template argument deduction.
+///
+/// \param Info the argument will be updated to provide additional information
+/// about template argument deduction.
+///
+/// \returns the result of template argument deduction.
+Sema::TemplateDeductionResult
+Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
+                        const TemplateArgumentListInfo *ExplicitTemplateArgs,
+                              QualType ArgFunctionType,
+                              FunctionDecl *&Specialization,
+                              TemplateDeductionInfo &Info) {
+  FunctionDecl *Function = FunctionTemplate->getTemplatedDecl();
+  TemplateParameterList *TemplateParams
+    = FunctionTemplate->getTemplateParameters();
+  QualType FunctionType = Function->getType();
+
+  // Substitute any explicit template arguments.
+  llvm::SmallVector<TemplateArgument, 4> Deduced;
+  llvm::SmallVector<QualType, 4> ParamTypes;
+  if (ExplicitTemplateArgs) {
+    if (TemplateDeductionResult Result
+          = SubstituteExplicitTemplateArguments(FunctionTemplate,
+                                                *ExplicitTemplateArgs,
+                                                Deduced, ParamTypes,
+                                                &FunctionType, Info))
+      return Result;
+  }
+
+  // Template argument deduction for function templates in a SFINAE context.
+  // Trap any errors that might occur.
+  SFINAETrap Trap(*this);
+
+  Deduced.resize(TemplateParams->size());
+
+  if (!ArgFunctionType.isNull()) {
+    // Deduce template arguments from the function type.
+    if (TemplateDeductionResult Result
+          = ::DeduceTemplateArguments(*this, TemplateParams,
+                                      FunctionType, ArgFunctionType, Info,
+                                      Deduced, 0))
+      return Result;
+  }
+  
+  return FinishTemplateArgumentDeduction(FunctionTemplate, Deduced,
+                                         Specialization, Info);
+}
+
+/// \brief Deduce template arguments for a templated conversion
+/// function (C++ [temp.deduct.conv]) and, if successful, produce a
+/// conversion function template specialization.
+Sema::TemplateDeductionResult
+Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
+                              QualType ToType,
+                              CXXConversionDecl *&Specialization,
+                              TemplateDeductionInfo &Info) {
+  CXXConversionDecl *Conv
+    = cast<CXXConversionDecl>(FunctionTemplate->getTemplatedDecl());
+  QualType FromType = Conv->getConversionType();
+
+  // Canonicalize the types for deduction.
+  QualType P = Context.getCanonicalType(FromType);
+  QualType A = Context.getCanonicalType(ToType);
+
+  // C++0x [temp.deduct.conv]p3:
+  //   If P is a reference type, the type referred to by P is used for
+  //   type deduction.
+  if (const ReferenceType *PRef = P->getAs<ReferenceType>())
+    P = PRef->getPointeeType();
+
+  // C++0x [temp.deduct.conv]p3:
+  //   If A is a reference type, the type referred to by A is used
+  //   for type deduction.
+  if (const ReferenceType *ARef = A->getAs<ReferenceType>())
+    A = ARef->getPointeeType();
+  // C++ [temp.deduct.conv]p2:
+  //
+  //   If A is not a reference type:
+  else {
+    assert(!A->isReferenceType() && "Reference types were handled above");
+
+    //   - If P is an array type, the pointer type produced by the
+    //     array-to-pointer standard conversion (4.2) is used in place
+    //     of P for type deduction; otherwise,
+    if (P->isArrayType())
+      P = Context.getArrayDecayedType(P);
+    //   - If P is a function type, the pointer type produced by the
+    //     function-to-pointer standard conversion (4.3) is used in
+    //     place of P for type deduction; otherwise,
+    else if (P->isFunctionType())
+      P = Context.getPointerType(P);
+    //   - If P is a cv-qualified type, the top level cv-qualifiers of
+    //     P’s type are ignored for type deduction.
+    else
+      P = P.getUnqualifiedType();
+
+    // C++0x [temp.deduct.conv]p3:
+    //   If A is a cv-qualified type, the top level cv-qualifiers of A’s
+    //   type are ignored for type deduction.
+    A = A.getUnqualifiedType();
+  }
+
+  // Template argument deduction for function templates in a SFINAE context.
+  // Trap any errors that might occur.
+  SFINAETrap Trap(*this);
+
+  // C++ [temp.deduct.conv]p1:
+  //   Template argument deduction is done by comparing the return
+  //   type of the template conversion function (call it P) with the
+  //   type that is required as the result of the conversion (call it
+  //   A) as described in 14.8.2.4.
+  TemplateParameterList *TemplateParams
+    = FunctionTemplate->getTemplateParameters();
+  llvm::SmallVector<TemplateArgument, 4> Deduced;
+  Deduced.resize(TemplateParams->size());
+
+  // C++0x [temp.deduct.conv]p4:
+  //   In general, the deduction process attempts to find template
+  //   argument values that will make the deduced A identical to
+  //   A. However, there are two cases that allow a difference:
+  unsigned TDF = 0;
+  //     - If the original A is a reference type, A can be more
+  //       cv-qualified than the deduced A (i.e., the type referred to
+  //       by the reference)
+  if (ToType->isReferenceType())
+    TDF |= TDF_ParamWithReferenceType;
+  //     - The deduced A can be another pointer or pointer to member
+  //       type that can be converted to A via a qualification
+  //       conversion.
+  //
+  // (C++0x [temp.deduct.conv]p6 clarifies that this only happens when
+  // both P and A are pointers or member pointers. In this case, we
+  // just ignore cv-qualifiers completely).
+  if ((P->isPointerType() && A->isPointerType()) ||
+      (P->isMemberPointerType() && P->isMemberPointerType()))
+    TDF |= TDF_IgnoreQualifiers;
+  if (TemplateDeductionResult Result
+        = ::DeduceTemplateArguments(*this, TemplateParams,
+                                    P, A, Info, Deduced, TDF))
+    return Result;
+
+  // FIXME: we need to check that the deduced A is the same as A,
+  // modulo the various allowed differences.
+
+  // Finish template argument deduction.
+  FunctionDecl *Spec = 0;
+  TemplateDeductionResult Result
+    = FinishTemplateArgumentDeduction(FunctionTemplate, Deduced, Spec, Info);
+  Specialization = cast_or_null<CXXConversionDecl>(Spec);
+  return Result;
+}
+
+/// \brief Deduce template arguments for a function template when there is
+/// nothing to deduce against (C++0x [temp.arg.explicit]p3).
+///
+/// \param FunctionTemplate the function template for which we are performing
+/// template argument deduction.
+///
+/// \param ExplicitTemplateArguments the explicitly-specified template 
+/// arguments.
+///
+/// \param Specialization if template argument deduction was successful,
+/// this will be set to the function template specialization produced by
+/// template argument deduction.
+///
+/// \param Info the argument will be updated to provide additional information
+/// about template argument deduction.
+///
+/// \returns the result of template argument deduction.
+Sema::TemplateDeductionResult
+Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
+                           const TemplateArgumentListInfo *ExplicitTemplateArgs,
+                              FunctionDecl *&Specialization,
+                              TemplateDeductionInfo &Info) {
+  return DeduceTemplateArguments(FunctionTemplate, ExplicitTemplateArgs,
+                                 QualType(), Specialization, Info);
+}
+
+/// \brief Stores the result of comparing the qualifiers of two types.
+enum DeductionQualifierComparison { 
+  NeitherMoreQualified = 0, 
+  ParamMoreQualified, 
+  ArgMoreQualified 
+};
+
+/// \brief Deduce the template arguments during partial ordering by comparing 
+/// the parameter type and the argument type (C++0x [temp.deduct.partial]).
+///
+/// \param S the semantic analysis object within which we are deducing
+///
+/// \param TemplateParams the template parameters that we are deducing
+///
+/// \param ParamIn the parameter type
+///
+/// \param ArgIn the argument type
+///
+/// \param Info information about the template argument deduction itself
+///
+/// \param Deduced the deduced template arguments
+///
+/// \returns the result of template argument deduction so far. Note that a
+/// "success" result means that template argument deduction has not yet failed,
+/// but it may still fail, later, for other reasons.
+static Sema::TemplateDeductionResult
+DeduceTemplateArgumentsDuringPartialOrdering(Sema &S,
+                                          TemplateParameterList *TemplateParams,
+                                             QualType ParamIn, QualType ArgIn,
+                                             Sema::TemplateDeductionInfo &Info,
+                             llvm::SmallVectorImpl<TemplateArgument> &Deduced,
+    llvm::SmallVectorImpl<DeductionQualifierComparison> *QualifierComparisons) {
+  CanQualType Param = S.Context.getCanonicalType(ParamIn);
+  CanQualType Arg = S.Context.getCanonicalType(ArgIn);
+
+  // C++0x [temp.deduct.partial]p5:
+  //   Before the partial ordering is done, certain transformations are 
+  //   performed on the types used for partial ordering: 
+  //     - If P is a reference type, P is replaced by the type referred to. 
+  CanQual<ReferenceType> ParamRef = Param->getAs<ReferenceType>();
+  if (!ParamRef.isNull())
+    Param = ParamRef->getPointeeType();
+  
+  //     - If A is a reference type, A is replaced by the type referred to.
+  CanQual<ReferenceType> ArgRef = Arg->getAs<ReferenceType>();
+  if (!ArgRef.isNull())
+    Arg = ArgRef->getPointeeType();
+  
+  if (QualifierComparisons && !ParamRef.isNull() && !ArgRef.isNull()) {
+    // C++0x [temp.deduct.partial]p6:
+    //   If both P and A were reference types (before being replaced with the 
+    //   type referred to above), determine which of the two types (if any) is 
+    //   more cv-qualified than the other; otherwise the types are considered to 
+    //   be equally cv-qualified for partial ordering purposes. The result of this
+    //   determination will be used below.
+    //
+    // We save this information for later, using it only when deduction 
+    // succeeds in both directions.
+    DeductionQualifierComparison QualifierResult = NeitherMoreQualified;
+    if (Param.isMoreQualifiedThan(Arg))
+      QualifierResult = ParamMoreQualified;
+    else if (Arg.isMoreQualifiedThan(Param))
+      QualifierResult = ArgMoreQualified;
+    QualifierComparisons->push_back(QualifierResult);
+  }
+  
+  // C++0x [temp.deduct.partial]p7:
+  //   Remove any top-level cv-qualifiers:
+  //     - If P is a cv-qualified type, P is replaced by the cv-unqualified 
+  //       version of P.
+  Param = Param.getUnqualifiedType();
+  //     - If A is a cv-qualified type, A is replaced by the cv-unqualified 
+  //       version of A.
+  Arg = Arg.getUnqualifiedType();
+  
+  // C++0x [temp.deduct.partial]p8:
+  //   Using the resulting types P and A the deduction is then done as 
+  //   described in 14.9.2.5. If deduction succeeds for a given type, the type
+  //   from the argument template is considered to be at least as specialized
+  //   as the type from the parameter template.
+  return DeduceTemplateArguments(S, TemplateParams, Param, Arg, Info,
+                                 Deduced, TDF_None);
+}
+
+static void
+MarkUsedTemplateParameters(Sema &SemaRef, QualType T,
+                           bool OnlyDeduced,
+                           unsigned Level,
+                           llvm::SmallVectorImpl<bool> &Deduced);
+  
+/// \brief Determine whether the function template \p FT1 is at least as
+/// specialized as \p FT2.
+static bool isAtLeastAsSpecializedAs(Sema &S,
+                                     SourceLocation Loc,
+                                     FunctionTemplateDecl *FT1,
+                                     FunctionTemplateDecl *FT2,
+                                     TemplatePartialOrderingContext TPOC,
+    llvm::SmallVectorImpl<DeductionQualifierComparison> *QualifierComparisons) {
+  FunctionDecl *FD1 = FT1->getTemplatedDecl();
+  FunctionDecl *FD2 = FT2->getTemplatedDecl();  
+  const FunctionProtoType *Proto1 = FD1->getType()->getAs<FunctionProtoType>();
+  const FunctionProtoType *Proto2 = FD2->getType()->getAs<FunctionProtoType>();
+  
+  assert(Proto1 && Proto2 && "Function templates must have prototypes");
+  TemplateParameterList *TemplateParams = FT2->getTemplateParameters();
+  llvm::SmallVector<TemplateArgument, 4> Deduced;
+  Deduced.resize(TemplateParams->size());
+
+  // C++0x [temp.deduct.partial]p3:
+  //   The types used to determine the ordering depend on the context in which
+  //   the partial ordering is done:
+  Sema::TemplateDeductionInfo Info(S.Context, Loc);
+  switch (TPOC) {
+  case TPOC_Call: {
+    //   - In the context of a function call, the function parameter types are
+    //     used.
+    unsigned NumParams = std::min(Proto1->getNumArgs(), Proto2->getNumArgs());
+    for (unsigned I = 0; I != NumParams; ++I)
+      if (DeduceTemplateArgumentsDuringPartialOrdering(S,
+                                                       TemplateParams,
+                                                       Proto2->getArgType(I),
+                                                       Proto1->getArgType(I),
+                                                       Info,
+                                                       Deduced,
+                                                       QualifierComparisons))
+        return false;
+    
+    break;
+  }
+    
+  case TPOC_Conversion:
+    //   - In the context of a call to a conversion operator, the return types
+    //     of the conversion function templates are used.
+    if (DeduceTemplateArgumentsDuringPartialOrdering(S,
+                                                     TemplateParams,
+                                                     Proto2->getResultType(),
+                                                     Proto1->getResultType(),
+                                                     Info,
+                                                     Deduced,
+                                                     QualifierComparisons))
+      return false;
+    break;
+    
+  case TPOC_Other:
+    //   - In other contexts (14.6.6.2) the function template’s function type 
+    //     is used.
+    if (DeduceTemplateArgumentsDuringPartialOrdering(S,
+                                                     TemplateParams,
+                                                     FD2->getType(),
+                                                     FD1->getType(),
+                                                     Info,
+                                                     Deduced,
+                                                     QualifierComparisons))
+      return false;
+    break;
+  }
+  
+  // C++0x [temp.deduct.partial]p11:
+  //   In most cases, all template parameters must have values in order for 
+  //   deduction to succeed, but for partial ordering purposes a template 
+  //   parameter may remain without a value provided it is not used in the 
+  //   types being used for partial ordering. [ Note: a template parameter used
+  //   in a non-deduced context is considered used. -end note]
+  unsigned ArgIdx = 0, NumArgs = Deduced.size();
+  for (; ArgIdx != NumArgs; ++ArgIdx)
+    if (Deduced[ArgIdx].isNull())
+      break;
+
+  if (ArgIdx == NumArgs) {
+    // All template arguments were deduced. FT1 is at least as specialized 
+    // as FT2.
+    return true;
+  }
+
+  // Figure out which template parameters were used.
+  llvm::SmallVector<bool, 4> UsedParameters;
+  UsedParameters.resize(TemplateParams->size());
+  switch (TPOC) {
+  case TPOC_Call: {
+    unsigned NumParams = std::min(Proto1->getNumArgs(), Proto2->getNumArgs());
+    for (unsigned I = 0; I != NumParams; ++I)
+      ::MarkUsedTemplateParameters(S, Proto2->getArgType(I), false, 
+                                   TemplateParams->getDepth(),
+                                   UsedParameters);
+    break;
+  }
+    
+  case TPOC_Conversion:
+    ::MarkUsedTemplateParameters(S, Proto2->getResultType(), false, 
+                                 TemplateParams->getDepth(),
+                                 UsedParameters);
+    break;
+    
+  case TPOC_Other:
+    ::MarkUsedTemplateParameters(S, FD2->getType(), false, 
+                                 TemplateParams->getDepth(),
+                                 UsedParameters);
+    break;
+  }
+  
+  for (; ArgIdx != NumArgs; ++ArgIdx)
+    // If this argument had no value deduced but was used in one of the types
+    // used for partial ordering, then deduction fails.
+    if (Deduced[ArgIdx].isNull() && UsedParameters[ArgIdx])
+      return false;
+  
+  return true;
+}
+                                    
+                                     
+/// \brief Returns the more specialized function template according
+/// to the rules of function template partial ordering (C++ [temp.func.order]).
+///
+/// \param FT1 the first function template
+///
+/// \param FT2 the second function template
+///
+/// \param TPOC the context in which we are performing partial ordering of
+/// function templates.
+///
+/// \returns the more specialized function template. If neither
+/// template is more specialized, returns NULL.
+FunctionTemplateDecl *
+Sema::getMoreSpecializedTemplate(FunctionTemplateDecl *FT1,
+                                 FunctionTemplateDecl *FT2,
+                                 SourceLocation Loc,
+                                 TemplatePartialOrderingContext TPOC) {
+  llvm::SmallVector<DeductionQualifierComparison, 4> QualifierComparisons;
+  bool Better1 = isAtLeastAsSpecializedAs(*this, Loc, FT1, FT2, TPOC, 0);
+  bool Better2 = isAtLeastAsSpecializedAs(*this, Loc, FT2, FT1, TPOC, 
+                                          &QualifierComparisons);
+  
+  if (Better1 != Better2) // We have a clear winner
+    return Better1? FT1 : FT2;
+  
+  if (!Better1 && !Better2) // Neither is better than the other
+    return 0;
+
+
+  // C++0x [temp.deduct.partial]p10:
+  //   If for each type being considered a given template is at least as 
+  //   specialized for all types and more specialized for some set of types and
+  //   the other template is not more specialized for any types or is not at 
+  //   least as specialized for any types, then the given template is more
+  //   specialized than the other template. Otherwise, neither template is more
+  //   specialized than the other.
+  Better1 = false;
+  Better2 = false;
+  for (unsigned I = 0, N = QualifierComparisons.size(); I != N; ++I) {
+    // C++0x [temp.deduct.partial]p9:
+    //   If, for a given type, deduction succeeds in both directions (i.e., the
+    //   types are identical after the transformations above) and if the type
+    //   from the argument template is more cv-qualified than the type from the
+    //   parameter template (as described above) that type is considered to be
+    //   more specialized than the other. If neither type is more cv-qualified 
+    //   than the other then neither type is more specialized than the other.
+    switch (QualifierComparisons[I]) {
+      case NeitherMoreQualified:
+        break;
+        
+      case ParamMoreQualified:
+        Better1 = true;
+        if (Better2)
+          return 0;
+        break;
+        
+      case ArgMoreQualified:
+        Better2 = true;
+        if (Better1)
+          return 0;
+        break;
+    }
+  }
+   
+  assert(!(Better1 && Better2) && "Should have broken out in the loop above");
+  if (Better1)
+    return FT1;
+  else if (Better2)
+    return FT2;
+  else
+    return 0;
+}
+
+/// \brief Determine if the two templates are equivalent.
+static bool isSameTemplate(TemplateDecl *T1, TemplateDecl *T2) {
+  if (T1 == T2)
+    return true;
+  
+  if (!T1 || !T2)
+    return false;
+  
+  return T1->getCanonicalDecl() == T2->getCanonicalDecl();
+}
+
+/// \brief Retrieve the most specialized of the given function template
+/// specializations.
+///
+/// \param SpecBegin the start iterator of the function template
+/// specializations that we will be comparing.
+///
+/// \param SpecEnd the end iterator of the function template
+/// specializations, paired with \p SpecBegin.
+///
+/// \param TPOC the partial ordering context to use to compare the function
+/// template specializations.
+///
+/// \param Loc the location where the ambiguity or no-specializations 
+/// diagnostic should occur.
+///
+/// \param NoneDiag partial diagnostic used to diagnose cases where there are
+/// no matching candidates.
+///
+/// \param AmbigDiag partial diagnostic used to diagnose an ambiguity, if one
+/// occurs.
+///
+/// \param CandidateDiag partial diagnostic used for each function template
+/// specialization that is a candidate in the ambiguous ordering. One parameter
+/// in this diagnostic should be unbound, which will correspond to the string
+/// describing the template arguments for the function template specialization.
+///
+/// \param Index if non-NULL and the result of this function is non-nULL, 
+/// receives the index corresponding to the resulting function template
+/// specialization.
+///
+/// \returns the most specialized function template specialization, if 
+/// found. Otherwise, returns SpecEnd.
+///
+/// \todo FIXME: Consider passing in the "also-ran" candidates that failed 
+/// template argument deduction.
+UnresolvedSetIterator
+Sema::getMostSpecialized(UnresolvedSetIterator SpecBegin,
+                         UnresolvedSetIterator SpecEnd,
+                         TemplatePartialOrderingContext TPOC,
+                         SourceLocation Loc,
+                         const PartialDiagnostic &NoneDiag,
+                         const PartialDiagnostic &AmbigDiag,
+                         const PartialDiagnostic &CandidateDiag) {
+  if (SpecBegin == SpecEnd) {
+    Diag(Loc, NoneDiag);
+    return SpecEnd;
+  }
+  
+  if (SpecBegin + 1 == SpecEnd)    
+    return SpecBegin;
+  
+  // Find the function template that is better than all of the templates it
+  // has been compared to.
+  UnresolvedSetIterator Best = SpecBegin;
+  FunctionTemplateDecl *BestTemplate 
+    = cast<FunctionDecl>(*Best)->getPrimaryTemplate();
+  assert(BestTemplate && "Not a function template specialization?");
+  for (UnresolvedSetIterator I = SpecBegin + 1; I != SpecEnd; ++I) {
+    FunctionTemplateDecl *Challenger
+      = cast<FunctionDecl>(*I)->getPrimaryTemplate();
+    assert(Challenger && "Not a function template specialization?");
+    if (isSameTemplate(getMoreSpecializedTemplate(BestTemplate, Challenger,
+                                                  Loc, TPOC),
+                       Challenger)) {
+      Best = I;
+      BestTemplate = Challenger;
+    }
+  }
+  
+  // Make sure that the "best" function template is more specialized than all
+  // of the others.
+  bool Ambiguous = false;
+  for (UnresolvedSetIterator I = SpecBegin; I != SpecEnd; ++I) {
+    FunctionTemplateDecl *Challenger
+      = cast<FunctionDecl>(*I)->getPrimaryTemplate();
+    if (I != Best &&
+        !isSameTemplate(getMoreSpecializedTemplate(BestTemplate, Challenger, 
+                                                   Loc, TPOC),
+                        BestTemplate)) {
+      Ambiguous = true;
+      break;
+    }
+  }
+  
+  if (!Ambiguous) {
+    // We found an answer. Return it.
+    return Best;
+  }
+  
+  // Diagnose the ambiguity.
+  Diag(Loc, AmbigDiag);
+  
+  // FIXME: Can we order the candidates in some sane way?
+  for (UnresolvedSetIterator I = SpecBegin; I != SpecEnd; ++I)
+    Diag((*I)->getLocation(), CandidateDiag)
+      << getTemplateArgumentBindingsText(
+        cast<FunctionDecl>(*I)->getPrimaryTemplate()->getTemplateParameters(),
+                    *cast<FunctionDecl>(*I)->getTemplateSpecializationArgs());
+  
+  return SpecEnd;
+}
+
+/// \brief Returns the more specialized class template partial specialization
+/// according to the rules of partial ordering of class template partial
+/// specializations (C++ [temp.class.order]).
+///
+/// \param PS1 the first class template partial specialization
+///
+/// \param PS2 the second class template partial specialization
+///
+/// \returns the more specialized class template partial specialization. If
+/// neither partial specialization is more specialized, returns NULL.
+ClassTemplatePartialSpecializationDecl *
+Sema::getMoreSpecializedPartialSpecialization(
+                                  ClassTemplatePartialSpecializationDecl *PS1,
+                                  ClassTemplatePartialSpecializationDecl *PS2,
+                                              SourceLocation Loc) {
+  // C++ [temp.class.order]p1:
+  //   For two class template partial specializations, the first is at least as
+  //   specialized as the second if, given the following rewrite to two 
+  //   function templates, the first function template is at least as 
+  //   specialized as the second according to the ordering rules for function 
+  //   templates (14.6.6.2):
+  //     - the first function template has the same template parameters as the
+  //       first partial specialization and has a single function parameter 
+  //       whose type is a class template specialization with the template 
+  //       arguments of the first partial specialization, and
+  //     - the second function template has the same template parameters as the
+  //       second partial specialization and has a single function parameter 
+  //       whose type is a class template specialization with the template 
+  //       arguments of the second partial specialization.
+  //
+  // Rather than synthesize function templates, we merely perform the 
+  // equivalent partial ordering by performing deduction directly on the
+  // template arguments of the class template partial specializations. This
+  // computation is slightly simpler than the general problem of function
+  // template partial ordering, because class template partial specializations
+  // are more constrained. We know that every template parameter is deduc
+  llvm::SmallVector<TemplateArgument, 4> Deduced;
+  Sema::TemplateDeductionInfo Info(Context, Loc);
+  
+  // Determine whether PS1 is at least as specialized as PS2
+  Deduced.resize(PS2->getTemplateParameters()->size());
+  bool Better1 = !DeduceTemplateArgumentsDuringPartialOrdering(*this,
+                                                  PS2->getTemplateParameters(),
+                                                  Context.getTypeDeclType(PS2),
+                                                  Context.getTypeDeclType(PS1),
+                                                               Info,
+                                                               Deduced,
+                                                               0);
+
+  // Determine whether PS2 is at least as specialized as PS1
+  Deduced.clear();
+  Deduced.resize(PS1->getTemplateParameters()->size());
+  bool Better2 = !DeduceTemplateArgumentsDuringPartialOrdering(*this,
+                                                  PS1->getTemplateParameters(),
+                                                  Context.getTypeDeclType(PS1),
+                                                  Context.getTypeDeclType(PS2),
+                                                               Info,
+                                                               Deduced,
+                                                               0);
+  
+  if (Better1 == Better2)
+    return 0;
+  
+  return Better1? PS1 : PS2;
+}
+
+static void
+MarkUsedTemplateParameters(Sema &SemaRef,
+                           const TemplateArgument &TemplateArg,
+                           bool OnlyDeduced,
+                           unsigned Depth,
+                           llvm::SmallVectorImpl<bool> &Used);
+
+/// \brief Mark the template parameters that are used by the given
+/// expression.
+static void
+MarkUsedTemplateParameters(Sema &SemaRef,
+                           const Expr *E,
+                           bool OnlyDeduced,
+                           unsigned Depth,
+                           llvm::SmallVectorImpl<bool> &Used) {
+  // FIXME: if !OnlyDeduced, we have to walk the whole subexpression to 
+  // find other occurrences of template parameters.
+  const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E);
+  if (!DRE)
+    return;
+
+  const NonTypeTemplateParmDecl *NTTP
+    = dyn_cast<NonTypeTemplateParmDecl>(DRE->getDecl());
+  if (!NTTP)
+    return;
+
+  if (NTTP->getDepth() == Depth)
+    Used[NTTP->getIndex()] = true;
+}
+
+/// \brief Mark the template parameters that are used by the given
+/// nested name specifier.
+static void
+MarkUsedTemplateParameters(Sema &SemaRef,
+                           NestedNameSpecifier *NNS,
+                           bool OnlyDeduced,
+                           unsigned Depth,
+                           llvm::SmallVectorImpl<bool> &Used) {
+  if (!NNS)
+    return;
+  
+  MarkUsedTemplateParameters(SemaRef, NNS->getPrefix(), OnlyDeduced, Depth,
+                             Used);
+  MarkUsedTemplateParameters(SemaRef, QualType(NNS->getAsType(), 0), 
+                             OnlyDeduced, Depth, Used);
+}
+  
+/// \brief Mark the template parameters that are used by the given
+/// template name.
+static void
+MarkUsedTemplateParameters(Sema &SemaRef,
+                           TemplateName Name,
+                           bool OnlyDeduced,
+                           unsigned Depth,
+                           llvm::SmallVectorImpl<bool> &Used) {
+  if (TemplateDecl *Template = Name.getAsTemplateDecl()) {
+    if (TemplateTemplateParmDecl *TTP
+          = dyn_cast<TemplateTemplateParmDecl>(Template)) {
+      if (TTP->getDepth() == Depth)
+        Used[TTP->getIndex()] = true;
+    }
+    return;
+  }
+  
+  if (QualifiedTemplateName *QTN = Name.getAsQualifiedTemplateName())
+    MarkUsedTemplateParameters(SemaRef, QTN->getQualifier(), OnlyDeduced, 
+                               Depth, Used);
+  if (DependentTemplateName *DTN = Name.getAsDependentTemplateName())
+    MarkUsedTemplateParameters(SemaRef, DTN->getQualifier(), OnlyDeduced, 
+                               Depth, Used);
+}
+
+/// \brief Mark the template parameters that are used by the given
+/// type.
+static void
+MarkUsedTemplateParameters(Sema &SemaRef, QualType T,
+                           bool OnlyDeduced,
+                           unsigned Depth,
+                           llvm::SmallVectorImpl<bool> &Used) {
+  if (T.isNull())
+    return;
+  
+  // Non-dependent types have nothing deducible
+  if (!T->isDependentType())
+    return;
+
+  T = SemaRef.Context.getCanonicalType(T);
+  switch (T->getTypeClass()) {
+  case Type::Pointer:
+    MarkUsedTemplateParameters(SemaRef,
+                               cast<PointerType>(T)->getPointeeType(),
+                               OnlyDeduced,
+                               Depth,
+                               Used);
+    break;
+
+  case Type::BlockPointer:
+    MarkUsedTemplateParameters(SemaRef,
+                               cast<BlockPointerType>(T)->getPointeeType(),
+                               OnlyDeduced,
+                               Depth,
+                               Used);
+    break;
+
+  case Type::LValueReference:
+  case Type::RValueReference:
+    MarkUsedTemplateParameters(SemaRef,
+                               cast<ReferenceType>(T)->getPointeeType(),
+                               OnlyDeduced,
+                               Depth,
+                               Used);
+    break;
+
+  case Type::MemberPointer: {
+    const MemberPointerType *MemPtr = cast<MemberPointerType>(T.getTypePtr());
+    MarkUsedTemplateParameters(SemaRef, MemPtr->getPointeeType(), OnlyDeduced,
+                               Depth, Used);
+    MarkUsedTemplateParameters(SemaRef, QualType(MemPtr->getClass(), 0),
+                               OnlyDeduced, Depth, Used);
+    break;
+  }
+
+  case Type::DependentSizedArray:
+    MarkUsedTemplateParameters(SemaRef,
+                               cast<DependentSizedArrayType>(T)->getSizeExpr(),
+                               OnlyDeduced, Depth, Used);
+    // Fall through to check the element type
+
+  case Type::ConstantArray:
+  case Type::IncompleteArray:
+    MarkUsedTemplateParameters(SemaRef,
+                               cast<ArrayType>(T)->getElementType(),
+                               OnlyDeduced, Depth, Used);
+    break;
+
+  case Type::Vector:
+  case Type::ExtVector:
+    MarkUsedTemplateParameters(SemaRef,
+                               cast<VectorType>(T)->getElementType(),
+                               OnlyDeduced, Depth, Used);
+    break;
+
+  case Type::DependentSizedExtVector: {
+    const DependentSizedExtVectorType *VecType
+      = cast<DependentSizedExtVectorType>(T);
+    MarkUsedTemplateParameters(SemaRef, VecType->getElementType(), OnlyDeduced,
+                               Depth, Used);
+    MarkUsedTemplateParameters(SemaRef, VecType->getSizeExpr(), OnlyDeduced, 
+                               Depth, Used);
+    break;
+  }
+
+  case Type::FunctionProto: {
+    const FunctionProtoType *Proto = cast<FunctionProtoType>(T);
+    MarkUsedTemplateParameters(SemaRef, Proto->getResultType(), OnlyDeduced,
+                               Depth, Used);
+    for (unsigned I = 0, N = Proto->getNumArgs(); I != N; ++I)
+      MarkUsedTemplateParameters(SemaRef, Proto->getArgType(I), OnlyDeduced,
+                                 Depth, Used);
+    break;
+  }
+
+  case Type::TemplateTypeParm: {
+    const TemplateTypeParmType *TTP = cast<TemplateTypeParmType>(T);
+    if (TTP->getDepth() == Depth)
+      Used[TTP->getIndex()] = true;
+    break;
+  }
+
+  case Type::TemplateSpecialization: {
+    const TemplateSpecializationType *Spec
+      = cast<TemplateSpecializationType>(T);
+    MarkUsedTemplateParameters(SemaRef, Spec->getTemplateName(), OnlyDeduced,
+                               Depth, Used);
+    for (unsigned I = 0, N = Spec->getNumArgs(); I != N; ++I)
+      MarkUsedTemplateParameters(SemaRef, Spec->getArg(I), OnlyDeduced, Depth,
+                                 Used);
+    break;
+  }
+
+  case Type::Complex:
+    if (!OnlyDeduced)
+      MarkUsedTemplateParameters(SemaRef, 
+                                 cast<ComplexType>(T)->getElementType(),
+                                 OnlyDeduced, Depth, Used);
+    break;
+
+  case Type::Typename:
+    if (!OnlyDeduced)
+      MarkUsedTemplateParameters(SemaRef,
+                                 cast<TypenameType>(T)->getQualifier(),
+                                 OnlyDeduced, Depth, Used);
+    break;
+
+  // None of these types have any template parameters in them.
+  case Type::Builtin:
+  case Type::VariableArray:
+  case Type::FunctionNoProto:
+  case Type::Record:
+  case Type::Enum:
+  case Type::ObjCInterface:
+  case Type::ObjCObjectPointer:
+  case Type::UnresolvedUsing:
+#define TYPE(Class, Base)
+#define ABSTRACT_TYPE(Class, Base)
+#define DEPENDENT_TYPE(Class, Base)
+#define NON_CANONICAL_TYPE(Class, Base) case Type::Class:
+#include "clang/AST/TypeNodes.def"
+    break;
+  }
+}
+
+/// \brief Mark the template parameters that are used by this
+/// template argument.
+static void
+MarkUsedTemplateParameters(Sema &SemaRef,
+                           const TemplateArgument &TemplateArg,
+                           bool OnlyDeduced,
+                           unsigned Depth,
+                           llvm::SmallVectorImpl<bool> &Used) {
+  switch (TemplateArg.getKind()) {
+  case TemplateArgument::Null:
+  case TemplateArgument::Integral:
+    case TemplateArgument::Declaration:
+    break;
+
+  case TemplateArgument::Type:
+    MarkUsedTemplateParameters(SemaRef, TemplateArg.getAsType(), OnlyDeduced,
+                               Depth, Used);
+    break;
+
+  case TemplateArgument::Template:
+    MarkUsedTemplateParameters(SemaRef, TemplateArg.getAsTemplate(), 
+                               OnlyDeduced, Depth, Used);
+    break;
+
+  case TemplateArgument::Expression:
+    MarkUsedTemplateParameters(SemaRef, TemplateArg.getAsExpr(), OnlyDeduced, 
+                               Depth, Used);
+    break;
+      
+  case TemplateArgument::Pack:
+    for (TemplateArgument::pack_iterator P = TemplateArg.pack_begin(),
+                                      PEnd = TemplateArg.pack_end();
+         P != PEnd; ++P)
+      MarkUsedTemplateParameters(SemaRef, *P, OnlyDeduced, Depth, Used);
+    break;
+  }
+}
+
+/// \brief Mark the template parameters can be deduced by the given
+/// template argument list.
+///
+/// \param TemplateArgs the template argument list from which template
+/// parameters will be deduced.
+///
+/// \param Deduced a bit vector whose elements will be set to \c true
+/// to indicate when the corresponding template parameter will be
+/// deduced.
+void
+Sema::MarkUsedTemplateParameters(const TemplateArgumentList &TemplateArgs,
+                                 bool OnlyDeduced, unsigned Depth,
+                                 llvm::SmallVectorImpl<bool> &Used) {
+  for (unsigned I = 0, N = TemplateArgs.size(); I != N; ++I)
+    ::MarkUsedTemplateParameters(*this, TemplateArgs[I], OnlyDeduced, 
+                                 Depth, Used);
+}
+
+/// \brief Marks all of the template parameters that will be deduced by a
+/// call to the given function template.
+void Sema::MarkDeducedTemplateParameters(FunctionTemplateDecl *FunctionTemplate,
+                                         llvm::SmallVectorImpl<bool> &Deduced) {
+  TemplateParameterList *TemplateParams 
+    = FunctionTemplate->getTemplateParameters();
+  Deduced.clear();
+  Deduced.resize(TemplateParams->size());
+  
+  FunctionDecl *Function = FunctionTemplate->getTemplatedDecl();
+  for (unsigned I = 0, N = Function->getNumParams(); I != N; ++I)
+    ::MarkUsedTemplateParameters(*this, Function->getParamDecl(I)->getType(),
+                                 true, TemplateParams->getDepth(), Deduced);
+}
diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp
new file mode 100644
index 0000000..99c1de6
--- /dev/null
+++ b/lib/Sema/SemaTemplateInstantiate.cpp
@@ -0,0 +1,1496 @@
+//===------- SemaTemplateInstantiate.cpp - C++ Template Instantiation ------===/
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//===----------------------------------------------------------------------===/
+//
+//  This file implements C++ template instantiation.
+//
+//===----------------------------------------------------------------------===/
+
+#include "Sema.h"
+#include "TreeTransform.h"
+#include "Lookup.h"
+#include "clang/AST/ASTConsumer.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/DeclTemplate.h"
+#include "clang/Parse/DeclSpec.h"
+#include "clang/Basic/LangOptions.h"
+
+using namespace clang;
+
+//===----------------------------------------------------------------------===/
+// Template Instantiation Support
+//===----------------------------------------------------------------------===/
+
+/// \brief Retrieve the template argument list(s) that should be used to
+/// instantiate the definition of the given declaration.
+///
+/// \param D the declaration for which we are computing template instantiation
+/// arguments.
+///
+/// \param Innermost if non-NULL, the innermost template argument list.
+///
+/// \param RelativeToPrimary true if we should get the template
+/// arguments relative to the primary template, even when we're
+/// dealing with a specialization. This is only relevant for function
+/// template specializations.
+MultiLevelTemplateArgumentList
+Sema::getTemplateInstantiationArgs(NamedDecl *D, 
+                                   const TemplateArgumentList *Innermost,
+                                   bool RelativeToPrimary) {
+  // Accumulate the set of template argument lists in this structure.
+  MultiLevelTemplateArgumentList Result;
+
+  if (Innermost)
+    Result.addOuterTemplateArguments(Innermost);
+  
+  DeclContext *Ctx = dyn_cast<DeclContext>(D);
+  if (!Ctx)
+    Ctx = D->getDeclContext();
+
+  while (!Ctx->isFileContext()) {
+    // Add template arguments from a class template instantiation.
+    if (ClassTemplateSpecializationDecl *Spec
+          = dyn_cast<ClassTemplateSpecializationDecl>(Ctx)) {
+      // We're done when we hit an explicit specialization.
+      if (Spec->getSpecializationKind() == TSK_ExplicitSpecialization)
+        break;
+
+      Result.addOuterTemplateArguments(&Spec->getTemplateInstantiationArgs());
+      
+      // If this class template specialization was instantiated from a 
+      // specialized member that is a class template, we're done.
+      assert(Spec->getSpecializedTemplate() && "No class template?");
+      if (Spec->getSpecializedTemplate()->isMemberSpecialization())
+        break;
+    }
+    // Add template arguments from a function template specialization.
+    else if (FunctionDecl *Function = dyn_cast<FunctionDecl>(Ctx)) {
+      if (!RelativeToPrimary &&
+          Function->getTemplateSpecializationKind() 
+                                                  == TSK_ExplicitSpecialization)
+        break;
+          
+      if (const TemplateArgumentList *TemplateArgs
+            = Function->getTemplateSpecializationArgs()) {
+        // Add the template arguments for this specialization.
+        Result.addOuterTemplateArguments(TemplateArgs);
+
+        // If this function was instantiated from a specialized member that is
+        // a function template, we're done.
+        assert(Function->getPrimaryTemplate() && "No function template?");
+        if (Function->getPrimaryTemplate()->isMemberSpecialization())
+          break;
+      }
+      
+      // If this is a friend declaration and it declares an entity at
+      // namespace scope, take arguments from its lexical parent
+      // instead of its semantic parent.
+      if (Function->getFriendObjectKind() &&
+          Function->getDeclContext()->isFileContext()) {
+        Ctx = Function->getLexicalDeclContext();
+        RelativeToPrimary = false;
+        continue;
+      }
+    }
+
+    Ctx = Ctx->getParent();
+    RelativeToPrimary = false;
+  }
+
+  return Result;
+}
+
+bool Sema::ActiveTemplateInstantiation::isInstantiationRecord() const {
+  switch (Kind) {
+  case TemplateInstantiation:
+  case DefaultTemplateArgumentInstantiation:
+  case DefaultFunctionArgumentInstantiation:
+    return true;
+      
+  case ExplicitTemplateArgumentSubstitution:
+  case DeducedTemplateArgumentSubstitution:
+  case PriorTemplateArgumentSubstitution:
+  case DefaultTemplateArgumentChecking:
+    return false;
+  }
+  
+  return true;
+}
+
+Sema::InstantiatingTemplate::
+InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
+                      Decl *Entity,
+                      SourceRange InstantiationRange)
+  :  SemaRef(SemaRef) {
+
+  Invalid = CheckInstantiationDepth(PointOfInstantiation,
+                                    InstantiationRange);
+  if (!Invalid) {
+    ActiveTemplateInstantiation Inst;
+    Inst.Kind = ActiveTemplateInstantiation::TemplateInstantiation;
+    Inst.PointOfInstantiation = PointOfInstantiation;
+    Inst.Entity = reinterpret_cast<uintptr_t>(Entity);
+    Inst.TemplateArgs = 0;
+    Inst.NumTemplateArgs = 0;
+    Inst.InstantiationRange = InstantiationRange;
+    SemaRef.ActiveTemplateInstantiations.push_back(Inst);
+  }
+}
+
+Sema::InstantiatingTemplate::InstantiatingTemplate(Sema &SemaRef,
+                                         SourceLocation PointOfInstantiation,
+                                         TemplateDecl *Template,
+                                         const TemplateArgument *TemplateArgs,
+                                         unsigned NumTemplateArgs,
+                                         SourceRange InstantiationRange)
+  : SemaRef(SemaRef) {
+
+  Invalid = CheckInstantiationDepth(PointOfInstantiation,
+                                    InstantiationRange);
+  if (!Invalid) {
+    ActiveTemplateInstantiation Inst;
+    Inst.Kind
+      = ActiveTemplateInstantiation::DefaultTemplateArgumentInstantiation;
+    Inst.PointOfInstantiation = PointOfInstantiation;
+    Inst.Entity = reinterpret_cast<uintptr_t>(Template);
+    Inst.TemplateArgs = TemplateArgs;
+    Inst.NumTemplateArgs = NumTemplateArgs;
+    Inst.InstantiationRange = InstantiationRange;
+    SemaRef.ActiveTemplateInstantiations.push_back(Inst);
+  }
+}
+
+Sema::InstantiatingTemplate::InstantiatingTemplate(Sema &SemaRef,
+                                         SourceLocation PointOfInstantiation,
+                                      FunctionTemplateDecl *FunctionTemplate,
+                                        const TemplateArgument *TemplateArgs,
+                                                   unsigned NumTemplateArgs,
+                         ActiveTemplateInstantiation::InstantiationKind Kind,
+                                              SourceRange InstantiationRange)
+: SemaRef(SemaRef) {
+
+  Invalid = CheckInstantiationDepth(PointOfInstantiation,
+                                    InstantiationRange);
+  if (!Invalid) {
+    ActiveTemplateInstantiation Inst;
+    Inst.Kind = Kind;
+    Inst.PointOfInstantiation = PointOfInstantiation;
+    Inst.Entity = reinterpret_cast<uintptr_t>(FunctionTemplate);
+    Inst.TemplateArgs = TemplateArgs;
+    Inst.NumTemplateArgs = NumTemplateArgs;
+    Inst.InstantiationRange = InstantiationRange;
+    SemaRef.ActiveTemplateInstantiations.push_back(Inst);
+    
+    if (!Inst.isInstantiationRecord())
+      ++SemaRef.NonInstantiationEntries;
+  }
+}
+
+Sema::InstantiatingTemplate::InstantiatingTemplate(Sema &SemaRef,
+                                         SourceLocation PointOfInstantiation,
+                          ClassTemplatePartialSpecializationDecl *PartialSpec,
+                                         const TemplateArgument *TemplateArgs,
+                                         unsigned NumTemplateArgs,
+                                         SourceRange InstantiationRange)
+  : SemaRef(SemaRef) {
+
+  Invalid = false;
+    
+  ActiveTemplateInstantiation Inst;
+  Inst.Kind = ActiveTemplateInstantiation::DeducedTemplateArgumentSubstitution;
+  Inst.PointOfInstantiation = PointOfInstantiation;
+  Inst.Entity = reinterpret_cast<uintptr_t>(PartialSpec);
+  Inst.TemplateArgs = TemplateArgs;
+  Inst.NumTemplateArgs = NumTemplateArgs;
+  Inst.InstantiationRange = InstantiationRange;
+  SemaRef.ActiveTemplateInstantiations.push_back(Inst);
+      
+  assert(!Inst.isInstantiationRecord());
+  ++SemaRef.NonInstantiationEntries;
+}
+
+Sema::InstantiatingTemplate::InstantiatingTemplate(Sema &SemaRef,
+                                          SourceLocation PointOfInstantiation,
+                                          ParmVarDecl *Param,
+                                          const TemplateArgument *TemplateArgs,
+                                          unsigned NumTemplateArgs,
+                                          SourceRange InstantiationRange)
+  : SemaRef(SemaRef) {
+
+  Invalid = CheckInstantiationDepth(PointOfInstantiation, InstantiationRange);
+
+  if (!Invalid) {
+    ActiveTemplateInstantiation Inst;
+    Inst.Kind
+      = ActiveTemplateInstantiation::DefaultFunctionArgumentInstantiation;
+    Inst.PointOfInstantiation = PointOfInstantiation;
+    Inst.Entity = reinterpret_cast<uintptr_t>(Param);
+    Inst.TemplateArgs = TemplateArgs;
+    Inst.NumTemplateArgs = NumTemplateArgs;
+    Inst.InstantiationRange = InstantiationRange;
+    SemaRef.ActiveTemplateInstantiations.push_back(Inst);
+  }
+}
+
+Sema::InstantiatingTemplate::
+InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
+                      TemplateDecl *Template,
+                      NonTypeTemplateParmDecl *Param,
+                      const TemplateArgument *TemplateArgs,
+                      unsigned NumTemplateArgs,
+                      SourceRange InstantiationRange) : SemaRef(SemaRef) {
+  Invalid = false;
+  
+  ActiveTemplateInstantiation Inst;
+  Inst.Kind = ActiveTemplateInstantiation::PriorTemplateArgumentSubstitution;
+  Inst.PointOfInstantiation = PointOfInstantiation;
+  Inst.Template = Template;
+  Inst.Entity = reinterpret_cast<uintptr_t>(Param);
+  Inst.TemplateArgs = TemplateArgs;
+  Inst.NumTemplateArgs = NumTemplateArgs;
+  Inst.InstantiationRange = InstantiationRange;
+  SemaRef.ActiveTemplateInstantiations.push_back(Inst);
+  
+  assert(!Inst.isInstantiationRecord());
+  ++SemaRef.NonInstantiationEntries;
+}
+
+Sema::InstantiatingTemplate::
+InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
+                      TemplateDecl *Template,
+                      TemplateTemplateParmDecl *Param,
+                      const TemplateArgument *TemplateArgs,
+                      unsigned NumTemplateArgs,
+                      SourceRange InstantiationRange) : SemaRef(SemaRef) {
+  Invalid = false;
+  ActiveTemplateInstantiation Inst;
+  Inst.Kind = ActiveTemplateInstantiation::PriorTemplateArgumentSubstitution;
+  Inst.PointOfInstantiation = PointOfInstantiation;
+  Inst.Template = Template;
+  Inst.Entity = reinterpret_cast<uintptr_t>(Param);
+  Inst.TemplateArgs = TemplateArgs;
+  Inst.NumTemplateArgs = NumTemplateArgs;
+  Inst.InstantiationRange = InstantiationRange;
+  SemaRef.ActiveTemplateInstantiations.push_back(Inst);
+  
+  assert(!Inst.isInstantiationRecord());
+  ++SemaRef.NonInstantiationEntries;
+}
+
+Sema::InstantiatingTemplate::
+InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
+                      TemplateDecl *Template,
+                      NamedDecl *Param,
+                      const TemplateArgument *TemplateArgs,
+                      unsigned NumTemplateArgs,
+                      SourceRange InstantiationRange) : SemaRef(SemaRef) {
+  Invalid = false;
+  
+  ActiveTemplateInstantiation Inst;
+  Inst.Kind = ActiveTemplateInstantiation::DefaultTemplateArgumentChecking;
+  Inst.PointOfInstantiation = PointOfInstantiation;
+  Inst.Template = Template;
+  Inst.Entity = reinterpret_cast<uintptr_t>(Param);
+  Inst.TemplateArgs = TemplateArgs;
+  Inst.NumTemplateArgs = NumTemplateArgs;
+  Inst.InstantiationRange = InstantiationRange;
+  SemaRef.ActiveTemplateInstantiations.push_back(Inst);
+  
+  assert(!Inst.isInstantiationRecord());
+  ++SemaRef.NonInstantiationEntries;
+}
+
+void Sema::InstantiatingTemplate::Clear() {
+  if (!Invalid) {
+    if (!SemaRef.ActiveTemplateInstantiations.back().isInstantiationRecord()) {
+      assert(SemaRef.NonInstantiationEntries > 0);
+      --SemaRef.NonInstantiationEntries;
+    }
+    
+    SemaRef.ActiveTemplateInstantiations.pop_back();
+    Invalid = true;
+  }
+}
+
+bool Sema::InstantiatingTemplate::CheckInstantiationDepth(
+                                        SourceLocation PointOfInstantiation,
+                                           SourceRange InstantiationRange) {
+  assert(SemaRef.NonInstantiationEntries <=
+                                   SemaRef.ActiveTemplateInstantiations.size());
+  if ((SemaRef.ActiveTemplateInstantiations.size() - 
+          SemaRef.NonInstantiationEntries)
+        <= SemaRef.getLangOptions().InstantiationDepth)
+    return false;
+
+  SemaRef.Diag(PointOfInstantiation,
+               diag::err_template_recursion_depth_exceeded)
+    << SemaRef.getLangOptions().InstantiationDepth
+    << InstantiationRange;
+  SemaRef.Diag(PointOfInstantiation, diag::note_template_recursion_depth)
+    << SemaRef.getLangOptions().InstantiationDepth;
+  return true;
+}
+
+/// \brief Prints the current instantiation stack through a series of
+/// notes.
+void Sema::PrintInstantiationStack() {
+  // FIXME: In all of these cases, we need to show the template arguments
+  for (llvm::SmallVector<ActiveTemplateInstantiation, 16>::reverse_iterator
+         Active = ActiveTemplateInstantiations.rbegin(),
+         ActiveEnd = ActiveTemplateInstantiations.rend();
+       Active != ActiveEnd;
+       ++Active) {
+    switch (Active->Kind) {
+    case ActiveTemplateInstantiation::TemplateInstantiation: {
+      Decl *D = reinterpret_cast<Decl *>(Active->Entity);
+      if (CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(D)) {
+        unsigned DiagID = diag::note_template_member_class_here;
+        if (isa<ClassTemplateSpecializationDecl>(Record))
+          DiagID = diag::note_template_class_instantiation_here;
+        Diags.Report(FullSourceLoc(Active->PointOfInstantiation, SourceMgr),
+                     DiagID)
+          << Context.getTypeDeclType(Record)
+          << Active->InstantiationRange;
+      } else if (FunctionDecl *Function = dyn_cast<FunctionDecl>(D)) {
+        unsigned DiagID;
+        if (Function->getPrimaryTemplate())
+          DiagID = diag::note_function_template_spec_here;
+        else
+          DiagID = diag::note_template_member_function_here;
+        Diags.Report(FullSourceLoc(Active->PointOfInstantiation, SourceMgr),
+                     DiagID)
+          << Function
+          << Active->InstantiationRange;
+      } else {
+        Diags.Report(FullSourceLoc(Active->PointOfInstantiation, SourceMgr),
+                     diag::note_template_static_data_member_def_here)
+          << cast<VarDecl>(D)
+          << Active->InstantiationRange;
+      }
+      break;
+    }
+
+    case ActiveTemplateInstantiation::DefaultTemplateArgumentInstantiation: {
+      TemplateDecl *Template = cast<TemplateDecl>((Decl *)Active->Entity);
+      std::string TemplateArgsStr
+        = TemplateSpecializationType::PrintTemplateArgumentList(
+                                                         Active->TemplateArgs,
+                                                      Active->NumTemplateArgs,
+                                                      Context.PrintingPolicy);
+      Diags.Report(FullSourceLoc(Active->PointOfInstantiation, SourceMgr),
+                   diag::note_default_arg_instantiation_here)
+        << (Template->getNameAsString() + TemplateArgsStr)
+        << Active->InstantiationRange;
+      break;
+    }
+
+    case ActiveTemplateInstantiation::ExplicitTemplateArgumentSubstitution: {
+      FunctionTemplateDecl *FnTmpl
+        = cast<FunctionTemplateDecl>((Decl *)Active->Entity);
+      Diags.Report(FullSourceLoc(Active->PointOfInstantiation, SourceMgr),
+                   diag::note_explicit_template_arg_substitution_here)
+        << FnTmpl << Active->InstantiationRange;
+      break;
+    }
+
+    case ActiveTemplateInstantiation::DeducedTemplateArgumentSubstitution:
+      if (ClassTemplatePartialSpecializationDecl *PartialSpec
+            = dyn_cast<ClassTemplatePartialSpecializationDecl>(
+                                                    (Decl *)Active->Entity)) {
+        Diags.Report(FullSourceLoc(Active->PointOfInstantiation, SourceMgr),
+                     diag::note_partial_spec_deduct_instantiation_here)
+          << Context.getTypeDeclType(PartialSpec)
+          << Active->InstantiationRange;
+      } else {
+        FunctionTemplateDecl *FnTmpl
+          = cast<FunctionTemplateDecl>((Decl *)Active->Entity);
+        Diags.Report(FullSourceLoc(Active->PointOfInstantiation, SourceMgr),
+                     diag::note_function_template_deduction_instantiation_here)
+          << FnTmpl << Active->InstantiationRange;
+      }
+      break;
+
+    case ActiveTemplateInstantiation::DefaultFunctionArgumentInstantiation: {
+      ParmVarDecl *Param = cast<ParmVarDecl>((Decl *)Active->Entity);
+      FunctionDecl *FD = cast<FunctionDecl>(Param->getDeclContext());
+
+      std::string TemplateArgsStr
+        = TemplateSpecializationType::PrintTemplateArgumentList(
+                                                         Active->TemplateArgs,
+                                                      Active->NumTemplateArgs,
+                                                      Context.PrintingPolicy);
+      Diags.Report(FullSourceLoc(Active->PointOfInstantiation, SourceMgr),
+                   diag::note_default_function_arg_instantiation_here)
+        << (FD->getNameAsString() + TemplateArgsStr)
+        << Active->InstantiationRange;
+      break;
+    }
+
+    case ActiveTemplateInstantiation::PriorTemplateArgumentSubstitution: {
+      NamedDecl *Parm = cast<NamedDecl>((Decl *)Active->Entity);
+      std::string Name;
+      if (!Parm->getName().empty())
+        Name = std::string(" '") + Parm->getName().str() + "'";
+                                        
+      Diags.Report(FullSourceLoc(Active->PointOfInstantiation, SourceMgr),
+                   diag::note_prior_template_arg_substitution)
+        << isa<TemplateTemplateParmDecl>(Parm)
+        << Name
+        << getTemplateArgumentBindingsText(
+                                    Active->Template->getTemplateParameters(), 
+                                           Active->TemplateArgs, 
+                                           Active->NumTemplateArgs)
+        << Active->InstantiationRange;
+      break;
+    }
+
+    case ActiveTemplateInstantiation::DefaultTemplateArgumentChecking: {
+      Diags.Report(FullSourceLoc(Active->PointOfInstantiation, SourceMgr),
+                   diag::note_template_default_arg_checking)
+        << getTemplateArgumentBindingsText(
+                                     Active->Template->getTemplateParameters(), 
+                                           Active->TemplateArgs, 
+                                           Active->NumTemplateArgs)
+        << Active->InstantiationRange;
+      break;
+    }
+    }
+  }
+}
+
+bool Sema::isSFINAEContext() const {
+  using llvm::SmallVector;
+  for (SmallVector<ActiveTemplateInstantiation, 16>::const_reverse_iterator
+         Active = ActiveTemplateInstantiations.rbegin(),
+         ActiveEnd = ActiveTemplateInstantiations.rend();
+       Active != ActiveEnd;
+       ++Active) 
+  {
+    switch(Active->Kind) {
+    case ActiveTemplateInstantiation::TemplateInstantiation:
+    case ActiveTemplateInstantiation::DefaultFunctionArgumentInstantiation:
+      // This is a template instantiation, so there is no SFINAE.
+      return false;
+
+    case ActiveTemplateInstantiation::DefaultTemplateArgumentInstantiation:
+    case ActiveTemplateInstantiation::PriorTemplateArgumentSubstitution:
+    case ActiveTemplateInstantiation::DefaultTemplateArgumentChecking:
+      // A default template argument instantiation and substitution into
+      // template parameters with arguments for prior parameters may or may 
+      // not be a SFINAE context; look further up the stack.
+      break;
+
+    case ActiveTemplateInstantiation::ExplicitTemplateArgumentSubstitution:
+    case ActiveTemplateInstantiation::DeducedTemplateArgumentSubstitution:
+      // We're either substitution explicitly-specified template arguments
+      // or deduced template arguments, so SFINAE applies.
+      return true;
+    }
+  }
+
+  return false;
+}
+
+//===----------------------------------------------------------------------===/
+// Template Instantiation for Types
+//===----------------------------------------------------------------------===/
+namespace {
+  class TemplateInstantiator
+    : public TreeTransform<TemplateInstantiator> {
+    const MultiLevelTemplateArgumentList &TemplateArgs;
+    SourceLocation Loc;
+    DeclarationName Entity;
+
+  public:
+    typedef TreeTransform<TemplateInstantiator> inherited;
+
+    TemplateInstantiator(Sema &SemaRef,
+                         const MultiLevelTemplateArgumentList &TemplateArgs,
+                         SourceLocation Loc,
+                         DeclarationName Entity)
+      : inherited(SemaRef), TemplateArgs(TemplateArgs), Loc(Loc),
+        Entity(Entity) { }
+
+    /// \brief Determine whether the given type \p T has already been
+    /// transformed.
+    ///
+    /// For the purposes of template instantiation, a type has already been
+    /// transformed if it is NULL or if it is not dependent.
+    bool AlreadyTransformed(QualType T) {
+      return T.isNull() || !T->isDependentType();
+    }
+
+    /// \brief Returns the location of the entity being instantiated, if known.
+    SourceLocation getBaseLocation() { return Loc; }
+
+    /// \brief Returns the name of the entity being instantiated, if any.
+    DeclarationName getBaseEntity() { return Entity; }
+
+    /// \brief Sets the "base" location and entity when that
+    /// information is known based on another transformation.
+    void setBase(SourceLocation Loc, DeclarationName Entity) {
+      this->Loc = Loc;
+      this->Entity = Entity;
+    }
+      
+    /// \brief Transform the given declaration by instantiating a reference to
+    /// this declaration.
+    Decl *TransformDecl(Decl *D);
+
+    /// \brief Transform the definition of the given declaration by
+    /// instantiating it.
+    Decl *TransformDefinition(Decl *D);
+
+    /// \bried Transform the first qualifier within a scope by instantiating the
+    /// declaration.
+    NamedDecl *TransformFirstQualifierInScope(NamedDecl *D, SourceLocation Loc);
+      
+    /// \brief Rebuild the exception declaration and register the declaration
+    /// as an instantiated local.
+    VarDecl *RebuildExceptionDecl(VarDecl *ExceptionDecl, QualType T,
+                                  TypeSourceInfo *Declarator,
+                                  IdentifierInfo *Name,
+                                  SourceLocation Loc, SourceRange TypeRange);
+
+    /// \brief Check for tag mismatches when instantiating an
+    /// elaborated type.
+    QualType RebuildElaboratedType(QualType T, ElaboratedType::TagKind Tag);
+
+    Sema::OwningExprResult TransformPredefinedExpr(PredefinedExpr *E);
+    Sema::OwningExprResult TransformDeclRefExpr(DeclRefExpr *E);
+    Sema::OwningExprResult TransformCXXDefaultArgExpr(CXXDefaultArgExpr *E);
+    Sema::OwningExprResult TransformTemplateParmRefExpr(DeclRefExpr *E,
+                                                NonTypeTemplateParmDecl *D);
+
+    /// \brief Transforms a template type parameter type by performing
+    /// substitution of the corresponding template type argument.
+    QualType TransformTemplateTypeParmType(TypeLocBuilder &TLB,
+                                           TemplateTypeParmTypeLoc TL);
+  };
+}
+
+Decl *TemplateInstantiator::TransformDecl(Decl *D) {
+  if (!D)
+    return 0;
+
+  if (TemplateTemplateParmDecl *TTP = dyn_cast<TemplateTemplateParmDecl>(D)) {
+    if (TTP->getDepth() < TemplateArgs.getNumLevels()) {
+      // If the corresponding template argument is NULL or non-existent, it's
+      // because we are performing instantiation from explicitly-specified
+      // template arguments in a function template, but there were some
+      // arguments left unspecified.
+      if (!TemplateArgs.hasTemplateArgument(TTP->getDepth(),
+                                            TTP->getPosition()))
+        return D;
+
+      TemplateName Template
+        = TemplateArgs(TTP->getDepth(), TTP->getPosition()).getAsTemplate();
+      assert(!Template.isNull() && Template.getAsTemplateDecl() &&
+             "Wrong kind of template template argument");
+      return Template.getAsTemplateDecl();
+    }
+
+    // Fall through to find the instantiated declaration for this template
+    // template parameter.
+  }
+
+  return SemaRef.FindInstantiatedDecl(cast<NamedDecl>(D), TemplateArgs);
+}
+
+Decl *TemplateInstantiator::TransformDefinition(Decl *D) {
+  Decl *Inst = getSema().SubstDecl(D, getSema().CurContext, TemplateArgs);
+  if (!Inst)
+    return 0;
+
+  getSema().CurrentInstantiationScope->InstantiatedLocal(D, Inst);
+  return Inst;
+}
+
+NamedDecl *
+TemplateInstantiator::TransformFirstQualifierInScope(NamedDecl *D, 
+                                                     SourceLocation Loc) {
+  // If the first part of the nested-name-specifier was a template type 
+  // parameter, instantiate that type parameter down to a tag type.
+  if (TemplateTypeParmDecl *TTPD = dyn_cast_or_null<TemplateTypeParmDecl>(D)) {
+    const TemplateTypeParmType *TTP 
+      = cast<TemplateTypeParmType>(getSema().Context.getTypeDeclType(TTPD));
+    if (TTP->getDepth() < TemplateArgs.getNumLevels()) {
+      QualType T = TemplateArgs(TTP->getDepth(), TTP->getIndex()).getAsType();
+      if (T.isNull())
+        return cast_or_null<NamedDecl>(TransformDecl(D));
+      
+      if (const TagType *Tag = T->getAs<TagType>())
+        return Tag->getDecl();
+      
+      // The resulting type is not a tag; complain.
+      getSema().Diag(Loc, diag::err_nested_name_spec_non_tag) << T;
+      return 0;
+    }
+  }
+  
+  return cast_or_null<NamedDecl>(TransformDecl(D));
+}
+
+VarDecl *
+TemplateInstantiator::RebuildExceptionDecl(VarDecl *ExceptionDecl,
+                                           QualType T,
+                                           TypeSourceInfo *Declarator,
+                                           IdentifierInfo *Name,
+                                           SourceLocation Loc,
+                                           SourceRange TypeRange) {
+  VarDecl *Var = inherited::RebuildExceptionDecl(ExceptionDecl, T, Declarator,
+                                                 Name, Loc, TypeRange);
+  if (Var && !Var->isInvalidDecl())
+    getSema().CurrentInstantiationScope->InstantiatedLocal(ExceptionDecl, Var);
+  return Var;
+}
+
+QualType
+TemplateInstantiator::RebuildElaboratedType(QualType T,
+                                            ElaboratedType::TagKind Tag) {
+  if (const TagType *TT = T->getAs<TagType>()) {
+    TagDecl* TD = TT->getDecl();
+
+    // FIXME: this location is very wrong;  we really need typelocs.
+    SourceLocation TagLocation = TD->getTagKeywordLoc();
+
+    // FIXME: type might be anonymous.
+    IdentifierInfo *Id = TD->getIdentifier();
+
+    // TODO: should we even warn on struct/class mismatches for this?  Seems
+    // like it's likely to produce a lot of spurious errors.
+    if (!SemaRef.isAcceptableTagRedeclaration(TD, Tag, TagLocation, *Id)) {
+      SemaRef.Diag(TagLocation, diag::err_use_with_wrong_tag)
+        << Id
+        << CodeModificationHint::CreateReplacement(SourceRange(TagLocation),
+                                                   TD->getKindName());
+      SemaRef.Diag(TD->getLocation(), diag::note_previous_use);
+    }
+  }
+
+  return TreeTransform<TemplateInstantiator>::RebuildElaboratedType(T, Tag);
+}
+
+Sema::OwningExprResult 
+TemplateInstantiator::TransformPredefinedExpr(PredefinedExpr *E) {
+  if (!E->isTypeDependent())
+    return SemaRef.Owned(E->Retain());
+
+  FunctionDecl *currentDecl = getSema().getCurFunctionDecl();
+  assert(currentDecl && "Must have current function declaration when "
+                        "instantiating.");
+
+  PredefinedExpr::IdentType IT = E->getIdentType();
+
+  unsigned Length =
+    PredefinedExpr::ComputeName(getSema().Context, IT, currentDecl).length();
+
+  llvm::APInt LengthI(32, Length + 1);
+  QualType ResTy = getSema().Context.CharTy.withConst();
+  ResTy = getSema().Context.getConstantArrayType(ResTy, LengthI, 
+                                                 ArrayType::Normal, 0);
+  PredefinedExpr *PE =
+    new (getSema().Context) PredefinedExpr(E->getLocation(), ResTy, IT);
+  return getSema().Owned(PE);
+}
+
+Sema::OwningExprResult
+TemplateInstantiator::TransformTemplateParmRefExpr(DeclRefExpr *E,
+                                               NonTypeTemplateParmDecl *NTTP) {
+  // If the corresponding template argument is NULL or non-existent, it's
+  // because we are performing instantiation from explicitly-specified
+  // template arguments in a function template, but there were some
+  // arguments left unspecified.
+  if (!TemplateArgs.hasTemplateArgument(NTTP->getDepth(),
+                                        NTTP->getPosition()))
+    return SemaRef.Owned(E->Retain());
+
+  const TemplateArgument &Arg = TemplateArgs(NTTP->getDepth(),
+                                             NTTP->getPosition());
+
+  // The template argument itself might be an expression, in which
+  // case we just return that expression.
+  if (Arg.getKind() == TemplateArgument::Expression)
+    return SemaRef.Owned(Arg.getAsExpr()->Retain());
+
+  if (Arg.getKind() == TemplateArgument::Declaration) {
+    ValueDecl *VD = cast<ValueDecl>(Arg.getAsDecl());
+
+    // Find the instantiation of the template argument.  This is
+    // required for nested templates.
+    VD = cast_or_null<ValueDecl>(
+                              getSema().FindInstantiatedDecl(VD, TemplateArgs));
+    if (!VD)
+      return SemaRef.ExprError();
+
+    // Derive the type we want the substituted decl to have.  This had
+    // better be non-dependent, or these checks will have serious problems.
+    QualType TargetType = SemaRef.SubstType(NTTP->getType(), TemplateArgs,
+                                            E->getLocation(), 
+                                            DeclarationName());
+    assert(!TargetType.isNull() && "type substitution failed for param type");
+    assert(!TargetType->isDependentType() && "param type still dependent");
+
+    if (VD->getDeclContext()->isRecord() && 
+        (isa<CXXMethodDecl>(VD) || isa<FieldDecl>(VD))) {
+      // If the value is a class member, we might have a pointer-to-member.
+      // Determine whether the non-type template template parameter is of
+      // pointer-to-member type. If so, we need to build an appropriate
+      // expression for a pointer-to-member, since a "normal" DeclRefExpr
+      // would refer to the member itself.
+      if (TargetType->isMemberPointerType()) {
+        QualType ClassType
+          = SemaRef.Context.getTypeDeclType(
+                                        cast<RecordDecl>(VD->getDeclContext()));
+        NestedNameSpecifier *Qualifier
+          = NestedNameSpecifier::Create(SemaRef.Context, 0, false,
+                                        ClassType.getTypePtr());
+        CXXScopeSpec SS;
+        SS.setScopeRep(Qualifier);
+        OwningExprResult RefExpr 
+          = SemaRef.BuildDeclRefExpr(VD, 
+                                     VD->getType().getNonReferenceType(), 
+                                     E->getLocation(), 
+                                     &SS);
+        if (RefExpr.isInvalid())
+          return SemaRef.ExprError();
+
+        RefExpr = SemaRef.CreateBuiltinUnaryOp(E->getLocation(), 
+                                               UnaryOperator::AddrOf, 
+                                               move(RefExpr));
+        assert(!RefExpr.isInvalid() &&
+               SemaRef.Context.hasSameType(((Expr*) RefExpr.get())->getType(),
+                                           TargetType));
+        return move(RefExpr);
+      }
+    }
+
+    QualType T = VD->getType().getNonReferenceType();
+
+    if (TargetType->isPointerType()) {
+      // C++03 [temp.arg.nontype]p5:
+      //  - For a non-type template-parameter of type pointer to
+      //    object, qualification conversions and the array-to-pointer
+      //    conversion are applied.
+      //  - For a non-type template-parameter of type pointer to
+      //    function, only the function-to-pointer conversion is
+      //    applied.
+
+      OwningExprResult RefExpr
+        = SemaRef.BuildDeclRefExpr(VD, T, E->getLocation());
+      if (RefExpr.isInvalid())
+        return SemaRef.ExprError();
+
+      // Decay functions and arrays.
+      Expr *RefE = (Expr *)RefExpr.get();
+      SemaRef.DefaultFunctionArrayConversion(RefE);
+      if (RefE != RefExpr.get()) {
+        RefExpr.release();
+        RefExpr = SemaRef.Owned(RefE);
+      }
+
+      // Qualification conversions.
+      RefExpr.release();
+      SemaRef.ImpCastExprToType(RefE, TargetType.getUnqualifiedType(),
+                                CastExpr::CK_NoOp);
+      return SemaRef.Owned(RefE);
+    }
+
+    // If the non-type template parameter has reference type, qualify the
+    // resulting declaration reference with the extra qualifiers on the
+    // type that the reference refers to.
+    if (const ReferenceType *TargetRef = TargetType->getAs<ReferenceType>())
+      T = SemaRef.Context.getQualifiedType(T, 
+                                  TargetRef->getPointeeType().getQualifiers());
+    
+    return SemaRef.BuildDeclRefExpr(VD, T, E->getLocation());
+  }
+
+  assert(Arg.getKind() == TemplateArgument::Integral);
+  QualType T = Arg.getIntegralType();
+  if (T->isCharType() || T->isWideCharType())
+    return SemaRef.Owned(new (SemaRef.Context) CharacterLiteral(
+                                              Arg.getAsIntegral()->getZExtValue(),
+                                              T->isWideCharType(),
+                                              T,
+                                              E->getSourceRange().getBegin()));
+  if (T->isBooleanType())
+    return SemaRef.Owned(new (SemaRef.Context) CXXBoolLiteralExpr(
+                                            Arg.getAsIntegral()->getBoolValue(),
+                                            T,
+                                            E->getSourceRange().getBegin()));
+
+  assert(Arg.getAsIntegral()->getBitWidth() == SemaRef.Context.getIntWidth(T));
+  return SemaRef.Owned(new (SemaRef.Context) IntegerLiteral(
+                                                *Arg.getAsIntegral(),
+                                                T,
+                                                E->getSourceRange().getBegin()));
+}
+                                                   
+
+Sema::OwningExprResult
+TemplateInstantiator::TransformDeclRefExpr(DeclRefExpr *E) {
+  NamedDecl *D = E->getDecl();
+  if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(D)) {
+    if (NTTP->getDepth() < TemplateArgs.getNumLevels())
+      return TransformTemplateParmRefExpr(E, NTTP);
+    
+    // We have a non-type template parameter that isn't fully substituted;
+    // FindInstantiatedDecl will find it in the local instantiation scope.
+  }
+
+  return TreeTransform<TemplateInstantiator>::TransformDeclRefExpr(E);
+}
+
+Sema::OwningExprResult TemplateInstantiator::TransformCXXDefaultArgExpr(
+    CXXDefaultArgExpr *E) {
+  assert(!cast<FunctionDecl>(E->getParam()->getDeclContext())->
+             getDescribedFunctionTemplate() &&
+         "Default arg expressions are never formed in dependent cases.");
+  return SemaRef.BuildCXXDefaultArgExpr(E->getUsedLocation(),
+                           cast<FunctionDecl>(E->getParam()->getDeclContext()), 
+                                        E->getParam());
+}
+
+
+QualType
+TemplateInstantiator::TransformTemplateTypeParmType(TypeLocBuilder &TLB,
+                                                TemplateTypeParmTypeLoc TL) {
+  TemplateTypeParmType *T = TL.getTypePtr();
+  if (T->getDepth() < TemplateArgs.getNumLevels()) {
+    // Replace the template type parameter with its corresponding
+    // template argument.
+
+    // If the corresponding template argument is NULL or doesn't exist, it's
+    // because we are performing instantiation from explicitly-specified
+    // template arguments in a function template class, but there were some
+    // arguments left unspecified.
+    if (!TemplateArgs.hasTemplateArgument(T->getDepth(), T->getIndex())) {
+      TemplateTypeParmTypeLoc NewTL
+        = TLB.push<TemplateTypeParmTypeLoc>(TL.getType());
+      NewTL.setNameLoc(TL.getNameLoc());
+      return TL.getType();
+    }
+
+    assert(TemplateArgs(T->getDepth(), T->getIndex()).getKind()
+             == TemplateArgument::Type &&
+           "Template argument kind mismatch");
+
+    QualType Replacement
+      = TemplateArgs(T->getDepth(), T->getIndex()).getAsType();
+
+    // TODO: only do this uniquing once, at the start of instantiation.
+    QualType Result
+      = getSema().Context.getSubstTemplateTypeParmType(T, Replacement);
+    SubstTemplateTypeParmTypeLoc NewTL
+      = TLB.push<SubstTemplateTypeParmTypeLoc>(Result);
+    NewTL.setNameLoc(TL.getNameLoc());
+    return Result;
+  }
+
+  // The template type parameter comes from an inner template (e.g.,
+  // the template parameter list of a member template inside the
+  // template we are instantiating). Create a new template type
+  // parameter with the template "level" reduced by one.
+  QualType Result
+    = getSema().Context.getTemplateTypeParmType(T->getDepth()
+                                                 - TemplateArgs.getNumLevels(),
+                                                T->getIndex(),
+                                                T->isParameterPack(),
+                                                T->getName());
+  TemplateTypeParmTypeLoc NewTL = TLB.push<TemplateTypeParmTypeLoc>(Result);
+  NewTL.setNameLoc(TL.getNameLoc());
+  return Result;
+}
+
+/// \brief Perform substitution on the type T with a given set of template
+/// arguments.
+///
+/// This routine substitutes the given template arguments into the
+/// type T and produces the instantiated type.
+///
+/// \param T the type into which the template arguments will be
+/// substituted. If this type is not dependent, it will be returned
+/// immediately.
+///
+/// \param TemplateArgs the template arguments that will be
+/// substituted for the top-level template parameters within T.
+///
+/// \param Loc the location in the source code where this substitution
+/// is being performed. It will typically be the location of the
+/// declarator (if we're instantiating the type of some declaration)
+/// or the location of the type in the source code (if, e.g., we're
+/// instantiating the type of a cast expression).
+///
+/// \param Entity the name of the entity associated with a declaration
+/// being instantiated (if any). May be empty to indicate that there
+/// is no such entity (if, e.g., this is a type that occurs as part of
+/// a cast expression) or that the entity has no name (e.g., an
+/// unnamed function parameter).
+///
+/// \returns If the instantiation succeeds, the instantiated
+/// type. Otherwise, produces diagnostics and returns a NULL type.
+TypeSourceInfo *Sema::SubstType(TypeSourceInfo *T,
+                                const MultiLevelTemplateArgumentList &Args,
+                                SourceLocation Loc,
+                                DeclarationName Entity) {
+  assert(!ActiveTemplateInstantiations.empty() &&
+         "Cannot perform an instantiation without some context on the "
+         "instantiation stack");
+  
+  if (!T->getType()->isDependentType())
+    return T;
+
+  TemplateInstantiator Instantiator(*this, Args, Loc, Entity);
+  return Instantiator.TransformType(T);
+}
+
+/// Deprecated form of the above.
+QualType Sema::SubstType(QualType T,
+                         const MultiLevelTemplateArgumentList &TemplateArgs,
+                         SourceLocation Loc, DeclarationName Entity) {
+  assert(!ActiveTemplateInstantiations.empty() &&
+         "Cannot perform an instantiation without some context on the "
+         "instantiation stack");
+
+  // If T is not a dependent type, there is nothing to do.
+  if (!T->isDependentType())
+    return T;
+
+  TemplateInstantiator Instantiator(*this, TemplateArgs, Loc, Entity);
+  return Instantiator.TransformType(T);
+}
+
+/// \brief Perform substitution on the base class specifiers of the
+/// given class template specialization.
+///
+/// Produces a diagnostic and returns true on error, returns false and
+/// attaches the instantiated base classes to the class template
+/// specialization if successful.
+bool
+Sema::SubstBaseSpecifiers(CXXRecordDecl *Instantiation,
+                          CXXRecordDecl *Pattern,
+                          const MultiLevelTemplateArgumentList &TemplateArgs) {
+  bool Invalid = false;
+  llvm::SmallVector<CXXBaseSpecifier*, 4> InstantiatedBases;
+  for (ClassTemplateSpecializationDecl::base_class_iterator
+         Base = Pattern->bases_begin(), BaseEnd = Pattern->bases_end();
+       Base != BaseEnd; ++Base) {
+    if (!Base->getType()->isDependentType()) {
+      const CXXRecordDecl *BaseDecl =
+        cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl());
+      
+      // Make sure to set the attributes from the base.
+      SetClassDeclAttributesFromBase(Instantiation, BaseDecl, 
+                                     Base->isVirtual());
+      
+      InstantiatedBases.push_back(new (Context) CXXBaseSpecifier(*Base));
+      continue;
+    }
+
+    QualType BaseType = SubstType(Base->getType(),
+                                  TemplateArgs,
+                                  Base->getSourceRange().getBegin(),
+                                  DeclarationName());
+    if (BaseType.isNull()) {
+      Invalid = true;
+      continue;
+    }
+
+    if (CXXBaseSpecifier *InstantiatedBase
+          = CheckBaseSpecifier(Instantiation,
+                               Base->getSourceRange(),
+                               Base->isVirtual(),
+                               Base->getAccessSpecifierAsWritten(),
+                               BaseType,
+                               /*FIXME: Not totally accurate */
+                               Base->getSourceRange().getBegin()))
+      InstantiatedBases.push_back(InstantiatedBase);
+    else
+      Invalid = true;
+  }
+
+  if (!Invalid &&
+      AttachBaseSpecifiers(Instantiation, InstantiatedBases.data(),
+                           InstantiatedBases.size()))
+    Invalid = true;
+
+  return Invalid;
+}
+
+/// \brief Instantiate the definition of a class from a given pattern.
+///
+/// \param PointOfInstantiation The point of instantiation within the
+/// source code.
+///
+/// \param Instantiation is the declaration whose definition is being
+/// instantiated. This will be either a class template specialization
+/// or a member class of a class template specialization.
+///
+/// \param Pattern is the pattern from which the instantiation
+/// occurs. This will be either the declaration of a class template or
+/// the declaration of a member class of a class template.
+///
+/// \param TemplateArgs The template arguments to be substituted into
+/// the pattern.
+///
+/// \param TSK the kind of implicit or explicit instantiation to perform.
+///
+/// \param Complain whether to complain if the class cannot be instantiated due
+/// to the lack of a definition.
+///
+/// \returns true if an error occurred, false otherwise.
+bool
+Sema::InstantiateClass(SourceLocation PointOfInstantiation,
+                       CXXRecordDecl *Instantiation, CXXRecordDecl *Pattern,
+                       const MultiLevelTemplateArgumentList &TemplateArgs,
+                       TemplateSpecializationKind TSK,
+                       bool Complain) {
+  bool Invalid = false;
+
+  CXXRecordDecl *PatternDef
+    = cast_or_null<CXXRecordDecl>(Pattern->getDefinition(Context));
+  if (!PatternDef) {
+    if (!Complain) {
+      // Say nothing
+    } else if (Pattern == Instantiation->getInstantiatedFromMemberClass()) {
+      Diag(PointOfInstantiation,
+           diag::err_implicit_instantiate_member_undefined)
+        << Context.getTypeDeclType(Instantiation);
+      Diag(Pattern->getLocation(), diag::note_member_of_template_here);
+    } else {
+      Diag(PointOfInstantiation, diag::err_template_instantiate_undefined)
+        << (TSK != TSK_ImplicitInstantiation)
+        << Context.getTypeDeclType(Instantiation);
+      Diag(Pattern->getLocation(), diag::note_template_decl_here);
+    }
+    return true;
+  }
+  Pattern = PatternDef;
+
+  // \brief Record the point of instantiation.
+  if (MemberSpecializationInfo *MSInfo 
+        = Instantiation->getMemberSpecializationInfo()) {
+    MSInfo->setTemplateSpecializationKind(TSK);
+    MSInfo->setPointOfInstantiation(PointOfInstantiation);
+  } else if (ClassTemplateSpecializationDecl *Spec 
+               = dyn_cast<ClassTemplateSpecializationDecl>(Instantiation)) {
+    Spec->setTemplateSpecializationKind(TSK);
+    Spec->setPointOfInstantiation(PointOfInstantiation);
+  }
+  
+  InstantiatingTemplate Inst(*this, PointOfInstantiation, Instantiation);
+  if (Inst)
+    return true;
+
+  // Enter the scope of this instantiation. We don't use
+  // PushDeclContext because we don't have a scope.
+  DeclContext *PreviousContext = CurContext;
+  CurContext = Instantiation;
+
+  // Start the definition of this instantiation.
+  Instantiation->startDefinition();
+
+  // Do substitution on the base class specifiers.
+  if (SubstBaseSpecifiers(Instantiation, Pattern, TemplateArgs))
+    Invalid = true;
+
+  llvm::SmallVector<DeclPtrTy, 4> Fields;
+  for (RecordDecl::decl_iterator Member = Pattern->decls_begin(),
+         MemberEnd = Pattern->decls_end();
+       Member != MemberEnd; ++Member) {
+    Decl *NewMember = SubstDecl(*Member, Instantiation, TemplateArgs);
+    if (NewMember) {
+      if (FieldDecl *Field = dyn_cast<FieldDecl>(NewMember))
+        Fields.push_back(DeclPtrTy::make(Field));
+      else if (NewMember->isInvalidDecl())
+        Invalid = true;
+    } else {
+      // FIXME: Eventually, a NULL return will mean that one of the
+      // instantiations was a semantic disaster, and we'll want to set Invalid =
+      // true. For now, we expect to skip some members that we can't yet handle.
+    }
+  }
+
+  // Finish checking fields.
+  ActOnFields(0, Instantiation->getLocation(), DeclPtrTy::make(Instantiation),
+              Fields.data(), Fields.size(), SourceLocation(), SourceLocation(),
+              0);
+  CheckCompletedCXXClass(Instantiation);
+  if (Instantiation->isInvalidDecl())
+    Invalid = true;
+  
+  // Exit the scope of this instantiation.
+  CurContext = PreviousContext;
+
+  // If this is a polymorphic C++ class without a key function, we'll
+  // have to mark all of the virtual members to allow emission of a vtable
+  // in this translation unit.
+  if (Instantiation->isDynamicClass() && !Context.getKeyFunction(Instantiation))
+      ClassesWithUnmarkedVirtualMembers.push_back(std::make_pair(Instantiation,
+                                                       PointOfInstantiation));
+
+  if (!Invalid)
+    Consumer.HandleTagDeclDefinition(Instantiation);
+
+  return Invalid;
+}
+
+bool
+Sema::InstantiateClassTemplateSpecialization(
+                           SourceLocation PointOfInstantiation,
+                           ClassTemplateSpecializationDecl *ClassTemplateSpec,
+                           TemplateSpecializationKind TSK,
+                           bool Complain) {
+  // Perform the actual instantiation on the canonical declaration.
+  ClassTemplateSpec = cast<ClassTemplateSpecializationDecl>(
+                                         ClassTemplateSpec->getCanonicalDecl());
+
+  // Check whether we have already instantiated or specialized this class
+  // template specialization.
+  if (ClassTemplateSpec->getSpecializationKind() != TSK_Undeclared) {
+    if (ClassTemplateSpec->getSpecializationKind() == 
+          TSK_ExplicitInstantiationDeclaration &&
+        TSK == TSK_ExplicitInstantiationDefinition) {
+      // An explicit instantiation definition follows an explicit instantiation
+      // declaration (C++0x [temp.explicit]p10); go ahead and perform the
+      // explicit instantiation.
+      ClassTemplateSpec->setSpecializationKind(TSK);
+      return false;
+    }
+    
+    // We can only instantiate something that hasn't already been
+    // instantiated or specialized. Fail without any diagnostics: our
+    // caller will provide an error message.    
+    return true;
+  }
+
+  if (ClassTemplateSpec->isInvalidDecl())
+    return true;
+  
+  ClassTemplateDecl *Template = ClassTemplateSpec->getSpecializedTemplate();
+  CXXRecordDecl *Pattern = 0;
+
+  // C++ [temp.class.spec.match]p1:
+  //   When a class template is used in a context that requires an
+  //   instantiation of the class, it is necessary to determine
+  //   whether the instantiation is to be generated using the primary
+  //   template or one of the partial specializations. This is done by
+  //   matching the template arguments of the class template
+  //   specialization with the template argument lists of the partial
+  //   specializations.
+  typedef std::pair<ClassTemplatePartialSpecializationDecl *,
+                    TemplateArgumentList *> MatchResult;
+  llvm::SmallVector<MatchResult, 4> Matched;
+  for (llvm::FoldingSet<ClassTemplatePartialSpecializationDecl>::iterator
+         Partial = Template->getPartialSpecializations().begin(),
+         PartialEnd = Template->getPartialSpecializations().end();
+       Partial != PartialEnd;
+       ++Partial) {
+    TemplateDeductionInfo Info(Context, PointOfInstantiation);
+    if (TemplateDeductionResult Result
+          = DeduceTemplateArguments(&*Partial,
+                                    ClassTemplateSpec->getTemplateArgs(),
+                                    Info)) {
+      // FIXME: Store the failed-deduction information for use in
+      // diagnostics, later.
+      (void)Result;
+    } else {
+      Matched.push_back(std::make_pair(&*Partial, Info.take()));
+    }
+  }
+
+  if (Matched.size() >= 1) {
+    llvm::SmallVector<MatchResult, 4>::iterator Best = Matched.begin();
+    if (Matched.size() == 1) {
+      //   -- If exactly one matching specialization is found, the
+      //      instantiation is generated from that specialization.
+      // We don't need to do anything for this.
+    } else {
+      //   -- If more than one matching specialization is found, the
+      //      partial order rules (14.5.4.2) are used to determine
+      //      whether one of the specializations is more specialized
+      //      than the others. If none of the specializations is more
+      //      specialized than all of the other matching
+      //      specializations, then the use of the class template is
+      //      ambiguous and the program is ill-formed.
+      for (llvm::SmallVector<MatchResult, 4>::iterator P = Best + 1,
+                                                    PEnd = Matched.end();
+           P != PEnd; ++P) {
+        if (getMoreSpecializedPartialSpecialization(P->first, Best->first,
+                                                    PointOfInstantiation) 
+              == P->first)
+          Best = P;
+      }
+      
+      // Determine if the best partial specialization is more specialized than
+      // the others.
+      bool Ambiguous = false;
+      for (llvm::SmallVector<MatchResult, 4>::iterator P = Matched.begin(),
+                                                    PEnd = Matched.end();
+           P != PEnd; ++P) {
+        if (P != Best &&
+            getMoreSpecializedPartialSpecialization(P->first, Best->first,
+                                                    PointOfInstantiation)
+              != Best->first) {
+          Ambiguous = true;
+          break;
+        }
+      }
+       
+      if (Ambiguous) {
+        // Partial ordering did not produce a clear winner. Complain.
+        ClassTemplateSpec->setInvalidDecl();
+        Diag(PointOfInstantiation, diag::err_partial_spec_ordering_ambiguous)
+          << ClassTemplateSpec;
+        
+        // Print the matching partial specializations.
+        for (llvm::SmallVector<MatchResult, 4>::iterator P = Matched.begin(),
+                                                      PEnd = Matched.end();
+             P != PEnd; ++P)
+          Diag(P->first->getLocation(), diag::note_partial_spec_match)
+            << getTemplateArgumentBindingsText(P->first->getTemplateParameters(),
+                                               *P->second);
+
+        return true;
+      }
+    }
+    
+    // Instantiate using the best class template partial specialization.
+    ClassTemplatePartialSpecializationDecl *OrigPartialSpec = Best->first;
+    while (OrigPartialSpec->getInstantiatedFromMember()) {
+      // If we've found an explicit specialization of this class template,
+      // stop here and use that as the pattern.
+      if (OrigPartialSpec->isMemberSpecialization())
+        break;
+      
+      OrigPartialSpec = OrigPartialSpec->getInstantiatedFromMember();
+    }
+    
+    Pattern = OrigPartialSpec;
+    ClassTemplateSpec->setInstantiationOf(Best->first, Best->second);
+  } else {
+    //   -- If no matches are found, the instantiation is generated
+    //      from the primary template.
+    ClassTemplateDecl *OrigTemplate = Template;
+    while (OrigTemplate->getInstantiatedFromMemberTemplate()) {
+      // If we've found an explicit specialization of this class template,
+      // stop here and use that as the pattern.
+      if (OrigTemplate->isMemberSpecialization())
+        break;
+      
+      OrigTemplate = OrigTemplate->getInstantiatedFromMemberTemplate();
+    }
+    
+    Pattern = OrigTemplate->getTemplatedDecl();
+  }
+
+  bool Result = InstantiateClass(PointOfInstantiation, ClassTemplateSpec, 
+                                 Pattern,
+                                getTemplateInstantiationArgs(ClassTemplateSpec),
+                                 TSK,
+                                 Complain);
+
+  for (unsigned I = 0, N = Matched.size(); I != N; ++I) {
+    // FIXME: Implement TemplateArgumentList::Destroy!
+    //    if (Matched[I].first != Pattern)
+    //      Matched[I].second->Destroy(Context);
+  }
+
+  return Result;
+}
+
+/// \brief Instantiates the definitions of all of the member
+/// of the given class, which is an instantiation of a class template
+/// or a member class of a template.
+void
+Sema::InstantiateClassMembers(SourceLocation PointOfInstantiation,
+                              CXXRecordDecl *Instantiation,
+                        const MultiLevelTemplateArgumentList &TemplateArgs,
+                              TemplateSpecializationKind TSK) {
+  for (DeclContext::decl_iterator D = Instantiation->decls_begin(),
+                               DEnd = Instantiation->decls_end();
+       D != DEnd; ++D) {
+    bool SuppressNew = false;
+    if (FunctionDecl *Function = dyn_cast<FunctionDecl>(*D)) {
+      if (FunctionDecl *Pattern
+            = Function->getInstantiatedFromMemberFunction()) {
+        MemberSpecializationInfo *MSInfo 
+          = Function->getMemberSpecializationInfo();
+        assert(MSInfo && "No member specialization information?");
+        if (CheckSpecializationInstantiationRedecl(PointOfInstantiation, TSK, 
+                                                   Function, 
+                                        MSInfo->getTemplateSpecializationKind(),
+                                              MSInfo->getPointOfInstantiation(), 
+                                                   SuppressNew) ||
+            SuppressNew)
+          continue;
+        
+        if (Function->getBody())
+          continue;
+
+        if (TSK == TSK_ExplicitInstantiationDefinition) {
+          // C++0x [temp.explicit]p8:
+          //   An explicit instantiation definition that names a class template
+          //   specialization explicitly instantiates the class template 
+          //   specialization and is only an explicit instantiation definition 
+          //   of members whose definition is visible at the point of 
+          //   instantiation.
+          if (!Pattern->getBody())
+            continue;
+        
+          Function->setTemplateSpecializationKind(TSK, PointOfInstantiation);
+                      
+          InstantiateFunctionDefinition(PointOfInstantiation, Function);
+        } else {
+          Function->setTemplateSpecializationKind(TSK, PointOfInstantiation);
+        }
+      }
+    } else if (VarDecl *Var = dyn_cast<VarDecl>(*D)) {
+      if (Var->isStaticDataMember()) {
+        MemberSpecializationInfo *MSInfo = Var->getMemberSpecializationInfo();
+        assert(MSInfo && "No member specialization information?");
+        if (CheckSpecializationInstantiationRedecl(PointOfInstantiation, TSK, 
+                                                   Var, 
+                                        MSInfo->getTemplateSpecializationKind(),
+                                              MSInfo->getPointOfInstantiation(), 
+                                                   SuppressNew) ||
+            SuppressNew)
+          continue;
+        
+        if (TSK == TSK_ExplicitInstantiationDefinition) {
+          // C++0x [temp.explicit]p8:
+          //   An explicit instantiation definition that names a class template
+          //   specialization explicitly instantiates the class template 
+          //   specialization and is only an explicit instantiation definition 
+          //   of members whose definition is visible at the point of 
+          //   instantiation.
+          if (!Var->getInstantiatedFromStaticDataMember()
+                                                     ->getOutOfLineDefinition())
+            continue;
+          
+          Var->setTemplateSpecializationKind(TSK, PointOfInstantiation);
+          InstantiateStaticDataMemberDefinition(PointOfInstantiation, Var);
+        } else {
+          Var->setTemplateSpecializationKind(TSK, PointOfInstantiation);
+        }
+      }      
+    } else if (CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(*D)) {
+      if (Record->isInjectedClassName())
+        continue;
+      
+      MemberSpecializationInfo *MSInfo = Record->getMemberSpecializationInfo();
+      assert(MSInfo && "No member specialization information?");
+      if (CheckSpecializationInstantiationRedecl(PointOfInstantiation, TSK, 
+                                                 Record, 
+                                        MSInfo->getTemplateSpecializationKind(),
+                                              MSInfo->getPointOfInstantiation(), 
+                                                 SuppressNew) ||
+          SuppressNew)
+        continue;
+      
+      CXXRecordDecl *Pattern = Record->getInstantiatedFromMemberClass();
+      assert(Pattern && "Missing instantiated-from-template information");
+      
+      if (!Record->getDefinition(Context)) {
+        if (!Pattern->getDefinition(Context)) {
+          // C++0x [temp.explicit]p8:
+          //   An explicit instantiation definition that names a class template
+          //   specialization explicitly instantiates the class template 
+          //   specialization and is only an explicit instantiation definition 
+          //   of members whose definition is visible at the point of 
+          //   instantiation.
+          if (TSK == TSK_ExplicitInstantiationDeclaration) {
+            MSInfo->setTemplateSpecializationKind(TSK);
+            MSInfo->setPointOfInstantiation(PointOfInstantiation);
+          }
+          
+          continue;
+        }
+        
+        InstantiateClass(PointOfInstantiation, Record, Pattern,
+                         TemplateArgs,
+                         TSK);
+      }
+      
+      Pattern = cast_or_null<CXXRecordDecl>(Record->getDefinition(Context));
+      if (Pattern)
+        InstantiateClassMembers(PointOfInstantiation, Pattern, TemplateArgs, 
+                                TSK);
+    }
+  }
+}
+
+/// \brief Instantiate the definitions of all of the members of the
+/// given class template specialization, which was named as part of an
+/// explicit instantiation.
+void
+Sema::InstantiateClassTemplateSpecializationMembers(
+                                           SourceLocation PointOfInstantiation,
+                            ClassTemplateSpecializationDecl *ClassTemplateSpec,
+                                               TemplateSpecializationKind TSK) {
+  // C++0x [temp.explicit]p7:
+  //   An explicit instantiation that names a class template
+  //   specialization is an explicit instantion of the same kind
+  //   (declaration or definition) of each of its members (not
+  //   including members inherited from base classes) that has not
+  //   been previously explicitly specialized in the translation unit
+  //   containing the explicit instantiation, except as described
+  //   below.
+  InstantiateClassMembers(PointOfInstantiation, ClassTemplateSpec,
+                          getTemplateInstantiationArgs(ClassTemplateSpec),
+                          TSK);
+}
+
+Sema::OwningStmtResult
+Sema::SubstStmt(Stmt *S, const MultiLevelTemplateArgumentList &TemplateArgs) {
+  if (!S)
+    return Owned(S);
+
+  TemplateInstantiator Instantiator(*this, TemplateArgs,
+                                    SourceLocation(),
+                                    DeclarationName());
+  return Instantiator.TransformStmt(S);
+}
+
+Sema::OwningExprResult
+Sema::SubstExpr(Expr *E, const MultiLevelTemplateArgumentList &TemplateArgs) {
+  if (!E)
+    return Owned(E);
+
+  TemplateInstantiator Instantiator(*this, TemplateArgs,
+                                    SourceLocation(),
+                                    DeclarationName());
+  return Instantiator.TransformExpr(E);
+}
+
+/// \brief Do template substitution on a nested-name-specifier.
+NestedNameSpecifier *
+Sema::SubstNestedNameSpecifier(NestedNameSpecifier *NNS,
+                               SourceRange Range,
+                         const MultiLevelTemplateArgumentList &TemplateArgs) {
+  TemplateInstantiator Instantiator(*this, TemplateArgs, Range.getBegin(),
+                                    DeclarationName());
+  return Instantiator.TransformNestedNameSpecifier(NNS, Range);
+}
+
+TemplateName
+Sema::SubstTemplateName(TemplateName Name, SourceLocation Loc,
+                        const MultiLevelTemplateArgumentList &TemplateArgs) {
+  TemplateInstantiator Instantiator(*this, TemplateArgs, Loc,
+                                    DeclarationName());
+  return Instantiator.TransformTemplateName(Name);
+}
+
+bool Sema::Subst(const TemplateArgumentLoc &Input, TemplateArgumentLoc &Output,
+                 const MultiLevelTemplateArgumentList &TemplateArgs) {
+  TemplateInstantiator Instantiator(*this, TemplateArgs, SourceLocation(),
+                                    DeclarationName());
+
+  return Instantiator.TransformTemplateArgument(Input, Output);
+}
diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp
new file mode 100644
index 0000000..08cb681
--- /dev/null
+++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -0,0 +1,2336 @@
+//===--- SemaTemplateInstantiateDecl.cpp - C++ Template Decl Instantiation ===/
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//===----------------------------------------------------------------------===/
+//
+//  This file implements C++ template instantiation for declarations.
+//
+//===----------------------------------------------------------------------===/
+#include "Sema.h"
+#include "Lookup.h"
+#include "clang/AST/ASTConsumer.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/DeclTemplate.h"
+#include "clang/AST/DeclVisitor.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/ExprCXX.h"
+#include "clang/Basic/PrettyStackTrace.h"
+#include "clang/Lex/Preprocessor.h"
+
+using namespace clang;
+
+namespace {
+  class TemplateDeclInstantiator
+    : public DeclVisitor<TemplateDeclInstantiator, Decl *> {
+    Sema &SemaRef;
+    DeclContext *Owner;
+    const MultiLevelTemplateArgumentList &TemplateArgs;
+
+    void InstantiateAttrs(Decl *Tmpl, Decl *New);
+      
+  public:
+    typedef Sema::OwningExprResult OwningExprResult;
+
+    TemplateDeclInstantiator(Sema &SemaRef, DeclContext *Owner,
+                             const MultiLevelTemplateArgumentList &TemplateArgs)
+      : SemaRef(SemaRef), Owner(Owner), TemplateArgs(TemplateArgs) { }
+
+    // FIXME: Once we get closer to completion, replace these manually-written
+    // declarations with automatically-generated ones from
+    // clang/AST/DeclNodes.def.
+    Decl *VisitTranslationUnitDecl(TranslationUnitDecl *D);
+    Decl *VisitNamespaceDecl(NamespaceDecl *D);
+    Decl *VisitTypedefDecl(TypedefDecl *D);
+    Decl *VisitVarDecl(VarDecl *D);
+    Decl *VisitFieldDecl(FieldDecl *D);
+    Decl *VisitStaticAssertDecl(StaticAssertDecl *D);
+    Decl *VisitEnumDecl(EnumDecl *D);
+    Decl *VisitEnumConstantDecl(EnumConstantDecl *D);
+    Decl *VisitFriendDecl(FriendDecl *D);
+    Decl *VisitFunctionDecl(FunctionDecl *D,
+                            TemplateParameterList *TemplateParams = 0);
+    Decl *VisitCXXRecordDecl(CXXRecordDecl *D);
+    Decl *VisitCXXMethodDecl(CXXMethodDecl *D,
+                             TemplateParameterList *TemplateParams = 0);
+    Decl *VisitCXXConstructorDecl(CXXConstructorDecl *D);
+    Decl *VisitCXXDestructorDecl(CXXDestructorDecl *D);
+    Decl *VisitCXXConversionDecl(CXXConversionDecl *D);
+    ParmVarDecl *VisitParmVarDecl(ParmVarDecl *D);
+    Decl *VisitClassTemplateDecl(ClassTemplateDecl *D);
+    Decl *VisitClassTemplatePartialSpecializationDecl(
+                                    ClassTemplatePartialSpecializationDecl *D);
+    Decl *VisitFunctionTemplateDecl(FunctionTemplateDecl *D);
+    Decl *VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D);
+    Decl *VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D);
+    Decl *VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D);
+    Decl *VisitUsingDirectiveDecl(UsingDirectiveDecl *D);
+    Decl *VisitUsingDecl(UsingDecl *D);
+    Decl *VisitUsingShadowDecl(UsingShadowDecl *D);
+    Decl *VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D);
+    Decl *VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D);
+
+    // Base case. FIXME: Remove once we can instantiate everything.
+    Decl *VisitDecl(Decl *D) {
+      unsigned DiagID = SemaRef.getDiagnostics().getCustomDiagID(
+                                                            Diagnostic::Error,
+                                                   "cannot instantiate %0 yet");
+      SemaRef.Diag(D->getLocation(), DiagID)
+        << D->getDeclKindName();
+      
+      return 0;
+    }
+
+    const LangOptions &getLangOptions() {
+      return SemaRef.getLangOptions();
+    }
+
+    // Helper functions for instantiating methods.
+    QualType SubstFunctionType(FunctionDecl *D,
+                             llvm::SmallVectorImpl<ParmVarDecl *> &Params);
+    bool InitFunctionInstantiation(FunctionDecl *New, FunctionDecl *Tmpl);
+    bool InitMethodInstantiation(CXXMethodDecl *New, CXXMethodDecl *Tmpl);
+
+    TemplateParameterList *
+      SubstTemplateParams(TemplateParameterList *List);
+      
+    bool InstantiateClassTemplatePartialSpecialization(
+                                              ClassTemplateDecl *ClassTemplate,
+                           ClassTemplatePartialSpecializationDecl *PartialSpec);
+  };
+}
+
+// FIXME: Is this too simple?
+void TemplateDeclInstantiator::InstantiateAttrs(Decl *Tmpl, Decl *New) {
+  for (const Attr *TmplAttr = Tmpl->getAttrs(); TmplAttr; 
+       TmplAttr = TmplAttr->getNext()) {
+    
+    // FIXME: Is cloning correct for all attributes?
+    Attr *NewAttr = TmplAttr->clone(SemaRef.Context);
+    
+    New->addAttr(NewAttr);
+  }
+}
+
+Decl *
+TemplateDeclInstantiator::VisitTranslationUnitDecl(TranslationUnitDecl *D) {
+  assert(false && "Translation units cannot be instantiated");
+  return D;
+}
+
+Decl *
+TemplateDeclInstantiator::VisitNamespaceDecl(NamespaceDecl *D) {
+  assert(false && "Namespaces cannot be instantiated");
+  return D;
+}
+
+Decl *TemplateDeclInstantiator::VisitTypedefDecl(TypedefDecl *D) {
+  bool Invalid = false;
+  TypeSourceInfo *DI = D->getTypeSourceInfo();
+  if (DI->getType()->isDependentType()) {
+    DI = SemaRef.SubstType(DI, TemplateArgs,
+                           D->getLocation(), D->getDeclName());
+    if (!DI) {
+      Invalid = true;
+      DI = SemaRef.Context.getTrivialTypeSourceInfo(SemaRef.Context.IntTy);
+    }
+  }
+
+  // Create the new typedef
+  TypedefDecl *Typedef
+    = TypedefDecl::Create(SemaRef.Context, Owner, D->getLocation(),
+                          D->getIdentifier(), DI);
+  if (Invalid)
+    Typedef->setInvalidDecl();
+
+  if (TypedefDecl *Prev = D->getPreviousDeclaration()) {
+    NamedDecl *InstPrev = SemaRef.FindInstantiatedDecl(Prev, TemplateArgs);
+    Typedef->setPreviousDeclaration(cast<TypedefDecl>(InstPrev));
+  }
+
+  Typedef->setAccess(D->getAccess());
+  Owner->addDecl(Typedef);
+
+  return Typedef;
+}
+
+/// \brief Instantiate the arguments provided as part of initialization.
+///
+/// \returns true if an error occurred, false otherwise.
+static bool InstantiateInitializationArguments(Sema &SemaRef,
+                                               Expr **Args, unsigned NumArgs,
+                           const MultiLevelTemplateArgumentList &TemplateArgs,
+                         llvm::SmallVectorImpl<SourceLocation> &FakeCommaLocs,
+                           ASTOwningVector<&ActionBase::DeleteExpr> &InitArgs) {
+  for (unsigned I = 0; I != NumArgs; ++I) {
+    // When we hit the first defaulted argument, break out of the loop:
+    // we don't pass those default arguments on.
+    if (Args[I]->isDefaultArgument())
+      break;
+  
+    Sema::OwningExprResult Arg = SemaRef.SubstExpr(Args[I], TemplateArgs);
+    if (Arg.isInvalid())
+      return true;
+  
+    Expr *ArgExpr = (Expr *)Arg.get();
+    InitArgs.push_back(Arg.release());
+    
+    // FIXME: We're faking all of the comma locations. Do we need them?
+    FakeCommaLocs.push_back(
+                          SemaRef.PP.getLocForEndOfToken(ArgExpr->getLocEnd()));
+  }
+  
+  return false;
+}
+
+Decl *TemplateDeclInstantiator::VisitVarDecl(VarDecl *D) {
+  // Do substitution on the type of the declaration
+  TypeSourceInfo *DI = SemaRef.SubstType(D->getTypeSourceInfo(),
+                                         TemplateArgs,
+                                         D->getTypeSpecStartLoc(),
+                                         D->getDeclName());
+  if (!DI)
+    return 0;
+
+  // Build the instantiated declaration
+  VarDecl *Var = VarDecl::Create(SemaRef.Context, Owner,
+                                 D->getLocation(), D->getIdentifier(),
+                                 DI->getType(), DI,
+                                 D->getStorageClass());
+  Var->setThreadSpecified(D->isThreadSpecified());
+  Var->setCXXDirectInitializer(D->hasCXXDirectInitializer());
+  Var->setDeclaredInCondition(D->isDeclaredInCondition());
+
+  // If we are instantiating a static data member defined
+  // out-of-line, the instantiation will have the same lexical
+  // context (which will be a namespace scope) as the template.
+  if (D->isOutOfLine())
+    Var->setLexicalDeclContext(D->getLexicalDeclContext());
+
+  Var->setAccess(D->getAccess());
+
+  // FIXME: In theory, we could have a previous declaration for variables that
+  // are not static data members.
+  bool Redeclaration = false;
+  // FIXME: having to fake up a LookupResult is dumb.
+  LookupResult Previous(SemaRef, Var->getDeclName(), Var->getLocation(),
+                        Sema::LookupOrdinaryName);
+  if (D->isStaticDataMember())
+    SemaRef.LookupQualifiedName(Previous, Owner, false);
+  SemaRef.CheckVariableDeclaration(Var, Previous, Redeclaration);
+
+  if (D->isOutOfLine()) {
+    D->getLexicalDeclContext()->addDecl(Var);
+    Owner->makeDeclVisibleInContext(Var);
+  } else {
+    Owner->addDecl(Var);
+  }
+
+  // Link instantiations of static data members back to the template from
+  // which they were instantiated.
+  if (Var->isStaticDataMember())
+    SemaRef.Context.setInstantiatedFromStaticDataMember(Var, D, 
+                                                     TSK_ImplicitInstantiation);
+  
+  if (Var->getAnyInitializer()) {
+    // We already have an initializer in the class.
+  } else if (D->getInit()) {
+    if (Var->isStaticDataMember() && !D->isOutOfLine())
+      SemaRef.PushExpressionEvaluationContext(Sema::Unevaluated);
+    else
+      SemaRef.PushExpressionEvaluationContext(Sema::PotentiallyEvaluated);
+
+    // Extract the initializer, skipping through any temporary-binding 
+    // expressions and look at the subexpression as it was written.
+    Expr *DInit = D->getInit();
+    if (CXXExprWithTemporaries *ExprTemp
+          = dyn_cast<CXXExprWithTemporaries>(DInit))
+      DInit = ExprTemp->getSubExpr();
+    while (CXXBindTemporaryExpr *Binder = dyn_cast<CXXBindTemporaryExpr>(DInit))
+      DInit = Binder->getSubExpr();
+    if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(DInit))
+      DInit = ICE->getSubExprAsWritten();
+        
+    if (ParenListExpr *PLE = dyn_cast<ParenListExpr>(DInit)) {
+      // The initializer is a parenthesized list of expressions that is
+      // type-dependent. Instantiate each of the expressions; we'll be 
+      // performing direct initialization with them.
+      llvm::SmallVector<SourceLocation, 4> CommaLocs;
+      ASTOwningVector<&ActionBase::DeleteExpr> InitArgs(SemaRef);
+      if (!InstantiateInitializationArguments(SemaRef, 
+                                              PLE->getExprs(), 
+                                              PLE->getNumExprs(),
+                                              TemplateArgs,
+                                              CommaLocs, InitArgs)) {
+        // Add the direct initializer to the declaration.
+        SemaRef.AddCXXDirectInitializerToDecl(Sema::DeclPtrTy::make(Var),
+                                              PLE->getLParenLoc(),
+                                              move_arg(InitArgs),
+                                              CommaLocs.data(),
+                                              PLE->getRParenLoc());
+      }
+    } else if (CXXConstructExpr *Construct =dyn_cast<CXXConstructExpr>(DInit)) {
+      // The initializer resolved to a constructor. Instantiate the constructor
+      // arguments.
+      llvm::SmallVector<SourceLocation, 4> CommaLocs;
+      ASTOwningVector<&ActionBase::DeleteExpr> InitArgs(SemaRef);
+      
+      if (!InstantiateInitializationArguments(SemaRef, 
+                                              Construct->getArgs(),
+                                              Construct->getNumArgs(),
+                                              TemplateArgs,
+                                              CommaLocs, InitArgs)) {
+        if (D->hasCXXDirectInitializer()) {
+          SourceLocation FakeLParenLoc = 
+            SemaRef.PP.getLocForEndOfToken(D->getLocation());
+          SourceLocation FakeRParenLoc = CommaLocs.empty()? FakeLParenLoc
+                                                          : CommaLocs.back();
+          SemaRef.AddCXXDirectInitializerToDecl(Sema::DeclPtrTy::make(Var),
+                                                FakeLParenLoc,
+                                                move_arg(InitArgs),
+                                                CommaLocs.data(),
+                                                FakeRParenLoc);          
+        } else if (InitArgs.size() == 1) {
+          Expr *Init = (Expr*)(InitArgs.take()[0]);
+          SemaRef.AddInitializerToDecl(Sema::DeclPtrTy::make(Var), 
+                                       SemaRef.Owned(Init),
+                                       false);
+        } else {
+          assert(InitArgs.size() == 0);
+          SemaRef.ActOnUninitializedDecl(Sema::DeclPtrTy::make(Var), false);          
+        }
+      } 
+    } else {
+      OwningExprResult Init
+        = SemaRef.SubstExpr(D->getInit(), TemplateArgs);
+
+      // FIXME: Not happy about invalidating decls just because of a bad 
+      // initializer, unless it affects the type.
+      if (Init.isInvalid())
+        Var->setInvalidDecl();
+      else
+        SemaRef.AddInitializerToDecl(Sema::DeclPtrTy::make(Var), move(Init),
+                                     D->hasCXXDirectInitializer());
+    }
+    
+    SemaRef.PopExpressionEvaluationContext();
+  } else if (!Var->isStaticDataMember() || Var->isOutOfLine())
+    SemaRef.ActOnUninitializedDecl(Sema::DeclPtrTy::make(Var), false);
+
+  return Var;
+}
+
+Decl *TemplateDeclInstantiator::VisitFieldDecl(FieldDecl *D) {
+  bool Invalid = false;
+  TypeSourceInfo *DI = D->getTypeSourceInfo();
+  if (DI->getType()->isDependentType())  {
+    DI = SemaRef.SubstType(DI, TemplateArgs,
+                           D->getLocation(), D->getDeclName());
+    if (!DI) {
+      DI = D->getTypeSourceInfo();
+      Invalid = true;
+    } else if (DI->getType()->isFunctionType()) {
+      // C++ [temp.arg.type]p3:
+      //   If a declaration acquires a function type through a type
+      //   dependent on a template-parameter and this causes a
+      //   declaration that does not use the syntactic form of a
+      //   function declarator to have function type, the program is
+      //   ill-formed.
+      SemaRef.Diag(D->getLocation(), diag::err_field_instantiates_to_function)
+        << DI->getType();
+      Invalid = true;
+    }
+  }
+
+  Expr *BitWidth = D->getBitWidth();
+  if (Invalid)
+    BitWidth = 0;
+  else if (BitWidth) {
+    // The bit-width expression is not potentially evaluated.
+    EnterExpressionEvaluationContext Unevaluated(SemaRef, Action::Unevaluated);
+
+    OwningExprResult InstantiatedBitWidth
+      = SemaRef.SubstExpr(BitWidth, TemplateArgs);
+    if (InstantiatedBitWidth.isInvalid()) {
+      Invalid = true;
+      BitWidth = 0;
+    } else
+      BitWidth = InstantiatedBitWidth.takeAs<Expr>();
+  }
+
+  FieldDecl *Field = SemaRef.CheckFieldDecl(D->getDeclName(),
+                                            DI->getType(), DI,
+                                            cast<RecordDecl>(Owner),
+                                            D->getLocation(),
+                                            D->isMutable(),
+                                            BitWidth,
+                                            D->getTypeSpecStartLoc(),
+                                            D->getAccess(),
+                                            0);
+  if (!Field) {
+    cast<Decl>(Owner)->setInvalidDecl();
+    return 0;
+  }
+
+  InstantiateAttrs(D, Field);
+  
+  if (Invalid)
+    Field->setInvalidDecl();
+
+  if (!Field->getDeclName()) {
+    // Keep track of where this decl came from.
+    SemaRef.Context.setInstantiatedFromUnnamedFieldDecl(Field, D);
+  }
+
+  Field->setImplicit(D->isImplicit());
+  Field->setAccess(D->getAccess());
+  Owner->addDecl(Field);
+
+  return Field;
+}
+
+Decl *TemplateDeclInstantiator::VisitFriendDecl(FriendDecl *D) {
+  FriendDecl::FriendUnion FU;
+
+  // Handle friend type expressions by simply substituting template
+  // parameters into the pattern type.
+  if (Type *Ty = D->getFriendType()) {
+    QualType T = SemaRef.SubstType(QualType(Ty,0), TemplateArgs,
+                                   D->getLocation(), DeclarationName());
+    if (T.isNull()) return 0;
+
+    assert(getLangOptions().CPlusPlus0x || T->isRecordType());
+    FU = T.getTypePtr();
+
+  // Handle everything else by appropriate substitution.
+  } else {
+    NamedDecl *ND = D->getFriendDecl();
+    assert(ND && "friend decl must be a decl or a type!");
+
+    // FIXME: We have a problem here, because the nested call to Visit(ND)
+    // will inject the thing that the friend references into the current
+    // owner, which is wrong.
+    Decl *NewND;
+
+    // Hack to make this work almost well pending a rewrite.
+    if (ND->getDeclContext()->isRecord()) {
+      if (!ND->getDeclContext()->isDependentContext()) {
+        NewND = SemaRef.FindInstantiatedDecl(ND, TemplateArgs);
+      } else {
+        // FIXME: Hack to avoid crashing when incorrectly trying to instantiate
+        // templated friend declarations. This doesn't produce a correct AST;
+        // however this is sufficient for some AST analysis. The real solution
+        // must be put in place during the pending rewrite. See PR5848.
+        return 0;
+      }
+    } else if (D->wasSpecialization()) {
+      // Totally egregious hack to work around PR5866
+      return 0;
+    } else
+      NewND = Visit(ND);
+    if (!NewND) return 0;
+
+    FU = cast<NamedDecl>(NewND);
+  }
+
+  FriendDecl *FD =
+    FriendDecl::Create(SemaRef.Context, Owner, D->getLocation(), FU,
+                       D->getFriendLoc());
+  FD->setAccess(AS_public);
+  Owner->addDecl(FD);
+  return FD;
+}
+
+Decl *TemplateDeclInstantiator::VisitStaticAssertDecl(StaticAssertDecl *D) {
+  Expr *AssertExpr = D->getAssertExpr();
+
+  // The expression in a static assertion is not potentially evaluated.
+  EnterExpressionEvaluationContext Unevaluated(SemaRef, Action::Unevaluated);
+
+  OwningExprResult InstantiatedAssertExpr
+    = SemaRef.SubstExpr(AssertExpr, TemplateArgs);
+  if (InstantiatedAssertExpr.isInvalid())
+    return 0;
+
+  OwningExprResult Message(SemaRef, D->getMessage());
+  D->getMessage()->Retain();
+  Decl *StaticAssert
+    = SemaRef.ActOnStaticAssertDeclaration(D->getLocation(),
+                                           move(InstantiatedAssertExpr),
+                                           move(Message)).getAs<Decl>();
+  return StaticAssert;
+}
+
+Decl *TemplateDeclInstantiator::VisitEnumDecl(EnumDecl *D) {
+  EnumDecl *Enum = EnumDecl::Create(SemaRef.Context, Owner,
+                                    D->getLocation(), D->getIdentifier(),
+                                    D->getTagKeywordLoc(),
+                                    /*PrevDecl=*/0);
+  Enum->setInstantiationOfMemberEnum(D);
+  Enum->setAccess(D->getAccess());
+  Owner->addDecl(Enum);
+  Enum->startDefinition();
+
+  llvm::SmallVector<Sema::DeclPtrTy, 4> Enumerators;
+
+  EnumConstantDecl *LastEnumConst = 0;
+  for (EnumDecl::enumerator_iterator EC = D->enumerator_begin(),
+         ECEnd = D->enumerator_end();
+       EC != ECEnd; ++EC) {
+    // The specified value for the enumerator.
+    OwningExprResult Value = SemaRef.Owned((Expr *)0);
+    if (Expr *UninstValue = EC->getInitExpr()) {
+      // The enumerator's value expression is not potentially evaluated.
+      EnterExpressionEvaluationContext Unevaluated(SemaRef,
+                                                   Action::Unevaluated);
+
+      Value = SemaRef.SubstExpr(UninstValue, TemplateArgs);
+    }
+
+    // Drop the initial value and continue.
+    bool isInvalid = false;
+    if (Value.isInvalid()) {
+      Value = SemaRef.Owned((Expr *)0);
+      isInvalid = true;
+    }
+
+    EnumConstantDecl *EnumConst
+      = SemaRef.CheckEnumConstant(Enum, LastEnumConst,
+                                  EC->getLocation(), EC->getIdentifier(),
+                                  move(Value));
+
+    if (isInvalid) {
+      if (EnumConst)
+        EnumConst->setInvalidDecl();
+      Enum->setInvalidDecl();
+    }
+
+    if (EnumConst) {
+      EnumConst->setAccess(Enum->getAccess());
+      Enum->addDecl(EnumConst);
+      Enumerators.push_back(Sema::DeclPtrTy::make(EnumConst));
+      LastEnumConst = EnumConst;
+    }
+  }
+
+  // FIXME: Fixup LBraceLoc and RBraceLoc
+  // FIXME: Empty Scope and AttributeList (required to handle attribute packed).
+  SemaRef.ActOnEnumBody(Enum->getLocation(), SourceLocation(), SourceLocation(),
+                        Sema::DeclPtrTy::make(Enum),
+                        &Enumerators[0], Enumerators.size(),
+                        0, 0);
+
+  return Enum;
+}
+
+Decl *TemplateDeclInstantiator::VisitEnumConstantDecl(EnumConstantDecl *D) {
+  assert(false && "EnumConstantDecls can only occur within EnumDecls.");
+  return 0;
+}
+
+namespace {
+  class SortDeclByLocation {
+    SourceManager &SourceMgr;
+    
+  public:
+    explicit SortDeclByLocation(SourceManager &SourceMgr) 
+      : SourceMgr(SourceMgr) { }
+    
+    bool operator()(const Decl *X, const Decl *Y) const {
+      return SourceMgr.isBeforeInTranslationUnit(X->getLocation(),
+                                                 Y->getLocation());
+    }
+  };
+}
+
+Decl *TemplateDeclInstantiator::VisitClassTemplateDecl(ClassTemplateDecl *D) {
+  // Create a local instantiation scope for this class template, which
+  // will contain the instantiations of the template parameters.
+  Sema::LocalInstantiationScope Scope(SemaRef);
+  TemplateParameterList *TempParams = D->getTemplateParameters();
+  TemplateParameterList *InstParams = SubstTemplateParams(TempParams);
+  if (!InstParams)
+    return NULL;
+
+  CXXRecordDecl *Pattern = D->getTemplatedDecl();
+  CXXRecordDecl *RecordInst
+    = CXXRecordDecl::Create(SemaRef.Context, Pattern->getTagKind(), Owner,
+                            Pattern->getLocation(), Pattern->getIdentifier(),
+                            Pattern->getTagKeywordLoc(), /*PrevDecl=*/ NULL,
+                            /*DelayTypeCreation=*/true);
+
+  ClassTemplateDecl *Inst
+    = ClassTemplateDecl::Create(SemaRef.Context, Owner, D->getLocation(),
+                                D->getIdentifier(), InstParams, RecordInst, 0);
+  RecordInst->setDescribedClassTemplate(Inst);
+  if (D->getFriendObjectKind())
+    Inst->setObjectOfFriendDecl(true);
+  else
+    Inst->setAccess(D->getAccess());
+  Inst->setInstantiatedFromMemberTemplate(D);
+  
+  // Trigger creation of the type for the instantiation.
+  SemaRef.Context.getTypeDeclType(RecordInst);
+  
+  // Finish handling of friends.
+  if (Inst->getFriendObjectKind()) {
+    return Inst;
+  }
+  
+  Inst->setAccess(D->getAccess());
+  Owner->addDecl(Inst);
+  
+  // First, we sort the partial specializations by location, so 
+  // that we instantiate them in the order they were declared.
+  llvm::SmallVector<ClassTemplatePartialSpecializationDecl *, 4> PartialSpecs;
+  for (llvm::FoldingSet<ClassTemplatePartialSpecializationDecl>::iterator
+         P = D->getPartialSpecializations().begin(), 
+         PEnd = D->getPartialSpecializations().end();
+       P != PEnd; ++P)
+    PartialSpecs.push_back(&*P);
+  std::sort(PartialSpecs.begin(), PartialSpecs.end(),
+            SortDeclByLocation(SemaRef.SourceMgr));
+  
+  // Instantiate all of the partial specializations of this member class 
+  // template.
+  for (unsigned I = 0, N = PartialSpecs.size(); I != N; ++I)
+    InstantiateClassTemplatePartialSpecialization(Inst, PartialSpecs[I]);
+  
+  return Inst;
+}
+
+Decl *
+TemplateDeclInstantiator::VisitClassTemplatePartialSpecializationDecl(
+                                   ClassTemplatePartialSpecializationDecl *D) {
+  ClassTemplateDecl *ClassTemplate = D->getSpecializedTemplate();
+  
+  // Lookup the already-instantiated declaration in the instantiation
+  // of the class template and return that.
+  DeclContext::lookup_result Found
+    = Owner->lookup(ClassTemplate->getDeclName());
+  if (Found.first == Found.second)
+    return 0;
+  
+  ClassTemplateDecl *InstClassTemplate
+    = dyn_cast<ClassTemplateDecl>(*Found.first);
+  if (!InstClassTemplate)
+    return 0;
+  
+  Decl *DCanon = D->getCanonicalDecl();
+  for (llvm::FoldingSet<ClassTemplatePartialSpecializationDecl>::iterator
+            P = InstClassTemplate->getPartialSpecializations().begin(),
+         PEnd = InstClassTemplate->getPartialSpecializations().end();
+       P != PEnd; ++P) {
+    if (P->getInstantiatedFromMember()->getCanonicalDecl() == DCanon)
+      return &*P;
+  }
+  
+  return 0;
+}
+
+Decl *
+TemplateDeclInstantiator::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) {
+  // Create a local instantiation scope for this function template, which
+  // will contain the instantiations of the template parameters and then get
+  // merged with the local instantiation scope for the function template 
+  // itself.
+  Sema::LocalInstantiationScope Scope(SemaRef);
+  
+  TemplateParameterList *TempParams = D->getTemplateParameters();
+  TemplateParameterList *InstParams = SubstTemplateParams(TempParams);
+  if (!InstParams)
+    return NULL;
+  
+  FunctionDecl *Instantiated = 0;
+  if (CXXMethodDecl *DMethod = dyn_cast<CXXMethodDecl>(D->getTemplatedDecl()))
+    Instantiated = cast_or_null<FunctionDecl>(VisitCXXMethodDecl(DMethod, 
+                                                                 InstParams));
+  else
+    Instantiated = cast_or_null<FunctionDecl>(VisitFunctionDecl(
+                                                          D->getTemplatedDecl(), 
+                                                                InstParams));
+  
+  if (!Instantiated)
+    return 0;
+
+  Instantiated->setAccess(D->getAccess());
+
+  // Link the instantiated function template declaration to the function
+  // template from which it was instantiated.
+  FunctionTemplateDecl *InstTemplate 
+    = Instantiated->getDescribedFunctionTemplate();
+  InstTemplate->setAccess(D->getAccess());
+  assert(InstTemplate && 
+         "VisitFunctionDecl/CXXMethodDecl didn't create a template!");
+
+  // Link the instantiation back to the pattern *unless* this is a
+  // non-definition friend declaration.
+  if (!InstTemplate->getInstantiatedFromMemberTemplate() &&
+      !(InstTemplate->getFriendObjectKind() &&
+        !D->getTemplatedDecl()->isThisDeclarationADefinition()))
+    InstTemplate->setInstantiatedFromMemberTemplate(D);
+  
+  // Add non-friends into the owner.
+  if (!InstTemplate->getFriendObjectKind())
+    Owner->addDecl(InstTemplate);
+  return InstTemplate;
+}
+
+Decl *TemplateDeclInstantiator::VisitCXXRecordDecl(CXXRecordDecl *D) {
+  CXXRecordDecl *PrevDecl = 0;
+  if (D->isInjectedClassName())
+    PrevDecl = cast<CXXRecordDecl>(Owner);
+  else if (D->getPreviousDeclaration()) {
+    NamedDecl *Prev = SemaRef.FindInstantiatedDecl(D->getPreviousDeclaration(),
+                                                   TemplateArgs);
+    if (!Prev) return 0;
+    PrevDecl = cast<CXXRecordDecl>(Prev);
+  }
+
+  CXXRecordDecl *Record
+    = CXXRecordDecl::Create(SemaRef.Context, D->getTagKind(), Owner,
+                            D->getLocation(), D->getIdentifier(),
+                            D->getTagKeywordLoc(), PrevDecl);
+  Record->setImplicit(D->isImplicit());
+  // FIXME: Check against AS_none is an ugly hack to work around the issue that
+  // the tag decls introduced by friend class declarations don't have an access
+  // specifier. Remove once this area of the code gets sorted out.
+  if (D->getAccess() != AS_none)
+    Record->setAccess(D->getAccess());
+  if (!D->isInjectedClassName())
+    Record->setInstantiationOfMemberClass(D, TSK_ImplicitInstantiation);
+
+  // If the original function was part of a friend declaration,
+  // inherit its namespace state.
+  if (Decl::FriendObjectKind FOK = D->getFriendObjectKind())
+    Record->setObjectOfFriendDecl(FOK == Decl::FOK_Declared);
+
+  Record->setAnonymousStructOrUnion(D->isAnonymousStructOrUnion());
+
+  Owner->addDecl(Record);
+  return Record;
+}
+
+/// Normal class members are of more specific types and therefore
+/// don't make it here.  This function serves two purposes:
+///   1) instantiating function templates
+///   2) substituting friend declarations
+/// FIXME: preserve function definitions in case #2
+Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D,
+                                       TemplateParameterList *TemplateParams) {
+  // Check whether there is already a function template specialization for
+  // this declaration.
+  FunctionTemplateDecl *FunctionTemplate = D->getDescribedFunctionTemplate();
+  void *InsertPos = 0;
+  if (FunctionTemplate && !TemplateParams) {
+    llvm::FoldingSetNodeID ID;
+    FunctionTemplateSpecializationInfo::Profile(ID,
+                             TemplateArgs.getInnermost().getFlatArgumentList(),
+                                       TemplateArgs.getInnermost().flat_size(),
+                                                SemaRef.Context);
+
+    FunctionTemplateSpecializationInfo *Info
+      = FunctionTemplate->getSpecializations().FindNodeOrInsertPos(ID,
+                                                                   InsertPos);
+
+    // If we already have a function template specialization, return it.
+    if (Info)
+      return Info->Function;
+  }
+
+  bool MergeWithParentScope = (TemplateParams != 0) ||
+    !(isa<Decl>(Owner) && 
+      cast<Decl>(Owner)->isDefinedOutsideFunctionOrMethod());
+  Sema::LocalInstantiationScope Scope(SemaRef, MergeWithParentScope);
+
+  llvm::SmallVector<ParmVarDecl *, 4> Params;
+  QualType T = SubstFunctionType(D, Params);
+  if (T.isNull())
+    return 0;
+
+  // If we're instantiating a local function declaration, put the result
+  // in the owner;  otherwise we need to find the instantiated context.
+  DeclContext *DC;
+  if (D->getDeclContext()->isFunctionOrMethod())
+    DC = Owner;
+  else
+    DC = SemaRef.FindInstantiatedContext(D->getDeclContext(), TemplateArgs);
+
+  FunctionDecl *Function =
+      FunctionDecl::Create(SemaRef.Context, DC, D->getLocation(),
+                           D->getDeclName(), T, D->getTypeSourceInfo(),
+                           D->getStorageClass(),
+                           D->isInlineSpecified(), D->hasWrittenPrototype());
+  Function->setLexicalDeclContext(Owner);
+
+  // Attach the parameters
+  for (unsigned P = 0; P < Params.size(); ++P)
+    Params[P]->setOwningFunction(Function);
+  Function->setParams(SemaRef.Context, Params.data(), Params.size());
+
+  if (TemplateParams) {
+    // Our resulting instantiation is actually a function template, since we
+    // are substituting only the outer template parameters. For example, given
+    //
+    //   template<typename T>
+    //   struct X {
+    //     template<typename U> friend void f(T, U);
+    //   };
+    //
+    //   X<int> x;
+    //
+    // We are instantiating the friend function template "f" within X<int>, 
+    // which means substituting int for T, but leaving "f" as a friend function
+    // template.
+    // Build the function template itself.
+    FunctionTemplate = FunctionTemplateDecl::Create(SemaRef.Context, Owner,
+                                                    Function->getLocation(),
+                                                    Function->getDeclName(),
+                                                    TemplateParams, Function);
+    Function->setDescribedFunctionTemplate(FunctionTemplate);
+    FunctionTemplate->setLexicalDeclContext(D->getLexicalDeclContext());
+  } else if (FunctionTemplate) {
+    // Record this function template specialization.
+    Function->setFunctionTemplateSpecialization(SemaRef.Context,
+                                                FunctionTemplate,
+                                                &TemplateArgs.getInnermost(),
+                                                InsertPos);
+  }
+    
+  if (InitFunctionInstantiation(Function, D))
+    Function->setInvalidDecl();
+
+  bool Redeclaration = false;
+  bool OverloadableAttrRequired = false;
+    
+  LookupResult Previous(SemaRef, Function->getDeclName(), SourceLocation(),
+                        Sema::LookupOrdinaryName, Sema::ForRedeclaration);
+
+  if (TemplateParams || !FunctionTemplate) {
+    // Look only into the namespace where the friend would be declared to 
+    // find a previous declaration. This is the innermost enclosing namespace, 
+    // as described in ActOnFriendFunctionDecl.
+    SemaRef.LookupQualifiedName(Previous, DC);
+    
+    // In C++, the previous declaration we find might be a tag type
+    // (class or enum). In this case, the new declaration will hide the
+    // tag type. Note that this does does not apply if we're declaring a
+    // typedef (C++ [dcl.typedef]p4).
+    if (Previous.isSingleTagDecl())
+      Previous.clear();
+  }
+  
+  SemaRef.CheckFunctionDeclaration(/*Scope*/ 0, Function, Previous,
+                                   false, Redeclaration,
+                                   /*FIXME:*/OverloadableAttrRequired);
+
+  // If the original function was part of a friend declaration,
+  // inherit its namespace state and add it to the owner.
+  NamedDecl *FromFriendD 
+      = TemplateParams? cast<NamedDecl>(D->getDescribedFunctionTemplate()) : D;
+  if (FromFriendD->getFriendObjectKind()) {
+    NamedDecl *ToFriendD = 0;
+    NamedDecl *PrevDecl;
+    if (TemplateParams) {
+      ToFriendD = cast<NamedDecl>(FunctionTemplate);
+      PrevDecl = FunctionTemplate->getPreviousDeclaration();
+    } else {
+      ToFriendD = Function;
+      PrevDecl = Function->getPreviousDeclaration();
+    }
+    ToFriendD->setObjectOfFriendDecl(PrevDecl != NULL);
+    if (!Owner->isDependentContext() && !PrevDecl)
+      DC->makeDeclVisibleInContext(ToFriendD, /* Recoverable = */ false);
+
+    if (!TemplateParams)
+      Function->setInstantiationOfMemberFunction(D, TSK_ImplicitInstantiation);
+  }
+
+  return Function;
+}
+
+Decl *
+TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D,
+                                      TemplateParameterList *TemplateParams) {
+  FunctionTemplateDecl *FunctionTemplate = D->getDescribedFunctionTemplate();
+  void *InsertPos = 0;
+  if (FunctionTemplate && !TemplateParams) {
+    // We are creating a function template specialization from a function
+    // template. Check whether there is already a function template
+    // specialization for this particular set of template arguments.
+    llvm::FoldingSetNodeID ID;
+    FunctionTemplateSpecializationInfo::Profile(ID,
+                            TemplateArgs.getInnermost().getFlatArgumentList(),
+                                      TemplateArgs.getInnermost().flat_size(),
+                                                SemaRef.Context);
+
+    FunctionTemplateSpecializationInfo *Info
+      = FunctionTemplate->getSpecializations().FindNodeOrInsertPos(ID,
+                                                                   InsertPos);
+
+    // If we already have a function template specialization, return it.
+    if (Info)
+      return Info->Function;
+  }
+
+  bool MergeWithParentScope = (TemplateParams != 0) ||
+    !(isa<Decl>(Owner) && 
+      cast<Decl>(Owner)->isDefinedOutsideFunctionOrMethod());
+  Sema::LocalInstantiationScope Scope(SemaRef, MergeWithParentScope);
+
+  llvm::SmallVector<ParmVarDecl *, 4> Params;
+  QualType T = SubstFunctionType(D, Params);
+  if (T.isNull())
+    return 0;
+
+  // Build the instantiated method declaration.
+  CXXRecordDecl *Record = cast<CXXRecordDecl>(Owner);
+  CXXMethodDecl *Method = 0;
+
+  DeclarationName Name = D->getDeclName();
+  if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(D)) {
+    QualType ClassTy = SemaRef.Context.getTypeDeclType(Record);
+    Name = SemaRef.Context.DeclarationNames.getCXXConstructorName(
+                                    SemaRef.Context.getCanonicalType(ClassTy));
+    Method = CXXConstructorDecl::Create(SemaRef.Context, Record,
+                                        Constructor->getLocation(),
+                                        Name, T,
+                                        Constructor->getTypeSourceInfo(),
+                                        Constructor->isExplicit(),
+                                        Constructor->isInlineSpecified(), false);
+  } else if (CXXDestructorDecl *Destructor = dyn_cast<CXXDestructorDecl>(D)) {
+    QualType ClassTy = SemaRef.Context.getTypeDeclType(Record);
+    Name = SemaRef.Context.DeclarationNames.getCXXDestructorName(
+                                   SemaRef.Context.getCanonicalType(ClassTy));
+    Method = CXXDestructorDecl::Create(SemaRef.Context, Record,
+                                       Destructor->getLocation(), Name,
+                                       T, Destructor->isInlineSpecified(), false);
+  } else if (CXXConversionDecl *Conversion = dyn_cast<CXXConversionDecl>(D)) {
+    CanQualType ConvTy
+      = SemaRef.Context.getCanonicalType(
+                                      T->getAs<FunctionType>()->getResultType());
+    Name = SemaRef.Context.DeclarationNames.getCXXConversionFunctionName(
+                                                                      ConvTy);
+    Method = CXXConversionDecl::Create(SemaRef.Context, Record,
+                                       Conversion->getLocation(), Name,
+                                       T, Conversion->getTypeSourceInfo(),
+                                       Conversion->isInlineSpecified(),
+                                       Conversion->isExplicit());
+  } else {
+    Method = CXXMethodDecl::Create(SemaRef.Context, Record, D->getLocation(),
+                                   D->getDeclName(), T, D->getTypeSourceInfo(),
+                                   D->isStatic(), D->isInlineSpecified());
+  }
+
+  if (TemplateParams) {
+    // Our resulting instantiation is actually a function template, since we
+    // are substituting only the outer template parameters. For example, given
+    //
+    //   template<typename T>
+    //   struct X {
+    //     template<typename U> void f(T, U);
+    //   };
+    //
+    //   X<int> x;
+    //
+    // We are instantiating the member template "f" within X<int>, which means
+    // substituting int for T, but leaving "f" as a member function template.
+    // Build the function template itself.
+    FunctionTemplate = FunctionTemplateDecl::Create(SemaRef.Context, Record,
+                                                    Method->getLocation(),
+                                                    Method->getDeclName(),
+                                                    TemplateParams, Method);
+    if (D->isOutOfLine())
+      FunctionTemplate->setLexicalDeclContext(D->getLexicalDeclContext());
+    Method->setDescribedFunctionTemplate(FunctionTemplate);
+  } else if (FunctionTemplate) {
+    // Record this function template specialization.
+    Method->setFunctionTemplateSpecialization(SemaRef.Context,
+                                              FunctionTemplate,
+                                              &TemplateArgs.getInnermost(),
+                                              InsertPos);
+  } else {
+    // Record that this is an instantiation of a member function.
+    Method->setInstantiationOfMemberFunction(D, TSK_ImplicitInstantiation);
+  }
+  
+  // If we are instantiating a member function defined
+  // out-of-line, the instantiation will have the same lexical
+  // context (which will be a namespace scope) as the template.
+  if (D->isOutOfLine())
+    Method->setLexicalDeclContext(D->getLexicalDeclContext());
+
+  // Attach the parameters
+  for (unsigned P = 0; P < Params.size(); ++P)
+    Params[P]->setOwningFunction(Method);
+  Method->setParams(SemaRef.Context, Params.data(), Params.size());
+
+  if (InitMethodInstantiation(Method, D))
+    Method->setInvalidDecl();
+
+  LookupResult Previous(SemaRef, Name, SourceLocation(),
+                        Sema::LookupOrdinaryName, Sema::ForRedeclaration);
+
+  if (!FunctionTemplate || TemplateParams) {
+    SemaRef.LookupQualifiedName(Previous, Owner);
+
+    // In C++, the previous declaration we find might be a tag type
+    // (class or enum). In this case, the new declaration will hide the
+    // tag type. Note that this does does not apply if we're declaring a
+    // typedef (C++ [dcl.typedef]p4).
+    if (Previous.isSingleTagDecl())
+      Previous.clear();
+  }
+
+  bool Redeclaration = false;
+  bool OverloadableAttrRequired = false;
+  SemaRef.CheckFunctionDeclaration(0, Method, Previous, false, Redeclaration,
+                                   /*FIXME:*/OverloadableAttrRequired);
+
+  if (D->isPure())
+    SemaRef.CheckPureMethod(Method, SourceRange());
+
+  Method->setAccess(D->getAccess());
+
+  if (!FunctionTemplate && (!Method->isInvalidDecl() || Previous.empty()) &&
+      !Method->getFriendObjectKind())
+    Owner->addDecl(Method);
+
+  return Method;
+}
+
+Decl *TemplateDeclInstantiator::VisitCXXConstructorDecl(CXXConstructorDecl *D) {
+  return VisitCXXMethodDecl(D);
+}
+
+Decl *TemplateDeclInstantiator::VisitCXXDestructorDecl(CXXDestructorDecl *D) {
+  return VisitCXXMethodDecl(D);
+}
+
+Decl *TemplateDeclInstantiator::VisitCXXConversionDecl(CXXConversionDecl *D) {
+  return VisitCXXMethodDecl(D);
+}
+
+ParmVarDecl *TemplateDeclInstantiator::VisitParmVarDecl(ParmVarDecl *D) {
+  QualType T;
+  TypeSourceInfo *DI = D->getTypeSourceInfo();
+  if (DI) {
+    DI = SemaRef.SubstType(DI, TemplateArgs, D->getLocation(),
+                           D->getDeclName());
+    if (DI) T = DI->getType();
+  } else {
+    T = SemaRef.SubstType(D->getType(), TemplateArgs, D->getLocation(),
+                          D->getDeclName());
+    DI = 0;
+  }
+
+  if (T.isNull())
+    return 0;
+
+  T = SemaRef.adjustParameterType(T);
+
+  // Allocate the parameter
+  ParmVarDecl *Param
+    = ParmVarDecl::Create(SemaRef.Context,
+                          SemaRef.Context.getTranslationUnitDecl(),
+                          D->getLocation(),
+                          D->getIdentifier(), T, DI, D->getStorageClass(), 0);
+
+  // Mark the default argument as being uninstantiated.
+  if (D->hasUninstantiatedDefaultArg())
+    Param->setUninstantiatedDefaultArg(D->getUninstantiatedDefaultArg());
+  else if (Expr *Arg = D->getDefaultArg())
+    Param->setUninstantiatedDefaultArg(Arg);
+  
+  // Note: we don't try to instantiate function parameters until after
+  // we've instantiated the function's type. Therefore, we don't have
+  // to check for 'void' parameter types here.
+  SemaRef.CurrentInstantiationScope->InstantiatedLocal(D, Param);
+  return Param;
+}
+
+Decl *TemplateDeclInstantiator::VisitTemplateTypeParmDecl(
+                                                    TemplateTypeParmDecl *D) {
+  // TODO: don't always clone when decls are refcounted.
+  const Type* T = D->getTypeForDecl();
+  assert(T->isTemplateTypeParmType());
+  const TemplateTypeParmType *TTPT = T->getAs<TemplateTypeParmType>();
+
+  TemplateTypeParmDecl *Inst =
+    TemplateTypeParmDecl::Create(SemaRef.Context, Owner, D->getLocation(),
+                                 TTPT->getDepth() - 1, TTPT->getIndex(),
+                                 TTPT->getName(),
+                                 D->wasDeclaredWithTypename(),
+                                 D->isParameterPack());
+
+  if (D->hasDefaultArgument())
+    Inst->setDefaultArgument(D->getDefaultArgumentInfo(), false);  
+
+  // Introduce this template parameter's instantiation into the instantiation 
+  // scope.
+  SemaRef.CurrentInstantiationScope->InstantiatedLocal(D, Inst);
+  
+  return Inst;
+}
+
+Decl *TemplateDeclInstantiator::VisitNonTypeTemplateParmDecl(
+                                                 NonTypeTemplateParmDecl *D) {
+  // Substitute into the type of the non-type template parameter.
+  QualType T;
+  TypeSourceInfo *DI = D->getTypeSourceInfo();
+  if (DI) {
+    DI = SemaRef.SubstType(DI, TemplateArgs, D->getLocation(),
+                           D->getDeclName());
+    if (DI) T = DI->getType();
+  } else {
+    T = SemaRef.SubstType(D->getType(), TemplateArgs, D->getLocation(),
+                          D->getDeclName());
+    DI = 0;
+  }
+  if (T.isNull())
+    return 0;
+  
+  // Check that this type is acceptable for a non-type template parameter.
+  bool Invalid = false;
+  T = SemaRef.CheckNonTypeTemplateParameterType(T, D->getLocation());
+  if (T.isNull()) {
+    T = SemaRef.Context.IntTy;
+    Invalid = true;
+  }
+  
+  NonTypeTemplateParmDecl *Param
+    = NonTypeTemplateParmDecl::Create(SemaRef.Context, Owner, D->getLocation(),
+                                      D->getDepth() - 1, D->getPosition(),
+                                      D->getIdentifier(), T, DI);
+  if (Invalid)
+    Param->setInvalidDecl();
+  
+  Param->setDefaultArgument(D->getDefaultArgument());
+  
+  // Introduce this template parameter's instantiation into the instantiation 
+  // scope.
+  SemaRef.CurrentInstantiationScope->InstantiatedLocal(D, Param);
+  return Param;
+}
+
+Decl *
+TemplateDeclInstantiator::VisitTemplateTemplateParmDecl(
+                                                  TemplateTemplateParmDecl *D) {
+  // Instantiate the template parameter list of the template template parameter.
+  TemplateParameterList *TempParams = D->getTemplateParameters();
+  TemplateParameterList *InstParams;
+  {
+    // Perform the actual substitution of template parameters within a new,
+    // local instantiation scope.
+    Sema::LocalInstantiationScope Scope(SemaRef);
+    InstParams = SubstTemplateParams(TempParams);
+    if (!InstParams)
+      return NULL;
+  }  
+  
+  // Build the template template parameter.
+  TemplateTemplateParmDecl *Param
+    = TemplateTemplateParmDecl::Create(SemaRef.Context, Owner, D->getLocation(),
+                                       D->getDepth() - 1, D->getPosition(),
+                                       D->getIdentifier(), InstParams);
+  Param->setDefaultArgument(D->getDefaultArgument());
+  
+  // Introduce this template parameter's instantiation into the instantiation 
+  // scope.
+  SemaRef.CurrentInstantiationScope->InstantiatedLocal(D, Param);
+  
+  return Param;
+}
+
+Decl *TemplateDeclInstantiator::VisitUsingDirectiveDecl(UsingDirectiveDecl *D) {
+  // Using directives are never dependent, so they require no explicit
+  
+  UsingDirectiveDecl *Inst
+    = UsingDirectiveDecl::Create(SemaRef.Context, Owner, D->getLocation(),
+                                 D->getNamespaceKeyLocation(), 
+                                 D->getQualifierRange(), D->getQualifier(), 
+                                 D->getIdentLocation(), 
+                                 D->getNominatedNamespace(), 
+                                 D->getCommonAncestor());
+  Owner->addDecl(Inst);
+  return Inst;
+}
+
+Decl *TemplateDeclInstantiator::VisitUsingDecl(UsingDecl *D) {
+  // The nested name specifier is non-dependent, so no transformation
+  // is required.
+
+  // We only need to do redeclaration lookups if we're in a class
+  // scope (in fact, it's not really even possible in non-class
+  // scopes).
+  bool CheckRedeclaration = Owner->isRecord();
+
+  LookupResult Prev(SemaRef, D->getDeclName(), D->getLocation(),
+                    Sema::LookupUsingDeclName, Sema::ForRedeclaration);
+
+  UsingDecl *NewUD = UsingDecl::Create(SemaRef.Context, Owner,
+                                       D->getLocation(),
+                                       D->getNestedNameRange(),
+                                       D->getUsingLocation(),
+                                       D->getTargetNestedNameDecl(),
+                                       D->getDeclName(),
+                                       D->isTypeName());
+
+  CXXScopeSpec SS;
+  SS.setScopeRep(D->getTargetNestedNameDecl());
+  SS.setRange(D->getNestedNameRange());
+
+  if (CheckRedeclaration) {
+    Prev.setHideTags(false);
+    SemaRef.LookupQualifiedName(Prev, Owner);
+
+    // Check for invalid redeclarations.
+    if (SemaRef.CheckUsingDeclRedeclaration(D->getUsingLocation(),
+                                            D->isTypeName(), SS,
+                                            D->getLocation(), Prev))
+      NewUD->setInvalidDecl();
+
+  }
+
+  if (!NewUD->isInvalidDecl() &&
+      SemaRef.CheckUsingDeclQualifier(D->getUsingLocation(), SS,
+                                      D->getLocation()))
+    NewUD->setInvalidDecl();
+
+  SemaRef.Context.setInstantiatedFromUsingDecl(NewUD, D);
+  NewUD->setAccess(D->getAccess());
+  Owner->addDecl(NewUD);
+
+  // Don't process the shadow decls for an invalid decl.
+  if (NewUD->isInvalidDecl())
+    return NewUD;
+
+  bool isFunctionScope = Owner->isFunctionOrMethod();
+
+  // Process the shadow decls.
+  for (UsingDecl::shadow_iterator I = D->shadow_begin(), E = D->shadow_end();
+         I != E; ++I) {
+    UsingShadowDecl *Shadow = *I;
+    NamedDecl *InstTarget =
+      cast<NamedDecl>(SemaRef.FindInstantiatedDecl(Shadow->getTargetDecl(),
+                                                   TemplateArgs));
+
+    if (CheckRedeclaration &&
+        SemaRef.CheckUsingShadowDecl(NewUD, InstTarget, Prev))
+      continue;
+
+    UsingShadowDecl *InstShadow
+      = SemaRef.BuildUsingShadowDecl(/*Scope*/ 0, NewUD, InstTarget);
+    SemaRef.Context.setInstantiatedFromUsingShadowDecl(InstShadow, Shadow);
+
+    if (isFunctionScope)
+      SemaRef.CurrentInstantiationScope->InstantiatedLocal(Shadow, InstShadow);
+  }
+
+  return NewUD;
+}
+
+Decl *TemplateDeclInstantiator::VisitUsingShadowDecl(UsingShadowDecl *D) {
+  // Ignore these;  we handle them in bulk when processing the UsingDecl.
+  return 0;
+}
+
+Decl * TemplateDeclInstantiator
+    ::VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D) {
+  NestedNameSpecifier *NNS =
+    SemaRef.SubstNestedNameSpecifier(D->getTargetNestedNameSpecifier(),
+                                     D->getTargetNestedNameRange(),
+                                     TemplateArgs);
+  if (!NNS)
+    return 0;
+
+  CXXScopeSpec SS;
+  SS.setRange(D->getTargetNestedNameRange());
+  SS.setScopeRep(NNS);
+
+  NamedDecl *UD =
+    SemaRef.BuildUsingDeclaration(/*Scope*/ 0, D->getAccess(),
+                                  D->getUsingLoc(), SS, D->getLocation(),
+                                  D->getDeclName(), 0,
+                                  /*instantiation*/ true,
+                                  /*typename*/ true, D->getTypenameLoc());
+  if (UD)
+    SemaRef.Context.setInstantiatedFromUsingDecl(cast<UsingDecl>(UD), D);
+
+  return UD;
+}
+
+Decl * TemplateDeclInstantiator
+    ::VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D) {
+  NestedNameSpecifier *NNS =
+    SemaRef.SubstNestedNameSpecifier(D->getTargetNestedNameSpecifier(),
+                                     D->getTargetNestedNameRange(),
+                                     TemplateArgs);
+  if (!NNS)
+    return 0;
+
+  CXXScopeSpec SS;
+  SS.setRange(D->getTargetNestedNameRange());
+  SS.setScopeRep(NNS);
+
+  NamedDecl *UD =
+    SemaRef.BuildUsingDeclaration(/*Scope*/ 0, D->getAccess(),
+                                  D->getUsingLoc(), SS, D->getLocation(),
+                                  D->getDeclName(), 0,
+                                  /*instantiation*/ true,
+                                  /*typename*/ false, SourceLocation());
+  if (UD)
+    SemaRef.Context.setInstantiatedFromUsingDecl(cast<UsingDecl>(UD), D);
+
+  return UD;
+}
+
+Decl *Sema::SubstDecl(Decl *D, DeclContext *Owner,
+                      const MultiLevelTemplateArgumentList &TemplateArgs) {
+  TemplateDeclInstantiator Instantiator(*this, Owner, TemplateArgs);
+  return Instantiator.Visit(D);
+}
+
+/// \brief Instantiates a nested template parameter list in the current
+/// instantiation context.
+///
+/// \param L The parameter list to instantiate
+///
+/// \returns NULL if there was an error
+TemplateParameterList *
+TemplateDeclInstantiator::SubstTemplateParams(TemplateParameterList *L) {
+  // Get errors for all the parameters before bailing out.
+  bool Invalid = false;
+
+  unsigned N = L->size();
+  typedef llvm::SmallVector<NamedDecl *, 8> ParamVector;
+  ParamVector Params;
+  Params.reserve(N);
+  for (TemplateParameterList::iterator PI = L->begin(), PE = L->end();
+       PI != PE; ++PI) {
+    NamedDecl *D = cast_or_null<NamedDecl>(Visit(*PI));
+    Params.push_back(D);
+    Invalid = Invalid || !D || D->isInvalidDecl();
+  }
+
+  // Clean up if we had an error.
+  if (Invalid) {
+    for (ParamVector::iterator PI = Params.begin(), PE = Params.end();
+         PI != PE; ++PI)
+      if (*PI)
+        (*PI)->Destroy(SemaRef.Context);
+    return NULL;
+  }
+
+  TemplateParameterList *InstL
+    = TemplateParameterList::Create(SemaRef.Context, L->getTemplateLoc(),
+                                    L->getLAngleLoc(), &Params.front(), N,
+                                    L->getRAngleLoc());
+  return InstL;
+}
+
+/// \brief Instantiate the declaration of a class template partial 
+/// specialization.
+///
+/// \param ClassTemplate the (instantiated) class template that is partially
+// specialized by the instantiation of \p PartialSpec.
+///
+/// \param PartialSpec the (uninstantiated) class template partial 
+/// specialization that we are instantiating.
+///
+/// \returns true if there was an error, false otherwise.
+bool 
+TemplateDeclInstantiator::InstantiateClassTemplatePartialSpecialization(
+                                            ClassTemplateDecl *ClassTemplate,
+                          ClassTemplatePartialSpecializationDecl *PartialSpec) {
+  // Create a local instantiation scope for this class template partial
+  // specialization, which will contain the instantiations of the template
+  // parameters.
+  Sema::LocalInstantiationScope Scope(SemaRef);
+  
+  // Substitute into the template parameters of the class template partial
+  // specialization.
+  TemplateParameterList *TempParams = PartialSpec->getTemplateParameters();
+  TemplateParameterList *InstParams = SubstTemplateParams(TempParams);
+  if (!InstParams)
+    return true;
+  
+  // Substitute into the template arguments of the class template partial
+  // specialization.
+  const TemplateArgumentLoc *PartialSpecTemplateArgs
+    = PartialSpec->getTemplateArgsAsWritten();
+  unsigned N = PartialSpec->getNumTemplateArgsAsWritten();
+
+  TemplateArgumentListInfo InstTemplateArgs; // no angle locations
+  for (unsigned I = 0; I != N; ++I) {
+    TemplateArgumentLoc Loc;
+    if (SemaRef.Subst(PartialSpecTemplateArgs[I], Loc, TemplateArgs))
+      return true;
+    InstTemplateArgs.addArgument(Loc);
+  }
+  
+
+  // Check that the template argument list is well-formed for this
+  // class template.
+  TemplateArgumentListBuilder Converted(ClassTemplate->getTemplateParameters(), 
+                                        InstTemplateArgs.size());
+  if (SemaRef.CheckTemplateArgumentList(ClassTemplate, 
+                                        PartialSpec->getLocation(),
+                                        InstTemplateArgs, 
+                                        false,
+                                        Converted))
+    return true;
+
+  // Figure out where to insert this class template partial specialization
+  // in the member template's set of class template partial specializations.
+  llvm::FoldingSetNodeID ID;
+  ClassTemplatePartialSpecializationDecl::Profile(ID,
+                                                  Converted.getFlatArguments(),
+                                                  Converted.flatSize(),
+                                                  SemaRef.Context);
+  void *InsertPos = 0;
+  ClassTemplateSpecializationDecl *PrevDecl
+    = ClassTemplate->getPartialSpecializations().FindNodeOrInsertPos(ID,
+                                                                     InsertPos);
+  
+  // Build the canonical type that describes the converted template
+  // arguments of the class template partial specialization.
+  QualType CanonType 
+    = SemaRef.Context.getTemplateSpecializationType(TemplateName(ClassTemplate),
+                                                  Converted.getFlatArguments(),
+                                                    Converted.flatSize());
+
+  // Build the fully-sugared type for this class template
+  // specialization as the user wrote in the specialization
+  // itself. This means that we'll pretty-print the type retrieved
+  // from the specialization's declaration the way that the user
+  // actually wrote the specialization, rather than formatting the
+  // name based on the "canonical" representation used to store the
+  // template arguments in the specialization.
+  QualType WrittenTy
+    = SemaRef.Context.getTemplateSpecializationType(TemplateName(ClassTemplate),
+                                                    InstTemplateArgs,
+                                                    CanonType);
+  
+  if (PrevDecl) {
+    // We've already seen a partial specialization with the same template
+    // parameters and template arguments. This can happen, for example, when
+    // substituting the outer template arguments ends up causing two
+    // class template partial specializations of a member class template
+    // to have identical forms, e.g.,
+    //
+    //   template<typename T, typename U>
+    //   struct Outer {
+    //     template<typename X, typename Y> struct Inner;
+    //     template<typename Y> struct Inner<T, Y>;
+    //     template<typename Y> struct Inner<U, Y>;
+    //   };
+    //
+    //   Outer<int, int> outer; // error: the partial specializations of Inner
+    //                          // have the same signature.
+    SemaRef.Diag(PartialSpec->getLocation(), diag::err_partial_spec_redeclared)
+      << WrittenTy;
+    SemaRef.Diag(PrevDecl->getLocation(), diag::note_prev_partial_spec_here)
+      << SemaRef.Context.getTypeDeclType(PrevDecl);
+    return true;
+  }
+  
+  
+  // Create the class template partial specialization declaration.
+  ClassTemplatePartialSpecializationDecl *InstPartialSpec
+    = ClassTemplatePartialSpecializationDecl::Create(SemaRef.Context, Owner, 
+                                                     PartialSpec->getLocation(), 
+                                                     InstParams,
+                                                     ClassTemplate, 
+                                                     Converted,
+                                                     InstTemplateArgs,
+                                                     0);
+  InstPartialSpec->setInstantiatedFromMember(PartialSpec);
+  InstPartialSpec->setTypeAsWritten(WrittenTy);
+  
+  // Add this partial specialization to the set of class template partial
+  // specializations.
+  ClassTemplate->getPartialSpecializations().InsertNode(InstPartialSpec,
+                                                        InsertPos);
+  return false;
+}
+
+/// \brief Does substitution on the type of the given function, including
+/// all of the function parameters.
+///
+/// \param D The function whose type will be the basis of the substitution
+///
+/// \param Params the instantiated parameter declarations
+
+/// \returns the instantiated function's type if successful, a NULL
+/// type if there was an error.
+QualType
+TemplateDeclInstantiator::SubstFunctionType(FunctionDecl *D,
+                              llvm::SmallVectorImpl<ParmVarDecl *> &Params) {
+  bool InvalidDecl = false;
+
+  // Substitute all of the function's formal parameter types.
+  TemplateDeclInstantiator ParamInstantiator(SemaRef, 0, TemplateArgs);
+  llvm::SmallVector<QualType, 4> ParamTys;
+  for (FunctionDecl::param_iterator P = D->param_begin(),
+                                 PEnd = D->param_end();
+       P != PEnd; ++P) {
+    if (ParmVarDecl *PInst = ParamInstantiator.VisitParmVarDecl(*P)) {
+      if (PInst->getType()->isVoidType()) {
+        SemaRef.Diag(PInst->getLocation(), diag::err_param_with_void_type);
+        PInst->setInvalidDecl();
+      } else if (SemaRef.RequireNonAbstractType(PInst->getLocation(),
+                                                PInst->getType(),
+                                                diag::err_abstract_type_in_decl,
+                                                Sema::AbstractParamType))
+        PInst->setInvalidDecl();
+
+      Params.push_back(PInst);
+      ParamTys.push_back(PInst->getType());
+
+      if (PInst->isInvalidDecl())
+        InvalidDecl = true;
+    } else
+      InvalidDecl = true;
+  }
+
+  // FIXME: Deallocate dead declarations.
+  if (InvalidDecl)
+    return QualType();
+
+  const FunctionProtoType *Proto = D->getType()->getAs<FunctionProtoType>();
+  assert(Proto && "Missing prototype?");
+  QualType ResultType
+    = SemaRef.SubstType(Proto->getResultType(), TemplateArgs,
+                        D->getLocation(), D->getDeclName());
+  if (ResultType.isNull())
+    return QualType();
+
+  return SemaRef.BuildFunctionType(ResultType, ParamTys.data(), ParamTys.size(),
+                                   Proto->isVariadic(), Proto->getTypeQuals(),
+                                   D->getLocation(), D->getDeclName());
+}
+
+/// \brief Initializes the common fields of an instantiation function
+/// declaration (New) from the corresponding fields of its template (Tmpl).
+///
+/// \returns true if there was an error
+bool
+TemplateDeclInstantiator::InitFunctionInstantiation(FunctionDecl *New,
+                                                    FunctionDecl *Tmpl) {
+  if (Tmpl->isDeleted())
+    New->setDeleted();
+
+  // If we are performing substituting explicitly-specified template arguments
+  // or deduced template arguments into a function template and we reach this
+  // point, we are now past the point where SFINAE applies and have committed
+  // to keeping the new function template specialization. We therefore
+  // convert the active template instantiation for the function template
+  // into a template instantiation for this specific function template
+  // specialization, which is not a SFINAE context, so that we diagnose any
+  // further errors in the declaration itself.
+  typedef Sema::ActiveTemplateInstantiation ActiveInstType;
+  ActiveInstType &ActiveInst = SemaRef.ActiveTemplateInstantiations.back();
+  if (ActiveInst.Kind == ActiveInstType::ExplicitTemplateArgumentSubstitution ||
+      ActiveInst.Kind == ActiveInstType::DeducedTemplateArgumentSubstitution) {
+    if (FunctionTemplateDecl *FunTmpl
+          = dyn_cast<FunctionTemplateDecl>((Decl *)ActiveInst.Entity)) {
+      assert(FunTmpl->getTemplatedDecl() == Tmpl &&
+             "Deduction from the wrong function template?");
+      (void) FunTmpl;
+      ActiveInst.Kind = ActiveInstType::TemplateInstantiation;
+      ActiveInst.Entity = reinterpret_cast<uintptr_t>(New);
+      --SemaRef.NonInstantiationEntries;
+    }
+  }
+
+  const FunctionProtoType *Proto = Tmpl->getType()->getAs<FunctionProtoType>();
+  assert(Proto && "Function template without prototype?");
+
+  if (Proto->hasExceptionSpec() || Proto->hasAnyExceptionSpec() ||
+      Proto->getNoReturnAttr()) {
+    // The function has an exception specification or a "noreturn"
+    // attribute. Substitute into each of the exception types.
+    llvm::SmallVector<QualType, 4> Exceptions;
+    for (unsigned I = 0, N = Proto->getNumExceptions(); I != N; ++I) {
+      // FIXME: Poor location information!
+      QualType T
+        = SemaRef.SubstType(Proto->getExceptionType(I), TemplateArgs,
+                            New->getLocation(), New->getDeclName());
+      if (T.isNull() || 
+          SemaRef.CheckSpecifiedExceptionType(T, New->getLocation()))
+        continue;
+
+      Exceptions.push_back(T);
+    }
+
+    // Rebuild the function type 
+
+    const FunctionProtoType *NewProto
+      = New->getType()->getAs<FunctionProtoType>();
+    assert(NewProto && "Template instantiation without function prototype?");
+    New->setType(SemaRef.Context.getFunctionType(NewProto->getResultType(),
+                                                 NewProto->arg_type_begin(),
+                                                 NewProto->getNumArgs(),
+                                                 NewProto->isVariadic(),
+                                                 NewProto->getTypeQuals(),
+                                                 Proto->hasExceptionSpec(),
+                                                 Proto->hasAnyExceptionSpec(),
+                                                 Exceptions.size(),
+                                                 Exceptions.data(),
+                                                 Proto->getNoReturnAttr(),
+                                                 Proto->getCallConv()));
+  }
+
+  return false;
+}
+
+/// \brief Initializes common fields of an instantiated method
+/// declaration (New) from the corresponding fields of its template
+/// (Tmpl).
+///
+/// \returns true if there was an error
+bool
+TemplateDeclInstantiator::InitMethodInstantiation(CXXMethodDecl *New,
+                                                  CXXMethodDecl *Tmpl) {
+  if (InitFunctionInstantiation(New, Tmpl))
+    return true;
+
+  CXXRecordDecl *Record = cast<CXXRecordDecl>(Owner);
+  New->setAccess(Tmpl->getAccess());
+  if (Tmpl->isVirtualAsWritten())
+    Record->setMethodAsVirtual(New);
+
+  // FIXME: attributes
+  // FIXME: New needs a pointer to Tmpl
+  return false;
+}
+
+/// \brief Instantiate the definition of the given function from its
+/// template.
+///
+/// \param PointOfInstantiation the point at which the instantiation was
+/// required. Note that this is not precisely a "point of instantiation"
+/// for the function, but it's close.
+///
+/// \param Function the already-instantiated declaration of a
+/// function template specialization or member function of a class template
+/// specialization.
+///
+/// \param Recursive if true, recursively instantiates any functions that
+/// are required by this instantiation.
+///
+/// \param DefinitionRequired if true, then we are performing an explicit
+/// instantiation where the body of the function is required. Complain if
+/// there is no such body.
+void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,
+                                         FunctionDecl *Function,
+                                         bool Recursive,
+                                         bool DefinitionRequired) {
+  if (Function->isInvalidDecl())
+    return;
+
+  assert(!Function->getBody() && "Already instantiated!");
+
+  // Never instantiate an explicit specialization.
+  if (Function->getTemplateSpecializationKind() == TSK_ExplicitSpecialization)
+    return;
+  
+  // Find the function body that we'll be substituting.
+  const FunctionDecl *PatternDecl = Function->getTemplateInstantiationPattern();
+  Stmt *Pattern = 0;
+  if (PatternDecl)
+    Pattern = PatternDecl->getBody(PatternDecl);
+
+  if (!Pattern) {
+    if (DefinitionRequired) {
+      if (Function->getPrimaryTemplate())
+        Diag(PointOfInstantiation, 
+             diag::err_explicit_instantiation_undefined_func_template)
+          << Function->getPrimaryTemplate();
+      else
+        Diag(PointOfInstantiation, 
+             diag::err_explicit_instantiation_undefined_member)
+          << 1 << Function->getDeclName() << Function->getDeclContext();
+      
+      if (PatternDecl)
+        Diag(PatternDecl->getLocation(), 
+             diag::note_explicit_instantiation_here);
+    }
+      
+    return;
+  }
+
+  // C++0x [temp.explicit]p9:
+  //   Except for inline functions, other explicit instantiation declarations
+  //   have the effect of suppressing the implicit instantiation of the entity
+  //   to which they refer.
+  if (Function->getTemplateSpecializationKind()
+        == TSK_ExplicitInstantiationDeclaration &&
+      !PatternDecl->isInlined())
+    return;
+
+  InstantiatingTemplate Inst(*this, PointOfInstantiation, Function);
+  if (Inst)
+    return;
+
+  // If we're performing recursive template instantiation, create our own
+  // queue of pending implicit instantiations that we will instantiate later,
+  // while we're still within our own instantiation context.
+  std::deque<PendingImplicitInstantiation> SavedPendingImplicitInstantiations;
+  if (Recursive)
+    PendingImplicitInstantiations.swap(SavedPendingImplicitInstantiations);
+
+  ActOnStartOfFunctionDef(0, DeclPtrTy::make(Function));
+
+  // Introduce a new scope where local variable instantiations will be
+  // recorded, unless we're actually a member function within a local
+  // class, in which case we need to merge our results with the parent
+  // scope (of the enclosing function).
+  bool MergeWithParentScope = false;
+  if (CXXRecordDecl *Rec = dyn_cast<CXXRecordDecl>(Function->getDeclContext()))
+    MergeWithParentScope = Rec->isLocalClass();
+
+  LocalInstantiationScope Scope(*this, MergeWithParentScope);
+
+  // Introduce the instantiated function parameters into the local
+  // instantiation scope.
+  for (unsigned I = 0, N = PatternDecl->getNumParams(); I != N; ++I)
+    Scope.InstantiatedLocal(PatternDecl->getParamDecl(I),
+                            Function->getParamDecl(I));
+
+  // Enter the scope of this instantiation. We don't use
+  // PushDeclContext because we don't have a scope.
+  DeclContext *PreviousContext = CurContext;
+  CurContext = Function;
+
+  MultiLevelTemplateArgumentList TemplateArgs =
+    getTemplateInstantiationArgs(Function);
+
+  // If this is a constructor, instantiate the member initializers.
+  if (const CXXConstructorDecl *Ctor =
+        dyn_cast<CXXConstructorDecl>(PatternDecl)) {
+    InstantiateMemInitializers(cast<CXXConstructorDecl>(Function), Ctor,
+                               TemplateArgs);
+  }
+
+  // Instantiate the function body.
+  OwningStmtResult Body = SubstStmt(Pattern, TemplateArgs);
+
+  if (Body.isInvalid())
+    Function->setInvalidDecl();
+  
+  ActOnFinishFunctionBody(DeclPtrTy::make(Function), move(Body),
+                          /*IsInstantiation=*/true);
+
+  CurContext = PreviousContext;
+
+  DeclGroupRef DG(Function);
+  Consumer.HandleTopLevelDecl(DG);
+
+  // This class may have local implicit instantiations that need to be
+  // instantiation within this scope.
+  PerformPendingImplicitInstantiations(/*LocalOnly=*/true);
+  Scope.Exit();
+
+  if (Recursive) {
+    // Instantiate any pending implicit instantiations found during the
+    // instantiation of this template.
+    PerformPendingImplicitInstantiations();
+
+    // Restore the set of pending implicit instantiations.
+    PendingImplicitInstantiations.swap(SavedPendingImplicitInstantiations);
+  }
+}
+
+/// \brief Instantiate the definition of the given variable from its
+/// template.
+///
+/// \param PointOfInstantiation the point at which the instantiation was
+/// required. Note that this is not precisely a "point of instantiation"
+/// for the function, but it's close.
+///
+/// \param Var the already-instantiated declaration of a static member
+/// variable of a class template specialization.
+///
+/// \param Recursive if true, recursively instantiates any functions that
+/// are required by this instantiation.
+///
+/// \param DefinitionRequired if true, then we are performing an explicit
+/// instantiation where an out-of-line definition of the member variable
+/// is required. Complain if there is no such definition.
+void Sema::InstantiateStaticDataMemberDefinition(
+                                          SourceLocation PointOfInstantiation,
+                                                 VarDecl *Var,
+                                                 bool Recursive,
+                                                 bool DefinitionRequired) {
+  if (Var->isInvalidDecl())
+    return;
+
+  // Find the out-of-line definition of this static data member.
+  VarDecl *Def = Var->getInstantiatedFromStaticDataMember();
+  assert(Def && "This data member was not instantiated from a template?");
+  assert(Def->isStaticDataMember() && "Not a static data member?");  
+  Def = Def->getOutOfLineDefinition();
+
+  if (!Def) {
+    // We did not find an out-of-line definition of this static data member,
+    // so we won't perform any instantiation. Rather, we rely on the user to
+    // instantiate this definition (or provide a specialization for it) in
+    // another translation unit.
+    if (DefinitionRequired) {
+      Def = Var->getInstantiatedFromStaticDataMember();
+      Diag(PointOfInstantiation, 
+           diag::err_explicit_instantiation_undefined_member)
+        << 2 << Var->getDeclName() << Var->getDeclContext();
+      Diag(Def->getLocation(), diag::note_explicit_instantiation_here);
+    }    
+    
+    return;
+  }
+
+  // Never instantiate an explicit specialization.
+  if (Var->getTemplateSpecializationKind() == TSK_ExplicitSpecialization)
+    return;
+  
+  // C++0x [temp.explicit]p9:
+  //   Except for inline functions, other explicit instantiation declarations
+  //   have the effect of suppressing the implicit instantiation of the entity
+  //   to which they refer.
+  if (Var->getTemplateSpecializationKind() 
+        == TSK_ExplicitInstantiationDeclaration)
+    return;
+
+  InstantiatingTemplate Inst(*this, PointOfInstantiation, Var);
+  if (Inst)
+    return;
+
+  // If we're performing recursive template instantiation, create our own
+  // queue of pending implicit instantiations that we will instantiate later,
+  // while we're still within our own instantiation context.
+  std::deque<PendingImplicitInstantiation> SavedPendingImplicitInstantiations;
+  if (Recursive)
+    PendingImplicitInstantiations.swap(SavedPendingImplicitInstantiations);
+
+  // Enter the scope of this instantiation. We don't use
+  // PushDeclContext because we don't have a scope.
+  DeclContext *PreviousContext = CurContext;
+  CurContext = Var->getDeclContext();
+
+  VarDecl *OldVar = Var;
+  Var = cast_or_null<VarDecl>(SubstDecl(Def, Var->getDeclContext(),
+                                          getTemplateInstantiationArgs(Var)));
+  CurContext = PreviousContext;
+
+  if (Var) {
+    MemberSpecializationInfo *MSInfo = OldVar->getMemberSpecializationInfo();
+    assert(MSInfo && "Missing member specialization information?");
+    Var->setTemplateSpecializationKind(MSInfo->getTemplateSpecializationKind(),
+                                       MSInfo->getPointOfInstantiation());
+    DeclGroupRef DG(Var);
+    Consumer.HandleTopLevelDecl(DG);
+  }
+
+  if (Recursive) {
+    // Instantiate any pending implicit instantiations found during the
+    // instantiation of this template.
+    PerformPendingImplicitInstantiations();
+
+    // Restore the set of pending implicit instantiations.
+    PendingImplicitInstantiations.swap(SavedPendingImplicitInstantiations);
+  }
+}
+
+void
+Sema::InstantiateMemInitializers(CXXConstructorDecl *New,
+                                 const CXXConstructorDecl *Tmpl,
+                           const MultiLevelTemplateArgumentList &TemplateArgs) {
+
+  llvm::SmallVector<MemInitTy*, 4> NewInits;
+  bool AnyErrors = false;
+  
+  // Instantiate all the initializers.
+  for (CXXConstructorDecl::init_const_iterator Inits = Tmpl->init_begin(),
+                                            InitsEnd = Tmpl->init_end();
+       Inits != InitsEnd; ++Inits) {
+    CXXBaseOrMemberInitializer *Init = *Inits;
+
+    ASTOwningVector<&ActionBase::DeleteExpr> NewArgs(*this);
+    llvm::SmallVector<SourceLocation, 4> CommaLocs;
+
+    // Instantiate all the arguments.
+    Expr *InitE = Init->getInit();
+    if (!InitE) {
+      // Nothing to instantiate;
+    } else if (ParenListExpr *ParenList = dyn_cast<ParenListExpr>(InitE)) {
+      if (InstantiateInitializationArguments(*this, ParenList->getExprs(),
+                                             ParenList->getNumExprs(),
+                                             TemplateArgs, CommaLocs, 
+                                             NewArgs)) {
+        AnyErrors = true;
+        continue;
+      }
+    } else {
+      OwningExprResult InitArg = SubstExpr(InitE, TemplateArgs);
+      if (InitArg.isInvalid()) {
+        AnyErrors = true;
+        continue;
+      }
+      
+      NewArgs.push_back(InitArg.release());
+    }
+    
+    MemInitResult NewInit;
+    if (Init->isBaseInitializer()) {
+      TypeSourceInfo *BaseTInfo = SubstType(Init->getBaseClassInfo(), 
+                                            TemplateArgs, 
+                                            Init->getSourceLocation(), 
+                                            New->getDeclName());
+      if (!BaseTInfo) {
+        AnyErrors = true;
+        New->setInvalidDecl();
+        continue;
+      }
+      
+      NewInit = BuildBaseInitializer(BaseTInfo->getType(), BaseTInfo,
+                                     (Expr **)NewArgs.data(),
+                                     NewArgs.size(),
+                                     Init->getLParenLoc(),
+                                     Init->getRParenLoc(),
+                                     New->getParent());
+    } else if (Init->isMemberInitializer()) {
+      FieldDecl *Member;
+
+      // Is this an anonymous union?
+      if (FieldDecl *UnionInit = Init->getAnonUnionMember())
+        Member = cast<FieldDecl>(FindInstantiatedDecl(UnionInit, TemplateArgs));
+      else
+        Member = cast<FieldDecl>(FindInstantiatedDecl(Init->getMember(),
+                                                      TemplateArgs));
+
+      NewInit = BuildMemberInitializer(Member, (Expr **)NewArgs.data(),
+                                       NewArgs.size(),
+                                       Init->getSourceLocation(),
+                                       Init->getLParenLoc(),
+                                       Init->getRParenLoc());
+    }
+
+    if (NewInit.isInvalid()) {
+      AnyErrors = true;
+      New->setInvalidDecl();
+    } else {
+      // FIXME: It would be nice if ASTOwningVector had a release function.
+      NewArgs.take();
+
+      NewInits.push_back((MemInitTy *)NewInit.get());
+    }
+  }
+
+  // Assign all the initializers to the new constructor.
+  ActOnMemInitializers(DeclPtrTy::make(New),
+                       /*FIXME: ColonLoc */
+                       SourceLocation(),
+                       NewInits.data(), NewInits.size(),
+                       AnyErrors);
+}
+
+// TODO: this could be templated if the various decl types used the
+// same method name.
+static bool isInstantiationOf(ClassTemplateDecl *Pattern,
+                              ClassTemplateDecl *Instance) {
+  Pattern = Pattern->getCanonicalDecl();
+
+  do {
+    Instance = Instance->getCanonicalDecl();
+    if (Pattern == Instance) return true;
+    Instance = Instance->getInstantiatedFromMemberTemplate();
+  } while (Instance);
+
+  return false;
+}
+
+static bool isInstantiationOf(FunctionTemplateDecl *Pattern,
+                              FunctionTemplateDecl *Instance) {
+  Pattern = Pattern->getCanonicalDecl();
+  
+  do {
+    Instance = Instance->getCanonicalDecl();
+    if (Pattern == Instance) return true;
+    Instance = Instance->getInstantiatedFromMemberTemplate();
+  } while (Instance);
+  
+  return false;
+}
+
+static bool 
+isInstantiationOf(ClassTemplatePartialSpecializationDecl *Pattern,
+                  ClassTemplatePartialSpecializationDecl *Instance) {
+  Pattern 
+    = cast<ClassTemplatePartialSpecializationDecl>(Pattern->getCanonicalDecl());
+  do {
+    Instance = cast<ClassTemplatePartialSpecializationDecl>(
+                                                Instance->getCanonicalDecl());
+    if (Pattern == Instance)
+      return true;
+    Instance = Instance->getInstantiatedFromMember();
+  } while (Instance);
+  
+  return false;
+}
+
+static bool isInstantiationOf(CXXRecordDecl *Pattern,
+                              CXXRecordDecl *Instance) {
+  Pattern = Pattern->getCanonicalDecl();
+
+  do {
+    Instance = Instance->getCanonicalDecl();
+    if (Pattern == Instance) return true;
+    Instance = Instance->getInstantiatedFromMemberClass();
+  } while (Instance);
+
+  return false;
+}
+
+static bool isInstantiationOf(FunctionDecl *Pattern,
+                              FunctionDecl *Instance) {
+  Pattern = Pattern->getCanonicalDecl();
+
+  do {
+    Instance = Instance->getCanonicalDecl();
+    if (Pattern == Instance) return true;
+    Instance = Instance->getInstantiatedFromMemberFunction();
+  } while (Instance);
+
+  return false;
+}
+
+static bool isInstantiationOf(EnumDecl *Pattern,
+                              EnumDecl *Instance) {
+  Pattern = Pattern->getCanonicalDecl();
+
+  do {
+    Instance = Instance->getCanonicalDecl();
+    if (Pattern == Instance) return true;
+    Instance = Instance->getInstantiatedFromMemberEnum();
+  } while (Instance);
+
+  return false;
+}
+
+static bool isInstantiationOf(UsingShadowDecl *Pattern,
+                              UsingShadowDecl *Instance,
+                              ASTContext &C) {
+  return C.getInstantiatedFromUsingShadowDecl(Instance) == Pattern;
+}
+
+static bool isInstantiationOf(UsingDecl *Pattern,
+                              UsingDecl *Instance,
+                              ASTContext &C) {
+  return C.getInstantiatedFromUsingDecl(Instance) == Pattern;
+}
+
+static bool isInstantiationOf(UnresolvedUsingValueDecl *Pattern,
+                              UsingDecl *Instance,
+                              ASTContext &C) {
+  return C.getInstantiatedFromUsingDecl(Instance) == Pattern;
+}
+
+static bool isInstantiationOf(UnresolvedUsingTypenameDecl *Pattern,
+                              UsingDecl *Instance,
+                              ASTContext &C) {
+  return C.getInstantiatedFromUsingDecl(Instance) == Pattern;
+}
+
+static bool isInstantiationOfStaticDataMember(VarDecl *Pattern,
+                                              VarDecl *Instance) {
+  assert(Instance->isStaticDataMember());
+
+  Pattern = Pattern->getCanonicalDecl();
+
+  do {
+    Instance = Instance->getCanonicalDecl();
+    if (Pattern == Instance) return true;
+    Instance = Instance->getInstantiatedFromStaticDataMember();
+  } while (Instance);
+
+  return false;
+}
+
+// Other is the prospective instantiation
+// D is the prospective pattern
+static bool isInstantiationOf(ASTContext &Ctx, NamedDecl *D, Decl *Other) {
+  if (D->getKind() != Other->getKind()) {
+    if (UnresolvedUsingTypenameDecl *UUD
+          = dyn_cast<UnresolvedUsingTypenameDecl>(D)) {
+      if (UsingDecl *UD = dyn_cast<UsingDecl>(Other)) {
+        return isInstantiationOf(UUD, UD, Ctx);
+      }
+    }
+
+    if (UnresolvedUsingValueDecl *UUD
+          = dyn_cast<UnresolvedUsingValueDecl>(D)) {
+      if (UsingDecl *UD = dyn_cast<UsingDecl>(Other)) {
+        return isInstantiationOf(UUD, UD, Ctx);
+      }
+    }
+
+    return false;
+  }
+
+  if (CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(Other))
+    return isInstantiationOf(cast<CXXRecordDecl>(D), Record);
+
+  if (FunctionDecl *Function = dyn_cast<FunctionDecl>(Other))
+    return isInstantiationOf(cast<FunctionDecl>(D), Function);
+
+  if (EnumDecl *Enum = dyn_cast<EnumDecl>(Other))
+    return isInstantiationOf(cast<EnumDecl>(D), Enum);
+
+  if (VarDecl *Var = dyn_cast<VarDecl>(Other))
+    if (Var->isStaticDataMember())
+      return isInstantiationOfStaticDataMember(cast<VarDecl>(D), Var);
+
+  if (ClassTemplateDecl *Temp = dyn_cast<ClassTemplateDecl>(Other))
+    return isInstantiationOf(cast<ClassTemplateDecl>(D), Temp);
+
+  if (FunctionTemplateDecl *Temp = dyn_cast<FunctionTemplateDecl>(Other))
+    return isInstantiationOf(cast<FunctionTemplateDecl>(D), Temp);
+
+  if (ClassTemplatePartialSpecializationDecl *PartialSpec
+        = dyn_cast<ClassTemplatePartialSpecializationDecl>(Other))
+    return isInstantiationOf(cast<ClassTemplatePartialSpecializationDecl>(D),
+                             PartialSpec);
+
+  if (FieldDecl *Field = dyn_cast<FieldDecl>(Other)) {
+    if (!Field->getDeclName()) {
+      // This is an unnamed field.
+      return Ctx.getInstantiatedFromUnnamedFieldDecl(Field) ==
+        cast<FieldDecl>(D);
+    }
+  }
+
+  if (UsingDecl *Using = dyn_cast<UsingDecl>(Other))
+    return isInstantiationOf(cast<UsingDecl>(D), Using, Ctx);
+
+  if (UsingShadowDecl *Shadow = dyn_cast<UsingShadowDecl>(Other))
+    return isInstantiationOf(cast<UsingShadowDecl>(D), Shadow, Ctx);
+
+  return D->getDeclName() && isa<NamedDecl>(Other) &&
+    D->getDeclName() == cast<NamedDecl>(Other)->getDeclName();
+}
+
+template<typename ForwardIterator>
+static NamedDecl *findInstantiationOf(ASTContext &Ctx,
+                                      NamedDecl *D,
+                                      ForwardIterator first,
+                                      ForwardIterator last) {
+  for (; first != last; ++first)
+    if (isInstantiationOf(Ctx, D, *first))
+      return cast<NamedDecl>(*first);
+
+  return 0;
+}
+
+/// \brief Finds the instantiation of the given declaration context
+/// within the current instantiation.
+///
+/// \returns NULL if there was an error
+DeclContext *Sema::FindInstantiatedContext(DeclContext* DC,
+                          const MultiLevelTemplateArgumentList &TemplateArgs) {
+  if (NamedDecl *D = dyn_cast<NamedDecl>(DC)) {
+    Decl* ID = FindInstantiatedDecl(D, TemplateArgs);
+    return cast_or_null<DeclContext>(ID);
+  } else return DC;
+}
+
+/// \brief Find the instantiation of the given declaration within the
+/// current instantiation.
+///
+/// This routine is intended to be used when \p D is a declaration
+/// referenced from within a template, that needs to mapped into the
+/// corresponding declaration within an instantiation. For example,
+/// given:
+///
+/// \code
+/// template<typename T>
+/// struct X {
+///   enum Kind {
+///     KnownValue = sizeof(T)
+///   };
+///
+///   bool getKind() const { return KnownValue; }
+/// };
+///
+/// template struct X<int>;
+/// \endcode
+///
+/// In the instantiation of X<int>::getKind(), we need to map the
+/// EnumConstantDecl for KnownValue (which refers to
+/// X<T>::<Kind>::KnownValue) to its instantiation
+/// (X<int>::<Kind>::KnownValue). InstantiateCurrentDeclRef() performs
+/// this mapping from within the instantiation of X<int>.
+NamedDecl *Sema::FindInstantiatedDecl(NamedDecl *D,
+                          const MultiLevelTemplateArgumentList &TemplateArgs) {
+  DeclContext *ParentDC = D->getDeclContext();
+  if (isa<ParmVarDecl>(D) || isa<NonTypeTemplateParmDecl>(D) ||
+      isa<TemplateTypeParmDecl>(D) || isa<TemplateTemplateParmDecl>(D) ||
+      ParentDC->isFunctionOrMethod()) {
+    // D is a local of some kind. Look into the map of local
+    // declarations to their instantiations.
+    return cast<NamedDecl>(CurrentInstantiationScope->getInstantiationOf(D));
+  }
+
+  if (CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(D)) {
+    if (!Record->isDependentContext())
+      return D;
+    
+    // If the RecordDecl is actually the injected-class-name or a
+    // "templated" declaration for a class template, class template
+    // partial specialization, or a member class of a class template,
+    // substitute into the injected-class-name of the class template
+    // or partial specialization to find the new DeclContext.
+    QualType T;
+    ClassTemplateDecl *ClassTemplate = Record->getDescribedClassTemplate();
+    
+    if (ClassTemplate) {
+      T = ClassTemplate->getInjectedClassNameType(Context);
+    } else if (ClassTemplatePartialSpecializationDecl *PartialSpec
+                 = dyn_cast<ClassTemplatePartialSpecializationDecl>(Record)) {
+      T = Context.getTypeDeclType(Record);
+      ClassTemplate = PartialSpec->getSpecializedTemplate();
+    } 
+    
+    if (!T.isNull()) {
+      // Substitute into the injected-class-name to get the type
+      // corresponding to the instantiation we want, which may also be
+      // the current instantiation (if we're in a template
+      // definition). This substitution should never fail, since we
+      // know we can instantiate the injected-class-name or we
+      // wouldn't have gotten to the injected-class-name!  
+
+      // FIXME: Can we use the CurrentInstantiationScope to avoid this
+      // extra instantiation in the common case?
+      T = SubstType(T, TemplateArgs, SourceLocation(), DeclarationName());
+      assert(!T.isNull() && "Instantiation of injected-class-name cannot fail.");
+    
+      if (!T->isDependentType()) {
+        assert(T->isRecordType() && "Instantiation must produce a record type");
+        return T->getAs<RecordType>()->getDecl();
+      }
+    
+      // We are performing "partial" template instantiation to create
+      // the member declarations for the members of a class template
+      // specialization. Therefore, D is actually referring to something
+      // in the current instantiation. Look through the current
+      // context, which contains actual instantiations, to find the
+      // instantiation of the "current instantiation" that D refers
+      // to.
+      bool SawNonDependentContext = false;
+      for (DeclContext *DC = CurContext; !DC->isFileContext();
+           DC = DC->getParent()) {
+        if (ClassTemplateSpecializationDecl *Spec
+                          = dyn_cast<ClassTemplateSpecializationDecl>(DC))
+          if (isInstantiationOf(ClassTemplate, 
+                                Spec->getSpecializedTemplate()))
+            return Spec;
+
+        if (!DC->isDependentContext())
+          SawNonDependentContext = true;
+      }
+
+      // We're performing "instantiation" of a member of the current
+      // instantiation while we are type-checking the
+      // definition. Compute the declaration context and return that.
+      assert(!SawNonDependentContext && 
+             "No dependent context while instantiating record");
+      DeclContext *DC = computeDeclContext(T);
+      assert(DC && 
+             "Unable to find declaration for the current instantiation");
+      return cast<CXXRecordDecl>(DC);
+    }
+
+    // Fall through to deal with other dependent record types (e.g.,
+    // anonymous unions in class templates).
+  }
+
+  if (!ParentDC->isDependentContext())
+    return D;
+  
+  ParentDC = FindInstantiatedContext(ParentDC, TemplateArgs);
+  if (!ParentDC)
+    return 0;
+
+  if (ParentDC != D->getDeclContext()) {
+    // We performed some kind of instantiation in the parent context,
+    // so now we need to look into the instantiated parent context to
+    // find the instantiation of the declaration D.
+    NamedDecl *Result = 0;
+    if (D->getDeclName()) {
+      DeclContext::lookup_result Found = ParentDC->lookup(D->getDeclName());
+      Result = findInstantiationOf(Context, D, Found.first, Found.second);
+    } else {
+      // Since we don't have a name for the entity we're looking for,
+      // our only option is to walk through all of the declarations to
+      // find that name. This will occur in a few cases:
+      //
+      //   - anonymous struct/union within a template
+      //   - unnamed class/struct/union/enum within a template
+      //
+      // FIXME: Find a better way to find these instantiations!
+      Result = findInstantiationOf(Context, D,
+                                   ParentDC->decls_begin(),
+                                   ParentDC->decls_end());
+    }
+
+    // UsingShadowDecls can instantiate to nothing because of using hiding.
+    assert((Result || isa<UsingShadowDecl>(D))
+           && "Unable to find instantiation of declaration!");
+
+    D = Result;
+  }
+
+  return D;
+}
+
+/// \brief Performs template instantiation for all implicit template
+/// instantiations we have seen until this point.
+void Sema::PerformPendingImplicitInstantiations(bool LocalOnly) {
+  while (!PendingLocalImplicitInstantiations.empty() ||
+         (!LocalOnly && !PendingImplicitInstantiations.empty())) {
+    PendingImplicitInstantiation Inst;
+
+    if (PendingLocalImplicitInstantiations.empty()) {
+      Inst = PendingImplicitInstantiations.front();
+      PendingImplicitInstantiations.pop_front();
+    } else {
+      Inst = PendingLocalImplicitInstantiations.front();
+      PendingLocalImplicitInstantiations.pop_front();
+    }
+
+    // Instantiate function definitions
+    if (FunctionDecl *Function = dyn_cast<FunctionDecl>(Inst.first)) {
+      PrettyStackTraceActionsDecl CrashInfo(DeclPtrTy::make(Function),
+                                            Function->getLocation(), *this,
+                                            Context.getSourceManager(),
+                                           "instantiating function definition");
+
+      if (!Function->getBody())
+        InstantiateFunctionDefinition(/*FIXME:*/Inst.second, Function, true);
+      continue;
+    }
+
+    // Instantiate static data member definitions.
+    VarDecl *Var = cast<VarDecl>(Inst.first);
+    assert(Var->isStaticDataMember() && "Not a static data member?");
+
+    PrettyStackTraceActionsDecl CrashInfo(DeclPtrTy::make(Var),
+                                          Var->getLocation(), *this,
+                                          Context.getSourceManager(),
+                                          "instantiating static data member "
+                                          "definition");
+
+    InstantiateStaticDataMemberDefinition(/*FIXME:*/Inst.second, Var, true);
+  }
+}
diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp
new file mode 100644
index 0000000..ceec5f2
--- /dev/null
+++ b/lib/Sema/SemaType.cpp
@@ -0,0 +1,2005 @@
+//===--- SemaType.cpp - Semantic Analysis for Types -----------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file 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/CXXInheritance.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/AST/DeclTemplate.h"
+#include "clang/AST/TypeLoc.h"
+#include "clang/AST/TypeLocVisitor.h"
+#include "clang/AST/Expr.h"
+#include "clang/Basic/PartialDiagnostic.h"
+#include "clang/Parse/DeclSpec.h"
+#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/Support/ErrorHandling.h"
+using namespace clang;
+
+/// \brief Perform adjustment on the parameter type of a function.
+///
+/// This routine adjusts the given parameter type @p T to the actual
+/// parameter type used by semantic analysis (C99 6.7.5.3p[7,8],
+/// C++ [dcl.fct]p3). The adjusted parameter type is returned.
+QualType Sema::adjustParameterType(QualType T) {
+  // C99 6.7.5.3p7:
+  //   A declaration of a parameter as "array of type" shall be
+  //   adjusted to "qualified pointer to type", where the type
+  //   qualifiers (if any) are those specified within the [ and ] of
+  //   the array type derivation.
+  if (T->isArrayType())
+    return Context.getArrayDecayedType(T);
+  
+  // C99 6.7.5.3p8:
+  //   A declaration of a parameter as "function returning type"
+  //   shall be adjusted to "pointer to function returning type", as
+  //   in 6.3.2.1.
+  if (T->isFunctionType())
+    return Context.getPointerType(T);
+
+  return T;
+}
+
+
+
+/// isOmittedBlockReturnType - Return true if this declarator is missing a
+/// return type because this is a omitted return type on a block literal. 
+static bool isOmittedBlockReturnType(const Declarator &D) {
+  if (D.getContext() != Declarator::BlockLiteralContext ||
+      D.getDeclSpec().hasTypeSpecifier())
+    return false;
+  
+  if (D.getNumTypeObjects() == 0)
+    return true;   // ^{ ... }
+  
+  if (D.getNumTypeObjects() == 1 &&
+      D.getTypeObject(0).Kind == DeclaratorChunk::Function)
+    return true;   // ^(int X, float Y) { ... }
+  
+  return false;
+}
+
+typedef std::pair<const AttributeList*,QualType> DelayedAttribute;
+typedef llvm::SmallVectorImpl<DelayedAttribute> DelayedAttributeSet;
+
+static void ProcessTypeAttributeList(Sema &S, QualType &Type,
+                                     const AttributeList *Attrs,
+                                     DelayedAttributeSet &DelayedFnAttrs);
+static bool ProcessFnAttr(Sema &S, QualType &Type, const AttributeList &Attr);
+
+static void ProcessDelayedFnAttrs(Sema &S, QualType &Type,
+                                  DelayedAttributeSet &Attrs) {
+  for (DelayedAttributeSet::iterator I = Attrs.begin(),
+         E = Attrs.end(); I != E; ++I)
+    if (ProcessFnAttr(S, Type, *I->first))
+      S.Diag(I->first->getLoc(), diag::warn_function_attribute_wrong_type)
+        << I->first->getName() << I->second;
+  Attrs.clear();
+}
+
+static void DiagnoseDelayedFnAttrs(Sema &S, DelayedAttributeSet &Attrs) {
+  for (DelayedAttributeSet::iterator I = Attrs.begin(),
+         E = Attrs.end(); I != E; ++I) {
+    S.Diag(I->first->getLoc(), diag::warn_function_attribute_wrong_type)
+      << I->first->getName() << I->second;
+  }
+  Attrs.clear();
+}
+
+/// \brief Convert the specified declspec to the appropriate type
+/// object.
+/// \param D  the declarator containing the declaration specifier.
+/// \returns The type described by the declaration specifiers.  This function
+/// never returns null.
+static QualType ConvertDeclSpecToType(Sema &TheSema,
+                                      Declarator &TheDeclarator,
+                                      DelayedAttributeSet &Delayed) {
+  // FIXME: Should move the logic from DeclSpec::Finish to here for validity
+  // checking.
+  const DeclSpec &DS = TheDeclarator.getDeclSpec();
+  SourceLocation DeclLoc = TheDeclarator.getIdentifierLoc();
+  if (DeclLoc.isInvalid())
+    DeclLoc = DS.getSourceRange().getBegin();
+  
+  ASTContext &Context = TheSema.Context;
+
+  QualType Result;
+  switch (DS.getTypeSpecType()) {
+  case DeclSpec::TST_void:
+    Result = Context.VoidTy;
+    break;
+  case DeclSpec::TST_char:
+    if (DS.getTypeSpecSign() == DeclSpec::TSS_unspecified)
+      Result = Context.CharTy;
+    else if (DS.getTypeSpecSign() == DeclSpec::TSS_signed)
+      Result = Context.SignedCharTy;
+    else {
+      assert(DS.getTypeSpecSign() == DeclSpec::TSS_unsigned &&
+             "Unknown TSS value");
+      Result = Context.UnsignedCharTy;
+    }
+    break;
+  case DeclSpec::TST_wchar:
+    if (DS.getTypeSpecSign() == DeclSpec::TSS_unspecified)
+      Result = Context.WCharTy;
+    else if (DS.getTypeSpecSign() == DeclSpec::TSS_signed) {
+      TheSema.Diag(DS.getTypeSpecSignLoc(), diag::ext_invalid_sign_spec)
+        << DS.getSpecifierName(DS.getTypeSpecType());
+      Result = Context.getSignedWCharType();
+    } else {
+      assert(DS.getTypeSpecSign() == DeclSpec::TSS_unsigned &&
+        "Unknown TSS value");
+      TheSema.Diag(DS.getTypeSpecSignLoc(), diag::ext_invalid_sign_spec)
+        << DS.getSpecifierName(DS.getTypeSpecType());
+      Result = Context.getUnsignedWCharType();
+    }
+    break;
+  case DeclSpec::TST_char16:
+      assert(DS.getTypeSpecSign() == DeclSpec::TSS_unspecified &&
+        "Unknown TSS value");
+      Result = Context.Char16Ty;
+    break;
+  case DeclSpec::TST_char32:
+      assert(DS.getTypeSpecSign() == DeclSpec::TSS_unspecified &&
+        "Unknown TSS value");
+      Result = Context.Char32Ty;
+    break;
+  case DeclSpec::TST_unspecified:
+    // "<proto1,proto2>" is an objc qualified ID with a missing id.
+    if (DeclSpec::ProtocolQualifierListTy PQ = DS.getProtocolQualifiers()) {
+      Result = Context.getObjCObjectPointerType(Context.ObjCBuiltinIdTy,
+                                                (ObjCProtocolDecl**)PQ,
+                                                DS.getNumProtocolQualifiers());
+      break;
+    }
+    
+    // If this is a missing declspec in a block literal return context, then it
+    // is inferred from the return statements inside the block.
+    if (isOmittedBlockReturnType(TheDeclarator)) {
+      Result = Context.DependentTy;
+      break;
+    }
+
+    // Unspecified typespec defaults to int in C90.  However, the C90 grammar
+    // [C90 6.5] only allows a decl-spec if there was *some* type-specifier,
+    // type-qualifier, or storage-class-specifier.  If not, emit an extwarn.
+    // Note that the one exception to this is function definitions, which are
+    // allowed to be completely missing a declspec.  This is handled in the
+    // parser already though by it pretending to have seen an 'int' in this
+    // case.
+    if (TheSema.getLangOptions().ImplicitInt) {
+      // In C89 mode, we only warn if there is a completely missing declspec
+      // when one is not allowed.
+      if (DS.isEmpty()) {
+        TheSema.Diag(DeclLoc, diag::ext_missing_declspec)
+          << DS.getSourceRange()
+        << CodeModificationHint::CreateInsertion(DS.getSourceRange().getBegin(),
+                                                 "int");
+      }
+    } else if (!DS.hasTypeSpecifier()) {
+      // C99 and C++ require a type specifier.  For example, C99 6.7.2p2 says:
+      // "At least one type specifier shall be given in the declaration
+      // specifiers in each declaration, and in the specifier-qualifier list in
+      // each struct declaration and type name."
+      // FIXME: Does Microsoft really have the implicit int extension in C++?
+      if (TheSema.getLangOptions().CPlusPlus &&
+          !TheSema.getLangOptions().Microsoft) {
+        TheSema.Diag(DeclLoc, diag::err_missing_type_specifier)
+          << DS.getSourceRange();
+
+        // When this occurs in C++ code, often something is very broken with the
+        // value being declared, poison it as invalid so we don't get chains of
+        // errors.
+        TheDeclarator.setInvalidType(true);
+      } else {
+        TheSema.Diag(DeclLoc, diag::ext_missing_type_specifier)
+          << DS.getSourceRange();
+      }
+    }
+
+    // FALL THROUGH.
+  case DeclSpec::TST_int: {
+    if (DS.getTypeSpecSign() != DeclSpec::TSS_unsigned) {
+      switch (DS.getTypeSpecWidth()) {
+      case DeclSpec::TSW_unspecified: Result = Context.IntTy; break;
+      case DeclSpec::TSW_short:       Result = Context.ShortTy; break;
+      case DeclSpec::TSW_long:        Result = Context.LongTy; break;
+      case DeclSpec::TSW_longlong:
+        Result = Context.LongLongTy;
+          
+        // long long is a C99 feature.
+        if (!TheSema.getLangOptions().C99 &&
+            !TheSema.getLangOptions().CPlusPlus0x)
+          TheSema.Diag(DS.getTypeSpecWidthLoc(), diag::ext_longlong);
+        break;
+      }
+    } else {
+      switch (DS.getTypeSpecWidth()) {
+      case DeclSpec::TSW_unspecified: Result = Context.UnsignedIntTy; break;
+      case DeclSpec::TSW_short:       Result = Context.UnsignedShortTy; break;
+      case DeclSpec::TSW_long:        Result = Context.UnsignedLongTy; break;
+      case DeclSpec::TSW_longlong:
+        Result = Context.UnsignedLongLongTy;
+          
+        // long long is a C99 feature.
+        if (!TheSema.getLangOptions().C99 &&
+            !TheSema.getLangOptions().CPlusPlus0x)
+          TheSema.Diag(DS.getTypeSpecWidthLoc(), diag::ext_longlong);
+        break;
+      }
+    }
+    break;
+  }
+  case DeclSpec::TST_float: Result = Context.FloatTy; break;
+  case DeclSpec::TST_double:
+    if (DS.getTypeSpecWidth() == DeclSpec::TSW_long)
+      Result = Context.LongDoubleTy;
+    else
+      Result = Context.DoubleTy;
+    break;
+  case DeclSpec::TST_bool: Result = Context.BoolTy; break; // _Bool or bool
+  case DeclSpec::TST_decimal32:    // _Decimal32
+  case DeclSpec::TST_decimal64:    // _Decimal64
+  case DeclSpec::TST_decimal128:   // _Decimal128
+    TheSema.Diag(DS.getTypeSpecTypeLoc(), diag::err_decimal_unsupported);
+    Result = Context.IntTy;
+    TheDeclarator.setInvalidType(true);
+    break;
+  case DeclSpec::TST_class:
+  case DeclSpec::TST_enum:
+  case DeclSpec::TST_union:
+  case DeclSpec::TST_struct: {
+    TypeDecl *D 
+      = dyn_cast_or_null<TypeDecl>(static_cast<Decl *>(DS.getTypeRep()));
+    if (!D) {
+      // This can happen in C++ with ambiguous lookups.
+      Result = Context.IntTy;
+      TheDeclarator.setInvalidType(true);
+      break;
+    }
+
+    // If the type is deprecated or unavailable, diagnose it.
+    TheSema.DiagnoseUseOfDecl(D, DS.getTypeSpecTypeLoc());
+    
+    assert(DS.getTypeSpecWidth() == 0 && DS.getTypeSpecComplex() == 0 &&
+           DS.getTypeSpecSign() == 0 && "No qualifiers on tag names!");
+    
+    // TypeQuals handled by caller.
+    Result = Context.getTypeDeclType(D);
+
+    // In C++, make an ElaboratedType.
+    if (TheSema.getLangOptions().CPlusPlus) {
+      TagDecl::TagKind Tag
+        = TagDecl::getTagKindForTypeSpec(DS.getTypeSpecType());
+      Result = Context.getElaboratedType(Result, Tag);
+    }
+
+    if (D->isInvalidDecl())
+      TheDeclarator.setInvalidType(true);
+    break;
+  }
+  case DeclSpec::TST_typename: {
+    assert(DS.getTypeSpecWidth() == 0 && DS.getTypeSpecComplex() == 0 &&
+           DS.getTypeSpecSign() == 0 &&
+           "Can't handle qualifiers on typedef names yet!");
+    Result = TheSema.GetTypeFromParser(DS.getTypeRep());
+
+    if (DeclSpec::ProtocolQualifierListTy PQ = DS.getProtocolQualifiers()) {
+      if (const ObjCInterfaceType *
+            Interface = Result->getAs<ObjCInterfaceType>()) {
+        // It would be nice if protocol qualifiers were only stored with the
+        // ObjCObjectPointerType. Unfortunately, this isn't possible due
+        // to the following typedef idiom (which is uncommon, but allowed):
+        //
+        // typedef Foo<P> T;
+        // static void func() {
+        //   Foo<P> *yy;
+        //   T *zz;
+        // }
+        Result = Context.getObjCInterfaceType(Interface->getDecl(),
+                                              (ObjCProtocolDecl**)PQ,
+                                              DS.getNumProtocolQualifiers());
+      } else if (Result->isObjCIdType())
+        // id<protocol-list>
+        Result = Context.getObjCObjectPointerType(Context.ObjCBuiltinIdTy,
+                        (ObjCProtocolDecl**)PQ, DS.getNumProtocolQualifiers());
+      else if (Result->isObjCClassType()) {
+        // Class<protocol-list>
+        Result = Context.getObjCObjectPointerType(Context.ObjCBuiltinClassTy,
+                        (ObjCProtocolDecl**)PQ, DS.getNumProtocolQualifiers());
+      } else {
+        TheSema.Diag(DeclLoc, diag::err_invalid_protocol_qualifiers)
+          << DS.getSourceRange();
+        TheDeclarator.setInvalidType(true);
+      }
+    }
+
+    // TypeQuals handled by caller.
+    break;
+  }
+  case DeclSpec::TST_typeofType:
+    // FIXME: Preserve type source info.
+    Result = TheSema.GetTypeFromParser(DS.getTypeRep());
+    assert(!Result.isNull() && "Didn't get a type for typeof?");
+    // TypeQuals handled by caller.
+    Result = Context.getTypeOfType(Result);
+    break;
+  case DeclSpec::TST_typeofExpr: {
+    Expr *E = static_cast<Expr *>(DS.getTypeRep());
+    assert(E && "Didn't get an expression for typeof?");
+    // TypeQuals handled by caller.
+    Result = TheSema.BuildTypeofExprType(E);
+    if (Result.isNull()) {
+      Result = Context.IntTy;
+      TheDeclarator.setInvalidType(true);
+    }
+    break;
+  }
+  case DeclSpec::TST_decltype: {
+    Expr *E = static_cast<Expr *>(DS.getTypeRep());
+    assert(E && "Didn't get an expression for decltype?");
+    // TypeQuals handled by caller.
+    Result = TheSema.BuildDecltypeType(E);
+    if (Result.isNull()) {
+      Result = Context.IntTy;
+      TheDeclarator.setInvalidType(true);
+    }
+    break;
+  }
+  case DeclSpec::TST_auto: {
+    // TypeQuals handled by caller.
+    Result = Context.UndeducedAutoTy;
+    break;
+  }
+
+  case DeclSpec::TST_error:
+    Result = Context.IntTy;
+    TheDeclarator.setInvalidType(true);
+    break;
+  }
+
+  // Handle complex types.
+  if (DS.getTypeSpecComplex() == DeclSpec::TSC_complex) {
+    if (TheSema.getLangOptions().Freestanding)
+      TheSema.Diag(DS.getTypeSpecComplexLoc(), diag::ext_freestanding_complex);
+    Result = Context.getComplexType(Result);
+  } else if (DS.isTypeAltiVecVector()) {
+    unsigned typeSize = static_cast<unsigned>(Context.getTypeSize(Result));
+    assert(typeSize > 0 && "type size for vector must be greater than 0 bits");
+    Result = Context.getVectorType(Result, 128/typeSize, true,
+      DS.isTypeAltiVecPixel());
+  }
+
+  assert(DS.getTypeSpecComplex() != DeclSpec::TSC_imaginary &&
+         "FIXME: imaginary types not supported yet!");
+
+  // See if there are any attributes on the declspec that apply to the type (as
+  // opposed to the decl).
+  if (const AttributeList *AL = DS.getAttributes())
+    ProcessTypeAttributeList(TheSema, Result, AL, Delayed);
+
+  // Apply const/volatile/restrict qualifiers to T.
+  if (unsigned TypeQuals = DS.getTypeQualifiers()) {
+
+    // Enforce C99 6.7.3p2: "Types other than pointer types derived from object
+    // or incomplete types shall not be restrict-qualified."  C++ also allows
+    // restrict-qualified references.
+    if (TypeQuals & DeclSpec::TQ_restrict) {
+      if (Result->isAnyPointerType() || Result->isReferenceType()) {
+        QualType EltTy;
+        if (Result->isObjCObjectPointerType())
+          EltTy = Result;
+        else
+          EltTy = Result->isPointerType() ?
+                    Result->getAs<PointerType>()->getPointeeType() :
+                    Result->getAs<ReferenceType>()->getPointeeType();
+
+        // If we have a pointer or reference, the pointee must have an object
+        // incomplete type.
+        if (!EltTy->isIncompleteOrObjectType()) {
+          TheSema.Diag(DS.getRestrictSpecLoc(),
+               diag::err_typecheck_invalid_restrict_invalid_pointee)
+            << EltTy << DS.getSourceRange();
+          TypeQuals &= ~DeclSpec::TQ_restrict; // Remove the restrict qualifier.
+        }
+      } else {
+        TheSema.Diag(DS.getRestrictSpecLoc(),
+             diag::err_typecheck_invalid_restrict_not_pointer)
+          << Result << DS.getSourceRange();
+        TypeQuals &= ~DeclSpec::TQ_restrict; // Remove the restrict qualifier.
+      }
+    }
+
+    // Warn about CV qualifiers on functions: C99 6.7.3p8: "If the specification
+    // of a function type includes any type qualifiers, the behavior is
+    // undefined."
+    if (Result->isFunctionType() && TypeQuals) {
+      // Get some location to point at, either the C or V location.
+      SourceLocation Loc;
+      if (TypeQuals & DeclSpec::TQ_const)
+        Loc = DS.getConstSpecLoc();
+      else if (TypeQuals & DeclSpec::TQ_volatile)
+        Loc = DS.getVolatileSpecLoc();
+      else {
+        assert((TypeQuals & DeclSpec::TQ_restrict) &&
+               "Has CVR quals but not C, V, or R?");
+        Loc = DS.getRestrictSpecLoc();
+      }
+      TheSema.Diag(Loc, diag::warn_typecheck_function_qualifiers)
+        << Result << DS.getSourceRange();
+    }
+
+    // C++ [dcl.ref]p1:
+    //   Cv-qualified references are ill-formed except when the
+    //   cv-qualifiers are introduced through the use of a typedef
+    //   (7.1.3) or of a template type argument (14.3), in which
+    //   case the cv-qualifiers are ignored.
+    // FIXME: Shouldn't we be checking SCS_typedef here?
+    if (DS.getTypeSpecType() == DeclSpec::TST_typename &&
+        TypeQuals && Result->isReferenceType()) {
+      TypeQuals &= ~DeclSpec::TQ_const;
+      TypeQuals &= ~DeclSpec::TQ_volatile;
+    }
+
+    Qualifiers Quals = Qualifiers::fromCVRMask(TypeQuals);
+    Result = Context.getQualifiedType(Result, Quals);
+  }
+
+  return Result;
+}
+
+static std::string getPrintableNameForEntity(DeclarationName Entity) {
+  if (Entity)
+    return Entity.getAsString();
+
+  return "type name";
+}
+
+/// \brief Build a pointer type.
+///
+/// \param T The type to which we'll be building a pointer.
+///
+/// \param Quals The cvr-qualifiers to be applied to the pointer type.
+///
+/// \param Loc The location of the entity whose type involves this
+/// pointer type or, if there is no such entity, the location of the
+/// type that will have pointer type.
+///
+/// \param Entity The name of the entity that involves the pointer
+/// type, if known.
+///
+/// \returns A suitable pointer type, if there are no
+/// errors. Otherwise, returns a NULL type.
+QualType Sema::BuildPointerType(QualType T, unsigned Quals,
+                                SourceLocation Loc, DeclarationName Entity) {
+  if (T->isReferenceType()) {
+    // C++ 8.3.2p4: There shall be no ... pointers to references ...
+    Diag(Loc, diag::err_illegal_decl_pointer_to_reference)
+      << getPrintableNameForEntity(Entity) << T;
+    return QualType();
+  }
+
+  Qualifiers Qs = Qualifiers::fromCVRMask(Quals);
+
+  // Enforce C99 6.7.3p2: "Types other than pointer types derived from
+  // object or incomplete types shall not be restrict-qualified."
+  if (Qs.hasRestrict() && !T->isIncompleteOrObjectType()) {
+    Diag(Loc, diag::err_typecheck_invalid_restrict_invalid_pointee)
+      << T;
+    Qs.removeRestrict();
+  }
+
+  // Build the pointer type.
+  return Context.getQualifiedType(Context.getPointerType(T), Qs);
+}
+
+/// \brief Build a reference type.
+///
+/// \param T The type to which we'll be building a reference.
+///
+/// \param CVR The cvr-qualifiers to be applied to the reference type.
+///
+/// \param Loc The location of the entity whose type involves this
+/// reference type or, if there is no such entity, the location of the
+/// type that will have reference type.
+///
+/// \param Entity The name of the entity that involves the reference
+/// type, if known.
+///
+/// \returns A suitable reference type, if there are no
+/// errors. Otherwise, returns a NULL type.
+QualType Sema::BuildReferenceType(QualType T, bool SpelledAsLValue,
+                                  unsigned CVR, SourceLocation Loc,
+                                  DeclarationName Entity) {
+  Qualifiers Quals = Qualifiers::fromCVRMask(CVR);
+
+  bool LValueRef = SpelledAsLValue || T->getAs<LValueReferenceType>();
+
+  // C++0x [dcl.typedef]p9: If a typedef TD names a type that is a
+  //   reference to a type T, and attempt to create the type "lvalue
+  //   reference to cv TD" creates the type "lvalue reference to T".
+  // We use the qualifiers (restrict or none) of the original reference,
+  // not the new ones. This is consistent with GCC.
+
+  // C++ [dcl.ref]p4: There shall be no references to references.
+  //
+  // According to C++ DR 106, references to references are only
+  // diagnosed when they are written directly (e.g., "int & &"),
+  // but not when they happen via a typedef:
+  //
+  //   typedef int& intref;
+  //   typedef intref& intref2;
+  //
+  // Parser::ParseDeclaratorInternal diagnoses the case where
+  // references are written directly; here, we handle the
+  // collapsing of references-to-references as described in C++
+  // DR 106 and amended by C++ DR 540.
+
+  // C++ [dcl.ref]p1:
+  //   A declarator that specifies the type "reference to cv void"
+  //   is ill-formed.
+  if (T->isVoidType()) {
+    Diag(Loc, diag::err_reference_to_void);
+    return QualType();
+  }
+
+  // Enforce C99 6.7.3p2: "Types other than pointer types derived from
+  // object or incomplete types shall not be restrict-qualified."
+  if (Quals.hasRestrict() && !T->isIncompleteOrObjectType()) {
+    Diag(Loc, diag::err_typecheck_invalid_restrict_invalid_pointee)
+      << T;
+    Quals.removeRestrict();
+  }
+
+  // C++ [dcl.ref]p1:
+  //   [...] Cv-qualified references are ill-formed except when the
+  //   cv-qualifiers are introduced through the use of a typedef
+  //   (7.1.3) or of a template type argument (14.3), in which case
+  //   the cv-qualifiers are ignored.
+  //
+  // We diagnose extraneous cv-qualifiers for the non-typedef,
+  // non-template type argument case within the parser. Here, we just
+  // ignore any extraneous cv-qualifiers.
+  Quals.removeConst();
+  Quals.removeVolatile();
+
+  // Handle restrict on references.
+  if (LValueRef)
+    return Context.getQualifiedType(
+               Context.getLValueReferenceType(T, SpelledAsLValue), Quals);
+  return Context.getQualifiedType(Context.getRValueReferenceType(T), Quals);
+}
+
+/// \brief Build an array type.
+///
+/// \param T The type of each element in the array.
+///
+/// \param ASM C99 array size modifier (e.g., '*', 'static').
+///
+/// \param ArraySize Expression describing the size of the array.
+///
+/// \param Quals The cvr-qualifiers to be applied to the array's
+/// element type.
+///
+/// \param Loc The location of the entity whose type involves this
+/// array type or, if there is no such entity, the location of the
+/// type that will have array type.
+///
+/// \param Entity The name of the entity that involves the array
+/// type, if known.
+///
+/// \returns A suitable array type, if there are no errors. Otherwise,
+/// returns a NULL type.
+QualType Sema::BuildArrayType(QualType T, ArrayType::ArraySizeModifier ASM,
+                              Expr *ArraySize, unsigned Quals,
+                              SourceRange Brackets, DeclarationName Entity) {
+
+  SourceLocation Loc = Brackets.getBegin();
+  // 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]())
+  // Not in C++, though. There we only dislike void.
+  if (getLangOptions().CPlusPlus) {
+    if (T->isVoidType()) {
+      Diag(Loc, diag::err_illegal_decl_array_incomplete_type) << T;
+      return QualType();
+    }
+  } else {
+    if (RequireCompleteType(Loc, T,
+                            diag::err_illegal_decl_array_incomplete_type))
+      return QualType();
+  }
+
+  if (T->isFunctionType()) {
+    Diag(Loc, diag::err_illegal_decl_array_of_functions)
+      << getPrintableNameForEntity(Entity) << T;
+    return QualType();
+  }
+
+  // C++ 8.3.2p4: There shall be no ... arrays of references ...
+  if (T->isReferenceType()) {
+    Diag(Loc, diag::err_illegal_decl_array_of_references)
+      << getPrintableNameForEntity(Entity) << T;
+    return QualType();
+  }
+
+  if (Context.getCanonicalType(T) == Context.UndeducedAutoTy) {
+    Diag(Loc,  diag::err_illegal_decl_array_of_auto)
+      << getPrintableNameForEntity(Entity);
+    return QualType();
+  }
+
+  if (const RecordType *EltTy = T->getAs<RecordType>()) {
+    // If the element type is a struct or union that contains a variadic
+    // array, accept it as a GNU extension: C99 6.7.2.1p2.
+    if (EltTy->getDecl()->hasFlexibleArrayMember())
+      Diag(Loc, diag::ext_flexible_array_in_array) << T;
+  } else if (T->isObjCInterfaceType()) {
+    Diag(Loc, diag::err_objc_array_of_interfaces) << T;
+    return QualType();
+  }
+
+  // C99 6.7.5.2p1: The size expression shall have integer type.
+  if (ArraySize && !ArraySize->isTypeDependent() &&
+      !ArraySize->getType()->isIntegerType()) {
+    Diag(ArraySize->getLocStart(), diag::err_array_size_non_int)
+      << ArraySize->getType() << ArraySize->getSourceRange();
+    ArraySize->Destroy(Context);
+    return QualType();
+  }
+  llvm::APSInt ConstVal(32);
+  if (!ArraySize) {
+    if (ASM == ArrayType::Star)
+      T = Context.getVariableArrayType(T, 0, ASM, Quals, Brackets);
+    else
+      T = Context.getIncompleteArrayType(T, ASM, Quals);
+  } else if (ArraySize->isValueDependent()) {
+    T = Context.getDependentSizedArrayType(T, ArraySize, ASM, Quals, Brackets);
+  } else if (!ArraySize->isIntegerConstantExpr(ConstVal, Context) ||
+             (!T->isDependentType() && !T->isIncompleteType() &&
+              !T->isConstantSizeType())) {
+    // Per C99, a variable array is an array with either a non-constant
+    // size or an element type that has a non-constant-size
+    T = Context.getVariableArrayType(T, ArraySize, ASM, Quals, Brackets);
+  } else {
+    // C99 6.7.5.2p1: If the expression is a constant expression, it shall
+    // have a value greater than zero.
+    if (ConstVal.isSigned() && ConstVal.isNegative()) {
+      Diag(ArraySize->getLocStart(),
+           diag::err_typecheck_negative_array_size)
+        << ArraySize->getSourceRange();
+      return QualType();
+    }
+    if (ConstVal == 0) {
+      // GCC accepts zero sized static arrays.
+      Diag(ArraySize->getLocStart(), diag::ext_typecheck_zero_array_size)
+        << ArraySize->getSourceRange();
+    }
+    T = Context.getConstantArrayType(T, ConstVal, ASM, Quals);
+  }
+  // If this is not C99, extwarn about VLA's and C99 array size modifiers.
+  if (!getLangOptions().C99) {
+    if (ArraySize && !ArraySize->isTypeDependent() &&
+        !ArraySize->isValueDependent() &&
+        !ArraySize->isIntegerConstantExpr(Context))
+      Diag(Loc, getLangOptions().CPlusPlus? diag::err_vla_cxx : diag::ext_vla);
+    else if (ASM != ArrayType::Normal || Quals != 0)
+      Diag(Loc, 
+           getLangOptions().CPlusPlus? diag::err_c99_array_usage_cxx
+                                     : diag::ext_c99_array_usage);
+  }
+
+  return T;
+}
+
+/// \brief Build an ext-vector type.
+///
+/// Run the required checks for the extended vector type.
+QualType Sema::BuildExtVectorType(QualType T, ExprArg ArraySize,
+                                  SourceLocation AttrLoc) {
+
+  Expr *Arg = (Expr *)ArraySize.get();
+
+  // unlike gcc's vector_size attribute, we do not allow vectors to be defined
+  // in conjunction with complex types (pointers, arrays, functions, etc.).
+  if (!T->isDependentType() &&
+      !T->isIntegerType() && !T->isRealFloatingType()) {
+    Diag(AttrLoc, diag::err_attribute_invalid_vector_type) << T;
+    return QualType();
+  }
+
+  if (!Arg->isTypeDependent() && !Arg->isValueDependent()) {
+    llvm::APSInt vecSize(32);
+    if (!Arg->isIntegerConstantExpr(vecSize, Context)) {
+      Diag(AttrLoc, diag::err_attribute_argument_not_int)
+      << "ext_vector_type" << Arg->getSourceRange();
+      return QualType();
+    }
+
+    // unlike gcc's vector_size attribute, the size is specified as the
+    // number of elements, not the number of bytes.
+    unsigned vectorSize = static_cast<unsigned>(vecSize.getZExtValue());
+
+    if (vectorSize == 0) {
+      Diag(AttrLoc, diag::err_attribute_zero_size)
+      << Arg->getSourceRange();
+      return QualType();
+    }
+
+    if (!T->isDependentType())
+      return Context.getExtVectorType(T, vectorSize);
+  }
+
+  return Context.getDependentSizedExtVectorType(T, ArraySize.takeAs<Expr>(),
+                                                AttrLoc);
+}
+
+/// \brief Build a function type.
+///
+/// This routine checks the function type according to C++ rules and
+/// under the assumption that the result type and parameter types have
+/// just been instantiated from a template. It therefore duplicates
+/// some of the behavior of GetTypeForDeclarator, but in a much
+/// simpler form that is only suitable for this narrow use case.
+///
+/// \param T The return type of the function.
+///
+/// \param ParamTypes The parameter types of the function. This array
+/// will be modified to account for adjustments to the types of the
+/// function parameters.
+///
+/// \param NumParamTypes The number of parameter types in ParamTypes.
+///
+/// \param Variadic Whether this is a variadic function type.
+///
+/// \param Quals The cvr-qualifiers to be applied to the function type.
+///
+/// \param Loc The location of the entity whose type involves this
+/// function type or, if there is no such entity, the location of the
+/// type that will have function type.
+///
+/// \param Entity The name of the entity that involves the function
+/// type, if known.
+///
+/// \returns A suitable function type, if there are no
+/// errors. Otherwise, returns a NULL type.
+QualType Sema::BuildFunctionType(QualType T,
+                                 QualType *ParamTypes,
+                                 unsigned NumParamTypes,
+                                 bool Variadic, unsigned Quals,
+                                 SourceLocation Loc, DeclarationName Entity) {
+  if (T->isArrayType() || T->isFunctionType()) {
+    Diag(Loc, diag::err_func_returning_array_function) 
+      << T->isFunctionType() << T;
+    return QualType();
+  }
+
+  bool Invalid = false;
+  for (unsigned Idx = 0; Idx < NumParamTypes; ++Idx) {
+    QualType ParamType = adjustParameterType(ParamTypes[Idx]);
+    if (ParamType->isVoidType()) {
+      Diag(Loc, diag::err_param_with_void_type);
+      Invalid = true;
+    }
+
+    ParamTypes[Idx] = ParamType;
+  }
+
+  if (Invalid)
+    return QualType();
+
+  return Context.getFunctionType(T, ParamTypes, NumParamTypes, Variadic,
+                                 Quals);
+}
+
+/// \brief Build a member pointer type \c T Class::*.
+///
+/// \param T the type to which the member pointer refers.
+/// \param Class the class type into which the member pointer points.
+/// \param CVR Qualifiers applied to the member pointer type
+/// \param Loc the location where this type begins
+/// \param Entity the name of the entity that will have this member pointer type
+///
+/// \returns a member pointer type, if successful, or a NULL type if there was
+/// an error.
+QualType Sema::BuildMemberPointerType(QualType T, QualType Class,
+                                      unsigned CVR, SourceLocation Loc,
+                                      DeclarationName Entity) {
+  Qualifiers Quals = Qualifiers::fromCVRMask(CVR);
+
+  // Verify that we're not building a pointer to pointer to function with
+  // exception specification.
+  if (CheckDistantExceptionSpec(T)) {
+    Diag(Loc, diag::err_distant_exception_spec);
+
+    // FIXME: If we're doing this as part of template instantiation,
+    // we should return immediately.
+
+    // Build the type anyway, but use the canonical type so that the
+    // exception specifiers are stripped off.
+    T = Context.getCanonicalType(T);
+  }
+
+  // C++ 8.3.3p3: A pointer to member shall not pointer to ... a member
+  //   with reference type, or "cv void."
+  if (T->isReferenceType()) {
+    Diag(Loc, diag::err_illegal_decl_mempointer_to_reference)
+      << (Entity? Entity.getAsString() : "type name") << T;
+    return QualType();
+  }
+
+  if (T->isVoidType()) {
+    Diag(Loc, diag::err_illegal_decl_mempointer_to_void)
+      << (Entity? Entity.getAsString() : "type name");
+    return QualType();
+  }
+
+  // Enforce C99 6.7.3p2: "Types other than pointer types derived from
+  // object or incomplete types shall not be restrict-qualified."
+  if (Quals.hasRestrict() && !T->isIncompleteOrObjectType()) {
+    Diag(Loc, diag::err_typecheck_invalid_restrict_invalid_pointee)
+      << T;
+
+    // FIXME: If we're doing this as part of template instantiation,
+    // we should return immediately.
+    Quals.removeRestrict();
+  }
+
+  if (!Class->isDependentType() && !Class->isRecordType()) {
+    Diag(Loc, diag::err_mempointer_in_nonclass_type) << Class;
+    return QualType();
+  }
+
+  return Context.getQualifiedType(
+           Context.getMemberPointerType(T, Class.getTypePtr()), Quals);
+}
+
+/// \brief Build a block pointer type.
+///
+/// \param T The type to which we'll be building a block pointer.
+///
+/// \param CVR The cvr-qualifiers to be applied to the block pointer type.
+///
+/// \param Loc The location of the entity whose type involves this
+/// block pointer type or, if there is no such entity, the location of the
+/// type that will have block pointer type.
+///
+/// \param Entity The name of the entity that involves the block pointer
+/// type, if known.
+///
+/// \returns A suitable block pointer type, if there are no
+/// errors. Otherwise, returns a NULL type.
+QualType Sema::BuildBlockPointerType(QualType T, unsigned CVR,
+                                     SourceLocation Loc,
+                                     DeclarationName Entity) {
+  if (!T->isFunctionType()) {
+    Diag(Loc, diag::err_nonfunction_block_type);
+    return QualType();
+  }
+
+  Qualifiers Quals = Qualifiers::fromCVRMask(CVR);
+  return Context.getQualifiedType(Context.getBlockPointerType(T), Quals);
+}
+
+QualType Sema::GetTypeFromParser(TypeTy *Ty, TypeSourceInfo **TInfo) {
+  QualType QT = QualType::getFromOpaquePtr(Ty);
+  if (QT.isNull()) {
+    if (TInfo) *TInfo = 0;
+    return QualType();
+  }
+
+  TypeSourceInfo *DI = 0;
+  if (LocInfoType *LIT = dyn_cast<LocInfoType>(QT)) {
+    QT = LIT->getType();
+    DI = LIT->getTypeSourceInfo();
+  }
+
+  if (TInfo) *TInfo = DI;
+  return QT;
+}
+
+/// GetTypeForDeclarator - Convert the type for the specified
+/// declarator to Type instances.
+///
+/// If OwnedDecl is non-NULL, and this declarator's decl-specifier-seq
+/// owns the declaration of a type (e.g., the definition of a struct
+/// type), then *OwnedDecl will receive the owned declaration.
+QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S,
+                                    TypeSourceInfo **TInfo,
+                                    TagDecl **OwnedDecl) {
+  // Determine the type of the declarator. Not all forms of declarator
+  // have a type.
+  QualType T;
+
+  llvm::SmallVector<DelayedAttribute,4> FnAttrsFromDeclSpec;
+
+  switch (D.getName().getKind()) {
+  case UnqualifiedId::IK_Identifier:
+  case UnqualifiedId::IK_OperatorFunctionId:
+  case UnqualifiedId::IK_LiteralOperatorId:
+  case UnqualifiedId::IK_TemplateId:
+    T = ConvertDeclSpecToType(*this, D, FnAttrsFromDeclSpec);
+    
+    if (!D.isInvalidType() && D.getDeclSpec().isTypeSpecOwned()) {
+      TagDecl* Owned = cast<TagDecl>((Decl *)D.getDeclSpec().getTypeRep());
+      Owned->setDefinedInDeclarator(Owned->isDefinition());
+      if (OwnedDecl) *OwnedDecl = Owned;
+    }
+    break;
+
+  case UnqualifiedId::IK_ConstructorName:
+  case UnqualifiedId::IK_ConstructorTemplateId:
+  case UnqualifiedId::IK_DestructorName:
+    // Constructors and destructors don't have return types. Use
+    // "void" instead. 
+    T = Context.VoidTy;
+    break;
+
+  case UnqualifiedId::IK_ConversionFunctionId:
+    // The result type of a conversion function is the type that it
+    // converts to.
+    T = GetTypeFromParser(D.getName().ConversionFunctionId);
+    break;
+  }
+  
+  if (T.isNull())
+    return T;
+
+  if (T == Context.UndeducedAutoTy) {
+    int Error = -1;
+
+    switch (D.getContext()) {
+    case Declarator::KNRTypeListContext:
+      assert(0 && "K&R type lists aren't allowed in C++");
+      break;
+    case Declarator::PrototypeContext:
+      Error = 0; // Function prototype
+      break;
+    case Declarator::MemberContext:
+      switch (cast<TagDecl>(CurContext)->getTagKind()) {
+      case TagDecl::TK_enum: assert(0 && "unhandled tag kind"); break;
+      case TagDecl::TK_struct: Error = 1; /* Struct member */ break;
+      case TagDecl::TK_union:  Error = 2; /* Union member */ break;
+      case TagDecl::TK_class:  Error = 3; /* Class member */ break;
+      }
+      break;
+    case Declarator::CXXCatchContext:
+      Error = 4; // Exception declaration
+      break;
+    case Declarator::TemplateParamContext:
+      Error = 5; // Template parameter
+      break;
+    case Declarator::BlockLiteralContext:
+      Error = 6;  // Block literal
+      break;
+    case Declarator::FileContext:
+    case Declarator::BlockContext:
+    case Declarator::ForContext:
+    case Declarator::ConditionContext:
+    case Declarator::TypeNameContext:
+      break;
+    }
+
+    if (Error != -1) {
+      Diag(D.getDeclSpec().getTypeSpecTypeLoc(), diag::err_auto_not_allowed)
+        << Error;
+      T = Context.IntTy;
+      D.setInvalidType(true);
+    }
+  }
+
+  // The name we're declaring, if any.
+  DeclarationName Name;
+  if (D.getIdentifier())
+    Name = D.getIdentifier();
+
+  llvm::SmallVector<DelayedAttribute,4> FnAttrsFromPreviousChunk;
+
+  // 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) {
+    DeclaratorChunk &DeclType = D.getTypeObject(e-i-1);
+    switch (DeclType.Kind) {
+    default: assert(0 && "Unknown decltype!");
+    case DeclaratorChunk::BlockPointer:
+      // If blocks are disabled, emit an error.
+      if (!LangOpts.Blocks)
+        Diag(DeclType.Loc, diag::err_blocks_disable);
+
+      T = BuildBlockPointerType(T, DeclType.Cls.TypeQuals, D.getIdentifierLoc(),
+                                Name);
+      break;
+    case DeclaratorChunk::Pointer:
+      // Verify that we're not building a pointer to pointer to function with
+      // exception specification.
+      if (getLangOptions().CPlusPlus && CheckDistantExceptionSpec(T)) {
+        Diag(D.getIdentifierLoc(), diag::err_distant_exception_spec);
+        D.setInvalidType(true);
+        // Build the type anyway.
+      }
+      if (getLangOptions().ObjC1 && T->isObjCInterfaceType()) {
+        const ObjCInterfaceType *OIT = T->getAs<ObjCInterfaceType>();
+        T = Context.getObjCObjectPointerType(T,
+                                         (ObjCProtocolDecl **)OIT->qual_begin(),
+                                         OIT->getNumProtocols());
+        break;
+      }
+      T = BuildPointerType(T, DeclType.Ptr.TypeQuals, DeclType.Loc, Name);
+      break;
+    case DeclaratorChunk::Reference: {
+      Qualifiers Quals;
+      if (DeclType.Ref.HasRestrict) Quals.addRestrict();
+
+      // Verify that we're not building a reference to pointer to function with
+      // exception specification.
+      if (getLangOptions().CPlusPlus && CheckDistantExceptionSpec(T)) {
+        Diag(D.getIdentifierLoc(), diag::err_distant_exception_spec);
+        D.setInvalidType(true);
+        // Build the type anyway.
+      }
+      T = BuildReferenceType(T, DeclType.Ref.LValueRef, Quals,
+                             DeclType.Loc, Name);
+      break;
+    }
+    case DeclaratorChunk::Array: {
+      // Verify that we're not building an array of pointers to function with
+      // exception specification.
+      if (getLangOptions().CPlusPlus && CheckDistantExceptionSpec(T)) {
+        Diag(D.getIdentifierLoc(), diag::err_distant_exception_spec);
+        D.setInvalidType(true);
+        // Build the type anyway.
+      }
+      DeclaratorChunk::ArrayTypeInfo &ATI = DeclType.Arr;
+      Expr *ArraySize = static_cast<Expr*>(ATI.NumElts);
+      ArrayType::ArraySizeModifier ASM;
+      if (ATI.isStar)
+        ASM = ArrayType::Star;
+      else if (ATI.hasStatic)
+        ASM = ArrayType::Static;
+      else
+        ASM = ArrayType::Normal;
+      if (ASM == ArrayType::Star &&
+          D.getContext() != Declarator::PrototypeContext) {
+        // FIXME: This check isn't quite right: it allows star in prototypes
+        // for function definitions, and disallows some edge cases detailed
+        // in http://gcc.gnu.org/ml/gcc-patches/2009-02/msg00133.html
+        Diag(DeclType.Loc, diag::err_array_star_outside_prototype);
+        ASM = ArrayType::Normal;
+        D.setInvalidType(true);
+      }
+      T = BuildArrayType(T, ASM, ArraySize,
+                         Qualifiers::fromCVRMask(ATI.TypeQuals),
+                         SourceRange(DeclType.Loc, DeclType.EndLoc), Name);
+      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;
+
+      // C99 6.7.5.3p1: The return type may not be a function or array type.
+      // For conversion functions, we'll diagnose this particular error later.
+      if ((T->isArrayType() || T->isFunctionType()) &&
+          (D.getName().getKind() != UnqualifiedId::IK_ConversionFunctionId)) {
+        Diag(DeclType.Loc, diag::err_func_returning_array_function) 
+          << T->isFunctionType() << T;
+        T = Context.IntTy;
+        D.setInvalidType(true);
+      }
+
+      if (getLangOptions().CPlusPlus && D.getDeclSpec().isTypeSpecOwned()) {
+        // C++ [dcl.fct]p6:
+        //   Types shall not be defined in return or parameter types.
+        TagDecl *Tag = cast<TagDecl>((Decl *)D.getDeclSpec().getTypeRep());
+        if (Tag->isDefinition())
+          Diag(Tag->getLocation(), diag::err_type_defined_in_result_type)
+            << Context.getTypeDeclType(Tag);
+      }
+
+      // Exception specs are not allowed in typedefs. Complain, but add it
+      // anyway.
+      if (FTI.hasExceptionSpec &&
+          D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_typedef)
+        Diag(FTI.getThrowLoc(), diag::err_exception_spec_in_typedef);
+
+      if (FTI.NumArgs == 0) {
+        if (getLangOptions().CPlusPlus) {
+          // C++ 8.3.5p2: If the parameter-declaration-clause is empty, the
+          // function takes no arguments.
+          llvm::SmallVector<QualType, 4> Exceptions;
+          Exceptions.reserve(FTI.NumExceptions);
+          for (unsigned ei = 0, ee = FTI.NumExceptions; ei != ee; ++ei) {
+            // FIXME: Preserve type source info.
+            QualType ET = GetTypeFromParser(FTI.Exceptions[ei].Ty);
+            // Check that the type is valid for an exception spec, and drop it
+            // if not.
+            if (!CheckSpecifiedExceptionType(ET, FTI.Exceptions[ei].Range))
+              Exceptions.push_back(ET);
+          }
+          T = Context.getFunctionType(T, NULL, 0, FTI.isVariadic, FTI.TypeQuals,
+                                      FTI.hasExceptionSpec,
+                                      FTI.hasAnyExceptionSpec,
+                                      Exceptions.size(), Exceptions.data());
+        } else if (FTI.isVariadic) {
+          // We allow a zero-parameter variadic function in C if the
+          // function is marked with the "overloadable"
+          // attribute. Scan for this attribute now.
+          bool Overloadable = false;
+          for (const AttributeList *Attrs = D.getAttributes();
+               Attrs; Attrs = Attrs->getNext()) {
+            if (Attrs->getKind() == AttributeList::AT_overloadable) {
+              Overloadable = true;
+              break;
+            }
+          }
+
+          if (!Overloadable)
+            Diag(FTI.getEllipsisLoc(), diag::err_ellipsis_first_arg);
+          T = Context.getFunctionType(T, NULL, 0, FTI.isVariadic, 0);
+        } else {
+          // Simple void foo(), where the incoming T is the result type.
+          T = Context.getFunctionNoProtoType(T);
+        }
+      } else if (FTI.ArgInfo[0].Param == 0) {
+        // C99 6.7.5.3p3: Reject int(x,y,z) when it's not a function definition.
+        Diag(FTI.ArgInfo[0].IdentLoc, diag::err_ident_list_in_fn_declaration);
+        D.setInvalidType(true);
+      } 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) {
+          ParmVarDecl *Param =
+            cast<ParmVarDecl>(FTI.ArgInfo[i].Param.getAs<Decl>());
+          QualType ArgTy = Param->getType();
+          assert(!ArgTy.isNull() && "Couldn't parse type?");
+
+          // Adjust the parameter type.
+          assert((ArgTy == adjustParameterType(ArgTy)) && "Unadjusted 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 FunctionProtoType 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);
+              ArgTy = Context.IntTy;
+              Param->setType(ArgTy);
+            } else if (FTI.ArgInfo[i].Ident) {
+              // Reject, but continue to parse 'int(void abc)'.
+              Diag(FTI.ArgInfo[i].IdentLoc,
+                   diag::err_param_with_void_type);
+              ArgTy = Context.IntTy;
+              Param->setType(ArgTy);
+            } else {
+              // Reject, but continue to parse 'float(const void)'.
+              if (ArgTy.hasQualifiers())
+                Diag(DeclType.Loc, diag::err_void_param_qualified);
+
+              // Do not add 'void' to the ArgTys list.
+              break;
+            }
+          } else if (!FTI.hasPrototype) {
+            if (ArgTy->isPromotableIntegerType()) {
+              ArgTy = Context.getPromotedIntegerType(ArgTy);
+            } else if (const BuiltinType* BTy = ArgTy->getAs<BuiltinType>()) {
+              if (BTy->getKind() == BuiltinType::Float)
+                ArgTy = Context.DoubleTy;
+            }
+          }
+
+          ArgTys.push_back(ArgTy);
+        }
+
+        llvm::SmallVector<QualType, 4> Exceptions;
+        Exceptions.reserve(FTI.NumExceptions);
+        for (unsigned ei = 0, ee = FTI.NumExceptions; ei != ee; ++ei) {
+          // FIXME: Preserve type source info.
+          QualType ET = GetTypeFromParser(FTI.Exceptions[ei].Ty);
+          // Check that the type is valid for an exception spec, and drop it if
+          // not.
+          if (!CheckSpecifiedExceptionType(ET, FTI.Exceptions[ei].Range))
+            Exceptions.push_back(ET);
+        }
+
+        T = Context.getFunctionType(T, ArgTys.data(), ArgTys.size(),
+                                    FTI.isVariadic, FTI.TypeQuals,
+                                    FTI.hasExceptionSpec,
+                                    FTI.hasAnyExceptionSpec,
+                                    Exceptions.size(), Exceptions.data());
+      }
+
+      // For GCC compatibility, we allow attributes that apply only to
+      // function types to be placed on a function's return type
+      // instead (as long as that type doesn't happen to be function
+      // or function-pointer itself).
+      ProcessDelayedFnAttrs(*this, T, FnAttrsFromPreviousChunk);
+
+      break;
+    }
+    case DeclaratorChunk::MemberPointer:
+      // Verify that we're not building a pointer to pointer to function with
+      // exception specification.
+      if (getLangOptions().CPlusPlus && CheckDistantExceptionSpec(T)) {
+        Diag(D.getIdentifierLoc(), diag::err_distant_exception_spec);
+        D.setInvalidType(true);
+        // Build the type anyway.
+      }
+      // The scope spec must refer to a class, or be dependent.
+      QualType ClsType;
+      if (isDependentScopeSpecifier(DeclType.Mem.Scope())
+            || dyn_cast_or_null<CXXRecordDecl>(
+                                   computeDeclContext(DeclType.Mem.Scope()))) {
+        NestedNameSpecifier *NNS
+          = (NestedNameSpecifier *)DeclType.Mem.Scope().getScopeRep();
+        NestedNameSpecifier *NNSPrefix = NNS->getPrefix();
+        switch (NNS->getKind()) {
+        case NestedNameSpecifier::Identifier:
+          ClsType = Context.getTypenameType(NNSPrefix, NNS->getAsIdentifier());
+          break;
+
+        case NestedNameSpecifier::Namespace:
+        case NestedNameSpecifier::Global:
+          llvm_unreachable("Nested-name-specifier must name a type");
+          break;
+            
+        case NestedNameSpecifier::TypeSpec:
+        case NestedNameSpecifier::TypeSpecWithTemplate:
+          ClsType = QualType(NNS->getAsType(), 0);
+          if (NNSPrefix)
+            ClsType = Context.getQualifiedNameType(NNSPrefix, ClsType);
+          break;
+        }
+      } else {
+        Diag(DeclType.Mem.Scope().getBeginLoc(),
+             diag::err_illegal_decl_mempointer_in_nonclass)
+          << (D.getIdentifier() ? D.getIdentifier()->getName() : "type name")
+          << DeclType.Mem.Scope().getRange();
+        D.setInvalidType(true);
+      }
+
+      if (!ClsType.isNull())
+        T = BuildMemberPointerType(T, ClsType, DeclType.Mem.TypeQuals,
+                                   DeclType.Loc, D.getIdentifier());
+      if (T.isNull()) {
+        T = Context.IntTy;
+        D.setInvalidType(true);
+      }
+      break;
+    }
+
+    if (T.isNull()) {
+      D.setInvalidType(true);
+      T = Context.IntTy;
+    }
+
+    DiagnoseDelayedFnAttrs(*this, FnAttrsFromPreviousChunk);
+
+    // See if there are any attributes on this declarator chunk.
+    if (const AttributeList *AL = DeclType.getAttrs())
+      ProcessTypeAttributeList(*this, T, AL, FnAttrsFromPreviousChunk);
+  }
+
+  if (getLangOptions().CPlusPlus && T->isFunctionType()) {
+    const FunctionProtoType *FnTy = T->getAs<FunctionProtoType>();
+    assert(FnTy && "Why oh why is there not a FunctionProtoType here?");
+
+    // C++ 8.3.5p4: A cv-qualifier-seq shall only be part of the function type
+    // for a nonstatic member function, the function type to which a pointer
+    // to member refers, or the top-level function type of a function typedef
+    // declaration.
+    if (FnTy->getTypeQuals() != 0 &&
+        D.getDeclSpec().getStorageClassSpec() != DeclSpec::SCS_typedef &&
+        ((D.getContext() != Declarator::MemberContext &&
+          (!D.getCXXScopeSpec().isSet() ||
+           !computeDeclContext(D.getCXXScopeSpec(), /*FIXME:*/true)
+              ->isRecord())) ||
+         D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_static)) {
+      if (D.isFunctionDeclarator())
+        Diag(D.getIdentifierLoc(), diag::err_invalid_qualified_function_type);
+      else
+        Diag(D.getIdentifierLoc(),
+             diag::err_invalid_qualified_typedef_function_type_use);
+
+      // Strip the cv-quals from the type.
+      T = Context.getFunctionType(FnTy->getResultType(), FnTy->arg_type_begin(),
+                                  FnTy->getNumArgs(), FnTy->isVariadic(), 0);
+    }
+  }
+
+  // Process any function attributes we might have delayed from the
+  // declaration-specifiers.
+  ProcessDelayedFnAttrs(*this, T, FnAttrsFromDeclSpec);
+
+  // If there were any type attributes applied to the decl itself, not
+  // the type, apply them to the result type.  But don't do this for
+  // block-literal expressions, which are parsed wierdly.
+  if (D.getContext() != Declarator::BlockLiteralContext)
+    if (const AttributeList *Attrs = D.getAttributes())
+      ProcessTypeAttributeList(*this, T, Attrs, FnAttrsFromPreviousChunk);
+
+  DiagnoseDelayedFnAttrs(*this, FnAttrsFromPreviousChunk);
+
+  if (TInfo) {
+    if (D.isInvalidType())
+      *TInfo = 0;
+    else
+      *TInfo = GetTypeSourceInfoForDeclarator(D, T);
+  }
+
+  return T;
+}
+
+namespace {
+  class TypeSpecLocFiller : public TypeLocVisitor<TypeSpecLocFiller> {
+    const DeclSpec &DS;
+
+  public:
+    TypeSpecLocFiller(const DeclSpec &DS) : DS(DS) {}
+
+    void VisitQualifiedTypeLoc(QualifiedTypeLoc TL) {
+      Visit(TL.getUnqualifiedLoc());
+    }
+    void VisitTypedefTypeLoc(TypedefTypeLoc TL) {
+      TL.setNameLoc(DS.getTypeSpecTypeLoc());
+    }
+    void VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc TL) {
+      TL.setNameLoc(DS.getTypeSpecTypeLoc());
+
+      if (DS.getProtocolQualifiers()) {
+        assert(TL.getNumProtocols() > 0);
+        assert(TL.getNumProtocols() == DS.getNumProtocolQualifiers());
+        TL.setLAngleLoc(DS.getProtocolLAngleLoc());
+        TL.setRAngleLoc(DS.getSourceRange().getEnd());
+        for (unsigned i = 0, e = DS.getNumProtocolQualifiers(); i != e; ++i)
+          TL.setProtocolLoc(i, DS.getProtocolLocs()[i]);
+      } else {
+        assert(TL.getNumProtocols() == 0);
+        TL.setLAngleLoc(SourceLocation());
+        TL.setRAngleLoc(SourceLocation());
+      }
+    }
+    void VisitObjCObjectPointerTypeLoc(ObjCObjectPointerTypeLoc TL) {
+      assert(TL.getNumProtocols() == DS.getNumProtocolQualifiers());
+
+      TL.setStarLoc(SourceLocation());
+
+      if (DS.getProtocolQualifiers()) {
+        assert(TL.getNumProtocols() > 0);
+        assert(TL.getNumProtocols() == DS.getNumProtocolQualifiers());
+        TL.setHasProtocolsAsWritten(true);
+        TL.setLAngleLoc(DS.getProtocolLAngleLoc());
+        TL.setRAngleLoc(DS.getSourceRange().getEnd());
+        for (unsigned i = 0, e = DS.getNumProtocolQualifiers(); i != e; ++i)
+          TL.setProtocolLoc(i, DS.getProtocolLocs()[i]);
+
+      } else {
+        assert(TL.getNumProtocols() == 0);
+        TL.setHasProtocolsAsWritten(false);
+        TL.setLAngleLoc(SourceLocation());
+        TL.setRAngleLoc(SourceLocation());
+      }
+
+      // This might not have been written with an inner type.
+      if (DS.getTypeSpecType() == DeclSpec::TST_unspecified) {
+        TL.setHasBaseTypeAsWritten(false);
+        TL.getBaseTypeLoc().initialize(SourceLocation());
+      } else {
+        TL.setHasBaseTypeAsWritten(true);
+        Visit(TL.getBaseTypeLoc());
+      }
+    }
+    void VisitTemplateSpecializationTypeLoc(TemplateSpecializationTypeLoc TL) {
+      TypeSourceInfo *TInfo = 0;
+      Sema::GetTypeFromParser(DS.getTypeRep(), &TInfo);
+
+      // If we got no declarator info from previous Sema routines,
+      // just fill with the typespec loc.
+      if (!TInfo) {
+        TL.initialize(DS.getTypeSpecTypeLoc());
+        return;
+      }
+
+      TemplateSpecializationTypeLoc OldTL =
+        cast<TemplateSpecializationTypeLoc>(TInfo->getTypeLoc());
+      TL.copy(OldTL);
+    }
+    void VisitTypeOfExprTypeLoc(TypeOfExprTypeLoc TL) {
+      assert(DS.getTypeSpecType() == DeclSpec::TST_typeofExpr);
+      TL.setTypeofLoc(DS.getTypeSpecTypeLoc());
+      TL.setParensRange(DS.getTypeofParensRange());
+    }
+    void VisitTypeOfTypeLoc(TypeOfTypeLoc TL) {
+      assert(DS.getTypeSpecType() == DeclSpec::TST_typeofType);
+      TL.setTypeofLoc(DS.getTypeSpecTypeLoc());
+      TL.setParensRange(DS.getTypeofParensRange());
+      assert(DS.getTypeRep());
+      TypeSourceInfo *TInfo = 0;
+      Sema::GetTypeFromParser(DS.getTypeRep(), &TInfo);
+      TL.setUnderlyingTInfo(TInfo);
+    }
+    void VisitBuiltinTypeLoc(BuiltinTypeLoc TL) {
+      // By default, use the source location of the type specifier.
+      TL.setBuiltinLoc(DS.getTypeSpecTypeLoc());
+      if (TL.needsExtraLocalData()) {
+        // Set info for the written builtin specifiers.
+        TL.getWrittenBuiltinSpecs() = DS.getWrittenBuiltinSpecs();
+        // Try to have a meaningful source location.
+        if (TL.getWrittenSignSpec() != TSS_unspecified)
+          // Sign spec loc overrides the others (e.g., 'unsigned long').
+          TL.setBuiltinLoc(DS.getTypeSpecSignLoc());
+        else if (TL.getWrittenWidthSpec() != TSW_unspecified)
+          // Width spec loc overrides type spec loc (e.g., 'short int').
+          TL.setBuiltinLoc(DS.getTypeSpecWidthLoc());
+      }
+    }
+    void VisitTypeLoc(TypeLoc TL) {
+      // FIXME: add other typespec types and change this to an assert.
+      TL.initialize(DS.getTypeSpecTypeLoc());
+    }
+  };
+
+  class DeclaratorLocFiller : public TypeLocVisitor<DeclaratorLocFiller> {
+    const DeclaratorChunk &Chunk;
+
+  public:
+    DeclaratorLocFiller(const DeclaratorChunk &Chunk) : Chunk(Chunk) {}
+
+    void VisitQualifiedTypeLoc(QualifiedTypeLoc TL) {
+      llvm_unreachable("qualified type locs not expected here!");
+    }
+
+    void VisitBlockPointerTypeLoc(BlockPointerTypeLoc TL) {
+      assert(Chunk.Kind == DeclaratorChunk::BlockPointer);
+      TL.setCaretLoc(Chunk.Loc);
+    }
+    void VisitPointerTypeLoc(PointerTypeLoc TL) {
+      assert(Chunk.Kind == DeclaratorChunk::Pointer);
+      TL.setStarLoc(Chunk.Loc);
+    }
+    void VisitObjCObjectPointerTypeLoc(ObjCObjectPointerTypeLoc TL) {
+      assert(Chunk.Kind == DeclaratorChunk::Pointer);
+      TL.setStarLoc(Chunk.Loc);
+      TL.setHasBaseTypeAsWritten(true);
+      TL.setHasProtocolsAsWritten(false);
+      TL.setLAngleLoc(SourceLocation());
+      TL.setRAngleLoc(SourceLocation());
+    }
+    void VisitMemberPointerTypeLoc(MemberPointerTypeLoc TL) {
+      assert(Chunk.Kind == DeclaratorChunk::MemberPointer);
+      TL.setStarLoc(Chunk.Loc);
+      // FIXME: nested name specifier
+    }
+    void VisitLValueReferenceTypeLoc(LValueReferenceTypeLoc TL) {
+      assert(Chunk.Kind == DeclaratorChunk::Reference);
+      // 'Amp' is misleading: this might have been originally
+      /// spelled with AmpAmp.
+      TL.setAmpLoc(Chunk.Loc);
+    }
+    void VisitRValueReferenceTypeLoc(RValueReferenceTypeLoc TL) {
+      assert(Chunk.Kind == DeclaratorChunk::Reference);
+      assert(!Chunk.Ref.LValueRef);
+      TL.setAmpAmpLoc(Chunk.Loc);
+    }
+    void VisitArrayTypeLoc(ArrayTypeLoc TL) {
+      assert(Chunk.Kind == DeclaratorChunk::Array);
+      TL.setLBracketLoc(Chunk.Loc);
+      TL.setRBracketLoc(Chunk.EndLoc);
+      TL.setSizeExpr(static_cast<Expr*>(Chunk.Arr.NumElts));
+    }
+    void VisitFunctionTypeLoc(FunctionTypeLoc TL) {
+      assert(Chunk.Kind == DeclaratorChunk::Function);
+      TL.setLParenLoc(Chunk.Loc);
+      TL.setRParenLoc(Chunk.EndLoc);
+
+      const DeclaratorChunk::FunctionTypeInfo &FTI = Chunk.Fun;
+      for (unsigned i = 0, e = TL.getNumArgs(), tpi = 0; i != e; ++i) {
+        ParmVarDecl *Param = FTI.ArgInfo[i].Param.getAs<ParmVarDecl>();
+        TL.setArg(tpi++, Param);
+      }
+      // FIXME: exception specs
+    }
+
+    void VisitTypeLoc(TypeLoc TL) {
+      llvm_unreachable("unsupported TypeLoc kind in declarator!");
+    }
+  };
+}
+
+/// \brief Create and instantiate a TypeSourceInfo with type source information.
+///
+/// \param T QualType referring to the type as written in source code.
+TypeSourceInfo *
+Sema::GetTypeSourceInfoForDeclarator(Declarator &D, QualType T) {
+  TypeSourceInfo *TInfo = Context.CreateTypeSourceInfo(T);
+  UnqualTypeLoc CurrTL = TInfo->getTypeLoc().getUnqualifiedLoc();
+
+  for (unsigned i = 0, e = D.getNumTypeObjects(); i != e; ++i) {
+    DeclaratorLocFiller(D.getTypeObject(i)).Visit(CurrTL);
+    CurrTL = CurrTL.getNextTypeLoc().getUnqualifiedLoc();
+  }
+  
+  TypeSpecLocFiller(D.getDeclSpec()).Visit(CurrTL);
+
+  return TInfo;
+}
+
+/// \brief Create a LocInfoType to hold the given QualType and TypeSourceInfo.
+QualType Sema::CreateLocInfoType(QualType T, TypeSourceInfo *TInfo) {
+  // FIXME: LocInfoTypes are "transient", only needed for passing to/from Parser
+  // and Sema during declaration parsing. Try deallocating/caching them when
+  // it's appropriate, instead of allocating them and keeping them around.
+  LocInfoType *LocT = (LocInfoType*)BumpAlloc.Allocate(sizeof(LocInfoType), 8);
+  new (LocT) LocInfoType(T, TInfo);
+  assert(LocT->getTypeClass() != T->getTypeClass() &&
+         "LocInfoType's TypeClass conflicts with an existing Type class");
+  return QualType(LocT, 0);
+}
+
+void LocInfoType::getAsStringInternal(std::string &Str,
+                                      const PrintingPolicy &Policy) const {
+  assert(false && "LocInfoType leaked into the type system; an opaque TypeTy*"
+         " was used directly instead of getting the QualType through"
+         " GetTypeFromParser");
+}
+
+/// UnwrapSimilarPointerTypes - If T1 and T2 are pointer types  that
+/// may be similar (C++ 4.4), replaces T1 and T2 with the type that
+/// they point to and return true. If T1 and T2 aren't pointer types
+/// or pointer-to-member types, or if they are not similar at this
+/// level, returns false and leaves T1 and T2 unchanged. Top-level
+/// qualifiers on T1 and T2 are ignored. This function will typically
+/// be called in a loop that successively "unwraps" pointer and
+/// pointer-to-member types to compare them at each level.
+bool Sema::UnwrapSimilarPointerTypes(QualType& T1, QualType& T2) {
+  const PointerType *T1PtrType = T1->getAs<PointerType>(),
+                    *T2PtrType = T2->getAs<PointerType>();
+  if (T1PtrType && T2PtrType) {
+    T1 = T1PtrType->getPointeeType();
+    T2 = T2PtrType->getPointeeType();
+    return true;
+  }
+
+  const MemberPointerType *T1MPType = T1->getAs<MemberPointerType>(),
+                          *T2MPType = T2->getAs<MemberPointerType>();
+  if (T1MPType && T2MPType &&
+      Context.getCanonicalType(T1MPType->getClass()) ==
+      Context.getCanonicalType(T2MPType->getClass())) {
+    T1 = T1MPType->getPointeeType();
+    T2 = T2MPType->getPointeeType();
+    return true;
+  }
+  return false;
+}
+
+Sema::TypeResult Sema::ActOnTypeName(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!");
+
+  TypeSourceInfo *TInfo = 0;
+  TagDecl *OwnedTag = 0;
+  QualType T = GetTypeForDeclarator(D, S, &TInfo, &OwnedTag);
+  if (D.isInvalidType())
+    return true;
+
+  if (getLangOptions().CPlusPlus) {
+    // Check that there are no default arguments (C++ only).
+    CheckExtraCXXDefaultArguments(D);
+
+    // C++0x [dcl.type]p3:
+    //   A type-specifier-seq shall not define a class or enumeration
+    //   unless it appears in the type-id of an alias-declaration
+    //   (7.1.3).
+    if (OwnedTag && OwnedTag->isDefinition())
+      Diag(OwnedTag->getLocation(), diag::err_type_defined_in_type_specifier)
+        << Context.getTypeDeclType(OwnedTag);
+  }
+
+  if (TInfo)
+    T = CreateLocInfoType(T, TInfo);
+
+  return T.getAsOpaquePtr();
+}
+
+
+
+//===----------------------------------------------------------------------===//
+// Type Attribute Processing
+//===----------------------------------------------------------------------===//
+
+/// HandleAddressSpaceTypeAttribute - Process an address_space attribute on the
+/// specified type.  The attribute contains 1 argument, the id of the address
+/// space for the type.
+static void HandleAddressSpaceTypeAttribute(QualType &Type,
+                                            const AttributeList &Attr, Sema &S){
+
+  // If this type is already address space qualified, reject it.
+  // Clause 6.7.3 - Type qualifiers: "No type shall be qualified by qualifiers
+  // for two or more different address spaces."
+  if (Type.getAddressSpace()) {
+    S.Diag(Attr.getLoc(), diag::err_attribute_address_multiple_qualifiers);
+    return;
+  }
+
+  // Check the attribute arguments.
+  if (Attr.getNumArgs() != 1) {
+    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
+    return;
+  }
+  Expr *ASArgExpr = static_cast<Expr *>(Attr.getArg(0));
+  llvm::APSInt addrSpace(32);
+  if (!ASArgExpr->isIntegerConstantExpr(addrSpace, S.Context)) {
+    S.Diag(Attr.getLoc(), diag::err_attribute_address_space_not_int)
+      << ASArgExpr->getSourceRange();
+    return;
+  }
+
+  // Bounds checking.
+  if (addrSpace.isSigned()) {
+    if (addrSpace.isNegative()) {
+      S.Diag(Attr.getLoc(), diag::err_attribute_address_space_negative)
+        << ASArgExpr->getSourceRange();
+      return;
+    }
+    addrSpace.setIsSigned(false);
+  }
+  llvm::APSInt max(addrSpace.getBitWidth());
+  max = Qualifiers::MaxAddressSpace;
+  if (addrSpace > max) {
+    S.Diag(Attr.getLoc(), diag::err_attribute_address_space_too_high)
+      << Qualifiers::MaxAddressSpace << ASArgExpr->getSourceRange();
+    return;
+  }
+
+  unsigned ASIdx = static_cast<unsigned>(addrSpace.getZExtValue());
+  Type = S.Context.getAddrSpaceQualType(Type, ASIdx);
+}
+
+/// HandleObjCGCTypeAttribute - Process an objc's gc attribute on the
+/// specified type.  The attribute contains 1 argument, weak or strong.
+static void HandleObjCGCTypeAttribute(QualType &Type,
+                                      const AttributeList &Attr, Sema &S) {
+  if (Type.getObjCGCAttr() != Qualifiers::GCNone) {
+    S.Diag(Attr.getLoc(), diag::err_attribute_multiple_objc_gc);
+    return;
+  }
+
+  // Check the attribute arguments.
+  if (!Attr.getParameterName()) {
+    S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_string)
+      << "objc_gc" << 1;
+    return;
+  }
+  Qualifiers::GC GCAttr;
+  if (Attr.getNumArgs() != 0) {
+    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
+    return;
+  }
+  if (Attr.getParameterName()->isStr("weak"))
+    GCAttr = Qualifiers::Weak;
+  else if (Attr.getParameterName()->isStr("strong"))
+    GCAttr = Qualifiers::Strong;
+  else {
+    S.Diag(Attr.getLoc(), diag::warn_attribute_type_not_supported)
+      << "objc_gc" << Attr.getParameterName();
+    return;
+  }
+
+  Type = S.Context.getObjCGCQualType(Type, GCAttr);
+}
+
+/// Process an individual function attribute.  Returns true if the
+/// attribute does not make sense to apply to this type.
+bool ProcessFnAttr(Sema &S, QualType &Type, const AttributeList &Attr) {
+  if (Attr.getKind() == AttributeList::AT_noreturn) {
+    // Complain immediately if the arg count is wrong.
+    if (Attr.getNumArgs() != 0) {
+      S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
+      return false;
+    }
+
+    // Delay if this is not a function or pointer to block.
+    if (!Type->isFunctionPointerType()
+        && !Type->isBlockPointerType()
+        && !Type->isFunctionType())
+      return true;
+
+    // Otherwise we can process right away.
+    Type = S.Context.getNoReturnType(Type);
+    return false;
+  }
+
+  // Otherwise, a calling convention.
+  if (Attr.getNumArgs() != 0) {
+    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
+    return false;
+  }
+
+  QualType T = Type;
+  if (const PointerType *PT = Type->getAs<PointerType>())
+    T = PT->getPointeeType();
+  const FunctionType *Fn = T->getAs<FunctionType>();
+
+  // Delay if the type didn't work out to a function.
+  if (!Fn) return true;
+
+  // TODO: diagnose uses of these conventions on the wrong target.
+  CallingConv CC;
+  switch (Attr.getKind()) {
+  case AttributeList::AT_cdecl: CC = CC_C; break;
+  case AttributeList::AT_fastcall: CC = CC_X86FastCall; break;
+  case AttributeList::AT_stdcall: CC = CC_X86StdCall; break;
+  default: llvm_unreachable("unexpected attribute kind"); return false;
+  }
+
+  CallingConv CCOld = Fn->getCallConv();
+  if (CC == CCOld) return false;
+
+  if (CCOld != CC_Default) {
+    // Should we diagnose reapplications of the same convention?
+    S.Diag(Attr.getLoc(), diag::err_attributes_are_not_compatible)
+      << FunctionType::getNameForCallConv(CC)
+      << FunctionType::getNameForCallConv(CCOld);
+    return false;
+  }
+
+  // Diagnose the use of X86 fastcall on varargs or unprototyped functions.
+  if (CC == CC_X86FastCall) {
+    if (isa<FunctionNoProtoType>(Fn)) {
+      S.Diag(Attr.getLoc(), diag::err_cconv_knr)
+        << FunctionType::getNameForCallConv(CC);
+      return false;
+    }
+
+    const FunctionProtoType *FnP = cast<FunctionProtoType>(Fn);
+    if (FnP->isVariadic()) {
+      S.Diag(Attr.getLoc(), diag::err_cconv_varargs)
+        << FunctionType::getNameForCallConv(CC);
+      return false;
+    }
+  }
+
+  Type = S.Context.getCallConvType(Type, CC);
+  return false;
+}
+
+/// HandleVectorSizeAttribute - 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.
+static void HandleVectorSizeAttr(QualType& CurType, const AttributeList &Attr, Sema &S) {
+  // Check the attribute arugments.
+  if (Attr.getNumArgs() != 1) {
+    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
+    return;
+  }
+  Expr *sizeExpr = static_cast<Expr *>(Attr.getArg(0));
+  llvm::APSInt vecSize(32);
+  if (!sizeExpr->isIntegerConstantExpr(vecSize, S.Context)) {
+    S.Diag(Attr.getLoc(), diag::err_attribute_argument_not_int)
+      << "vector_size" << sizeExpr->getSourceRange();
+    return;
+  }
+  // the base type must be integer or float, and can't already be a vector.
+  if (CurType->isVectorType() ||
+      (!CurType->isIntegerType() && !CurType->isRealFloatingType())) {
+    S.Diag(Attr.getLoc(), diag::err_attribute_invalid_vector_type) << CurType;
+    return;
+  }
+  unsigned typeSize = static_cast<unsigned>(S.Context.getTypeSize(CurType));
+  // vecSize is specified in bytes - convert to bits.
+  unsigned vectorSize = static_cast<unsigned>(vecSize.getZExtValue() * 8);
+
+  // the vector size needs to be an integral multiple of the type size.
+  if (vectorSize % typeSize) {
+    S.Diag(Attr.getLoc(), diag::err_attribute_invalid_size)
+      << sizeExpr->getSourceRange();
+    return;
+  }
+  if (vectorSize == 0) {
+    S.Diag(Attr.getLoc(), diag::err_attribute_zero_size)
+      << sizeExpr->getSourceRange();
+    return;
+  }
+
+  // Success! Instantiate the vector type, the number of elements is > 0, and
+  // not required to be a power of 2, unlike GCC.
+  CurType = S.Context.getVectorType(CurType, vectorSize/typeSize, false, false);
+}
+
+void ProcessTypeAttributeList(Sema &S, QualType &Result,
+                              const AttributeList *AL,
+                              DelayedAttributeSet &FnAttrs) {
+  // Scan through and apply attributes to this type where it makes sense.  Some
+  // attributes (such as __address_space__, __vector_size__, etc) apply to the
+  // type, but others can be present in the type specifiers even though they
+  // apply to the decl.  Here we apply type attributes and ignore the rest.
+  for (; AL; AL = AL->getNext()) {
+    // If this is an attribute we can handle, do so now, otherwise, add it to
+    // the LeftOverAttrs list for rechaining.
+    switch (AL->getKind()) {
+    default: break;
+
+    case AttributeList::AT_address_space:
+      HandleAddressSpaceTypeAttribute(Result, *AL, S);
+      break;
+    case AttributeList::AT_objc_gc:
+      HandleObjCGCTypeAttribute(Result, *AL, S);
+      break;
+    case AttributeList::AT_vector_size:
+      HandleVectorSizeAttr(Result, *AL, S);
+      break;
+
+    case AttributeList::AT_noreturn:
+    case AttributeList::AT_cdecl:
+    case AttributeList::AT_fastcall:
+    case AttributeList::AT_stdcall:
+      if (ProcessFnAttr(S, Result, *AL))
+        FnAttrs.push_back(DelayedAttribute(AL, Result));
+      break;
+    }
+  }
+}
+
+/// @brief Ensure that the type T is a complete type.
+///
+/// This routine checks whether the type @p T is complete in any
+/// context where a complete type is required. If @p T is a complete
+/// type, returns false. If @p T is a class template specialization,
+/// this routine then attempts to perform class template
+/// instantiation. If instantiation fails, or if @p T is incomplete
+/// and cannot be completed, issues the diagnostic @p diag (giving it
+/// the type @p T) and returns true.
+///
+/// @param Loc  The location in the source that the incomplete type
+/// diagnostic should refer to.
+///
+/// @param T  The type that this routine is examining for completeness.
+///
+/// @param PD The partial diagnostic that will be printed out if T is not a
+/// complete type.
+///
+/// @returns @c true if @p T is incomplete and a diagnostic was emitted,
+/// @c false otherwise.
+bool Sema::RequireCompleteType(SourceLocation Loc, QualType T,
+                               const PartialDiagnostic &PD,
+                               std::pair<SourceLocation, 
+                                         PartialDiagnostic> Note) {
+  unsigned diag = PD.getDiagID();
+
+  // FIXME: Add this assertion to make sure we always get instantiation points.
+  //  assert(!Loc.isInvalid() && "Invalid location in RequireCompleteType");
+  // FIXME: Add this assertion to help us flush out problems with
+  // checking for dependent types and type-dependent expressions.
+  //
+  //  assert(!T->isDependentType() &&
+  //         "Can't ask whether a dependent type is complete");
+
+  // If we have a complete type, we're done.
+  if (!T->isIncompleteType())
+    return false;
+
+  // If we have a class template specialization or a class member of a
+  // class template specialization, or an array with known size of such,
+  // try to instantiate it.
+  QualType MaybeTemplate = T;
+  if (const ConstantArrayType *Array = Context.getAsConstantArrayType(T))
+    MaybeTemplate = Array->getElementType();
+  if (const RecordType *Record = MaybeTemplate->getAs<RecordType>()) {
+    if (ClassTemplateSpecializationDecl *ClassTemplateSpec
+          = dyn_cast<ClassTemplateSpecializationDecl>(Record->getDecl())) {
+      if (ClassTemplateSpec->getSpecializationKind() == TSK_Undeclared)
+        return InstantiateClassTemplateSpecialization(Loc, ClassTemplateSpec,
+                                                      TSK_ImplicitInstantiation,
+                                                      /*Complain=*/diag != 0);
+    } else if (CXXRecordDecl *Rec
+                 = dyn_cast<CXXRecordDecl>(Record->getDecl())) {
+      if (CXXRecordDecl *Pattern = Rec->getInstantiatedFromMemberClass()) {
+        MemberSpecializationInfo *MSInfo = Rec->getMemberSpecializationInfo();
+        assert(MSInfo && "Missing member specialization information?");
+        // This record was instantiated from a class within a template.
+        if (MSInfo->getTemplateSpecializationKind() 
+                                               != TSK_ExplicitSpecialization)
+          return InstantiateClass(Loc, Rec, Pattern,
+                                  getTemplateInstantiationArgs(Rec),
+                                  TSK_ImplicitInstantiation,
+                                  /*Complain=*/diag != 0);
+      }
+    }
+  }
+
+  if (diag == 0)
+    return true;
+
+  // We have an incomplete type. Produce a diagnostic.
+  Diag(Loc, PD) << T;
+
+  // If we have a note, produce it.
+  if (!Note.first.isInvalid())
+    Diag(Note.first, Note.second);
+    
+  // If the type was a forward declaration of a class/struct/union
+  // type, produce
+  const TagType *Tag = 0;
+  if (const RecordType *Record = T->getAs<RecordType>())
+    Tag = Record;
+  else if (const EnumType *Enum = T->getAs<EnumType>())
+    Tag = Enum;
+
+  if (Tag && !Tag->getDecl()->isInvalidDecl())
+    Diag(Tag->getDecl()->getLocation(),
+         Tag->isBeingDefined() ? diag::note_type_being_defined
+                               : diag::note_forward_declaration)
+        << QualType(Tag, 0);
+
+  return true;
+}
+
+/// \brief Retrieve a version of the type 'T' that is qualified by the
+/// nested-name-specifier contained in SS.
+QualType Sema::getQualifiedNameType(const CXXScopeSpec &SS, QualType T) {
+  if (!SS.isSet() || SS.isInvalid() || T.isNull())
+    return T;
+
+  NestedNameSpecifier *NNS
+    = static_cast<NestedNameSpecifier *>(SS.getScopeRep());
+  return Context.getQualifiedNameType(NNS, T);
+}
+
+QualType Sema::BuildTypeofExprType(Expr *E) {
+  if (E->getType() == Context.OverloadTy) {
+    // C++ [temp.arg.explicit]p3 allows us to resolve a template-id to a 
+    // function template specialization wherever deduction cannot occur.
+    if (FunctionDecl *Specialization
+        = ResolveSingleFunctionTemplateSpecialization(E)) {
+      E = FixOverloadedFunctionReference(E, Specialization);
+      if (!E)
+        return QualType();      
+    } else {
+      Diag(E->getLocStart(),
+           diag::err_cannot_determine_declared_type_of_overloaded_function)
+        << false << E->getSourceRange();
+      return QualType();
+    }
+  }
+  
+  return Context.getTypeOfExprType(E);
+}
+
+QualType Sema::BuildDecltypeType(Expr *E) {
+  if (E->getType() == Context.OverloadTy) {
+    // C++ [temp.arg.explicit]p3 allows us to resolve a template-id to a 
+    // function template specialization wherever deduction cannot occur.
+    if (FunctionDecl *Specialization
+          = ResolveSingleFunctionTemplateSpecialization(E)) {
+      E = FixOverloadedFunctionReference(E, Specialization);
+      if (!E)
+        return QualType();      
+    } else {
+      Diag(E->getLocStart(),
+           diag::err_cannot_determine_declared_type_of_overloaded_function)
+        << true << E->getSourceRange();
+      return QualType();
+    }
+  }
+  
+  return Context.getDecltypeType(E);
+}
diff --git a/lib/Sema/TargetAttributesSema.cpp b/lib/Sema/TargetAttributesSema.cpp
new file mode 100644
index 0000000..7c19bf6
--- /dev/null
+++ b/lib/Sema/TargetAttributesSema.cpp
@@ -0,0 +1,86 @@
+//===-- TargetAttributesSema.cpp - Encapsulate target attributes-*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains semantic analysis implementation for target-specific
+// attributes.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Sema.h"
+#include "TargetAttributesSema.h"
+#include "clang/Basic/TargetInfo.h"
+#include "llvm/ADT/Triple.h"
+
+using namespace clang;
+
+TargetAttributesSema::~TargetAttributesSema() {}
+bool TargetAttributesSema::ProcessDeclAttribute(Scope *scope, Decl *D,
+                                    const AttributeList &Attr, Sema &S) const {
+  return false;
+}
+
+static void HandleMSP430InterruptAttr(Decl *d,
+                                      const AttributeList &Attr, Sema &S) {
+    // Check the attribute arguments.
+    if (Attr.getNumArgs() != 1) {
+      S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
+      return;
+    }
+
+    // FIXME: Check for decl - it should be void ()(void).
+
+    Expr *NumParamsExpr = static_cast<Expr *>(Attr.getArg(0));
+    llvm::APSInt NumParams(32);
+    if (!NumParamsExpr->isIntegerConstantExpr(NumParams, S.Context)) {
+      S.Diag(Attr.getLoc(), diag::err_attribute_argument_not_int)
+        << "interrupt" << NumParamsExpr->getSourceRange();
+      return;
+    }
+
+    unsigned Num = NumParams.getLimitedValue(255);
+    if ((Num & 1) || Num > 30) {
+      S.Diag(Attr.getLoc(), diag::err_attribute_argument_out_of_bounds)
+        << "interrupt" << (int)NumParams.getSExtValue()
+        << NumParamsExpr->getSourceRange();
+      return;
+    }
+
+    d->addAttr(::new (S.Context) MSP430InterruptAttr(Num));
+    d->addAttr(::new (S.Context) UsedAttr());
+  }
+
+namespace {
+  class MSP430AttributesSema : public TargetAttributesSema {
+  public:
+    MSP430AttributesSema() { }
+    bool ProcessDeclAttribute(Scope *scope, Decl *D,
+                              const AttributeList &Attr, Sema &S) const {
+      if (Attr.getName()->getName() == "interrupt") {
+        HandleMSP430InterruptAttr(D, Attr, S);
+        return true;
+      }
+      return false;
+    }
+  };
+}
+
+const TargetAttributesSema &Sema::getTargetAttributesSema() const {
+  if (TheTargetAttributesSema)
+    return *TheTargetAttributesSema;
+
+  const llvm::Triple &Triple(Context.Target.getTriple());
+  switch (Triple.getArch()) {
+  default:
+    return *(TheTargetAttributesSema = new TargetAttributesSema);
+
+  case llvm::Triple::msp430:
+    return *(TheTargetAttributesSema = new MSP430AttributesSema);
+  }
+}
+
diff --git a/lib/Sema/TargetAttributesSema.h b/lib/Sema/TargetAttributesSema.h
new file mode 100644
index 0000000..8794e40
--- /dev/null
+++ b/lib/Sema/TargetAttributesSema.h
@@ -0,0 +1,27 @@
+//===--- TargetAttributesSema.h - Semantic Analysis For Target Attributes -===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef CLANG_SEMA_TARGETSEMA_H
+#define CLANG_SEMA_TARGETSEMA_H
+
+namespace clang {
+  class Scope;
+  class Decl;
+  class Attr;
+  class Sema;
+
+  class TargetAttributesSema {
+  public:
+    virtual ~TargetAttributesSema();
+    virtual bool ProcessDeclAttribute(Scope *scope, Decl *D,
+                                      const AttributeList &Attr, Sema &S) const;
+  };
+}
+
+#endif
diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h
new file mode 100644
index 0000000..02dabbb
--- /dev/null
+++ b/lib/Sema/TreeTransform.h
@@ -0,0 +1,5705 @@
+//===------- TreeTransform.h - Semantic Tree Transformation -----*- C++ -*-===/
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//===----------------------------------------------------------------------===/
+//
+//  This file implements a semantic tree transformation that takes a given
+//  AST and rebuilds it, possibly transforming some nodes in the process.
+//
+//===----------------------------------------------------------------------===/
+#ifndef LLVM_CLANG_SEMA_TREETRANSFORM_H
+#define LLVM_CLANG_SEMA_TREETRANSFORM_H
+
+#include "Sema.h"
+#include "Lookup.h"
+#include "clang/Sema/SemaDiagnostic.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/ExprCXX.h"
+#include "clang/AST/ExprObjC.h"
+#include "clang/AST/Stmt.h"
+#include "clang/AST/StmtCXX.h"
+#include "clang/AST/StmtObjC.h"
+#include "clang/AST/TypeLocBuilder.h"
+#include "clang/Parse/Ownership.h"
+#include "clang/Parse/Designator.h"
+#include "clang/Lex/Preprocessor.h"
+#include "llvm/Support/ErrorHandling.h"
+#include <algorithm>
+
+namespace clang {
+
+/// \brief A semantic tree transformation that allows one to transform one
+/// abstract syntax tree into another.
+///
+/// A new tree transformation is defined by creating a new subclass \c X of
+/// \c TreeTransform<X> and then overriding certain operations to provide
+/// behavior specific to that transformation. For example, template
+/// instantiation is implemented as a tree transformation where the
+/// transformation of TemplateTypeParmType nodes involves substituting the
+/// template arguments for their corresponding template parameters; a similar
+/// transformation is performed for non-type template parameters and
+/// template template parameters.
+///
+/// This tree-transformation template uses static polymorphism to allow
+/// subclasses to customize any of its operations. Thus, a subclass can
+/// override any of the transformation or rebuild operators by providing an
+/// operation with the same signature as the default implementation. The
+/// overridding function should not be virtual.
+///
+/// Semantic tree transformations are split into two stages, either of which
+/// can be replaced by a subclass. The "transform" step transforms an AST node
+/// or the parts of an AST node using the various transformation functions,
+/// then passes the pieces on to the "rebuild" step, which constructs a new AST
+/// node of the appropriate kind from the pieces. The default transformation
+/// routines recursively transform the operands to composite AST nodes (e.g.,
+/// the pointee type of a PointerType node) and, if any of those operand nodes
+/// were changed by the transformation, invokes the rebuild operation to create
+/// a new AST node.
+///
+/// Subclasses can customize the transformation at various levels. The
+/// most coarse-grained transformations involve replacing TransformType(),
+/// TransformExpr(), TransformDecl(), TransformNestedNameSpecifier(),
+/// TransformTemplateName(), or TransformTemplateArgument() with entirely
+/// new implementations.
+///
+/// For more fine-grained transformations, subclasses can replace any of the
+/// \c TransformXXX functions (where XXX is the name of an AST node, e.g.,
+/// PointerType, StmtExpr) to alter the transformation. As mentioned previously,
+/// replacing TransformTemplateTypeParmType() allows template instantiation
+/// to substitute template arguments for their corresponding template
+/// parameters. Additionally, subclasses can override the \c RebuildXXX
+/// functions to control how AST nodes are rebuilt when their operands change.
+/// By default, \c TreeTransform will invoke semantic analysis to rebuild
+/// AST nodes. However, certain other tree transformations (e.g, cloning) may
+/// be able to use more efficient rebuild steps.
+///
+/// There are a handful of other functions that can be overridden, allowing one
+/// to avoid traversing nodes that don't need any transformation
+/// (\c AlreadyTransformed()), force rebuilding AST nodes even when their
+/// operands have not changed (\c AlwaysRebuild()), and customize the
+/// default locations and entity names used for type-checking
+/// (\c getBaseLocation(), \c getBaseEntity()).
+template<typename Derived>
+class TreeTransform {
+protected:
+  Sema &SemaRef;
+
+public:
+  typedef Sema::OwningStmtResult OwningStmtResult;
+  typedef Sema::OwningExprResult OwningExprResult;
+  typedef Sema::StmtArg StmtArg;
+  typedef Sema::ExprArg ExprArg;
+  typedef Sema::MultiExprArg MultiExprArg;
+  typedef Sema::MultiStmtArg MultiStmtArg;
+  typedef Sema::DeclPtrTy DeclPtrTy;
+  
+  /// \brief Initializes a new tree transformer.
+  TreeTransform(Sema &SemaRef) : SemaRef(SemaRef) { }
+
+  /// \brief Retrieves a reference to the derived class.
+  Derived &getDerived() { return static_cast<Derived&>(*this); }
+
+  /// \brief Retrieves a reference to the derived class.
+  const Derived &getDerived() const {
+    return static_cast<const Derived&>(*this);
+  }
+
+  /// \brief Retrieves a reference to the semantic analysis object used for
+  /// this tree transform.
+  Sema &getSema() const { return SemaRef; }
+
+  /// \brief Whether the transformation should always rebuild AST nodes, even
+  /// if none of the children have changed.
+  ///
+  /// Subclasses may override this function to specify when the transformation
+  /// should rebuild all AST nodes.
+  bool AlwaysRebuild() { return false; }
+
+  /// \brief Returns the location of the entity being transformed, if that
+  /// information was not available elsewhere in the AST.
+  ///
+  /// By default, returns no source-location information. Subclasses can
+  /// provide an alternative implementation that provides better location
+  /// information.
+  SourceLocation getBaseLocation() { return SourceLocation(); }
+
+  /// \brief Returns the name of the entity being transformed, if that
+  /// information was not available elsewhere in the AST.
+  ///
+  /// By default, returns an empty name. Subclasses can provide an alternative
+  /// implementation with a more precise name.
+  DeclarationName getBaseEntity() { return DeclarationName(); }
+
+  /// \brief Sets the "base" location and entity when that
+  /// information is known based on another transformation.
+  ///
+  /// By default, the source location and entity are ignored. Subclasses can
+  /// override this function to provide a customized implementation.
+  void setBase(SourceLocation Loc, DeclarationName Entity) { }
+
+  /// \brief RAII object that temporarily sets the base location and entity
+  /// used for reporting diagnostics in types.
+  class TemporaryBase {
+    TreeTransform &Self;
+    SourceLocation OldLocation;
+    DeclarationName OldEntity;
+
+  public:
+    TemporaryBase(TreeTransform &Self, SourceLocation Location,
+                  DeclarationName Entity) : Self(Self) {
+      OldLocation = Self.getDerived().getBaseLocation();
+      OldEntity = Self.getDerived().getBaseEntity();
+      Self.getDerived().setBase(Location, Entity);
+    }
+
+    ~TemporaryBase() {
+      Self.getDerived().setBase(OldLocation, OldEntity);
+    }
+  };
+
+  /// \brief Determine whether the given type \p T has already been
+  /// transformed.
+  ///
+  /// Subclasses can provide an alternative implementation of this routine
+  /// to short-circuit evaluation when it is known that a given type will
+  /// not change. For example, template instantiation need not traverse
+  /// non-dependent types.
+  bool AlreadyTransformed(QualType T) {
+    return T.isNull();
+  }
+
+  /// \brief Determine whether the given call argument should be dropped, e.g.,
+  /// because it is a default argument.
+  ///
+  /// Subclasses can provide an alternative implementation of this routine to
+  /// determine which kinds of call arguments get dropped. By default,
+  /// CXXDefaultArgument nodes are dropped (prior to transformation).
+  bool DropCallArgument(Expr *E) {
+    return E->isDefaultArgument();
+  }
+  
+  /// \brief Transforms the given type into another type.
+  ///
+  /// By default, this routine transforms a type by creating a
+  /// TypeSourceInfo for it and delegating to the appropriate
+  /// function.  This is expensive, but we don't mind, because
+  /// this method is deprecated anyway;  all users should be
+  /// switched to storing TypeSourceInfos.
+  ///
+  /// \returns the transformed type.
+  QualType TransformType(QualType T);
+
+  /// \brief Transforms the given type-with-location into a new
+  /// type-with-location.
+  ///
+  /// By default, this routine transforms a type by delegating to the
+  /// appropriate TransformXXXType to build a new type.  Subclasses
+  /// may override this function (to take over all type
+  /// transformations) or some set of the TransformXXXType functions
+  /// to alter the transformation.
+  TypeSourceInfo *TransformType(TypeSourceInfo *DI);
+
+  /// \brief Transform the given type-with-location into a new
+  /// type, collecting location information in the given builder
+  /// as necessary.
+  ///
+  QualType TransformType(TypeLocBuilder &TLB, TypeLoc TL);
+
+  /// \brief Transform the given statement.
+  ///
+  /// By default, this routine transforms a statement by delegating to the
+  /// appropriate TransformXXXStmt function to transform a specific kind of
+  /// statement or the TransformExpr() function to transform an expression.
+  /// Subclasses may override this function to transform statements using some
+  /// other mechanism.
+  ///
+  /// \returns the transformed statement.
+  OwningStmtResult TransformStmt(Stmt *S);
+
+  /// \brief Transform the given expression.
+  ///
+  /// By default, this routine transforms an expression by delegating to the
+  /// appropriate TransformXXXExpr function to build a new expression.
+  /// Subclasses may override this function to transform expressions using some
+  /// other mechanism.
+  ///
+  /// \returns the transformed expression.
+  OwningExprResult TransformExpr(Expr *E);
+
+  /// \brief Transform the given declaration, which is referenced from a type
+  /// or expression.
+  ///
+  /// By default, acts as the identity function on declarations. Subclasses
+  /// may override this function to provide alternate behavior.
+  Decl *TransformDecl(Decl *D) { return D; }
+
+  /// \brief Transform the definition of the given declaration.
+  ///
+  /// By default, invokes TransformDecl() to transform the declaration.
+  /// Subclasses may override this function to provide alternate behavior.
+  Decl *TransformDefinition(Decl *D) { return getDerived().TransformDecl(D); }
+
+  /// \brief Transform the given declaration, which was the first part of a
+  /// nested-name-specifier in a member access expression.
+  ///
+  /// This specific declaration transformation only applies to the first 
+  /// identifier in a nested-name-specifier of a member access expression, e.g.,
+  /// the \c T in \c x->T::member
+  ///
+  /// By default, invokes TransformDecl() to transform the declaration.
+  /// Subclasses may override this function to provide alternate behavior.
+  NamedDecl *TransformFirstQualifierInScope(NamedDecl *D, SourceLocation Loc) { 
+    return cast_or_null<NamedDecl>(getDerived().TransformDecl(D)); 
+  }
+  
+  /// \brief Transform the given nested-name-specifier.
+  ///
+  /// By default, transforms all of the types and declarations within the
+  /// nested-name-specifier. Subclasses may override this function to provide
+  /// alternate behavior.
+  NestedNameSpecifier *TransformNestedNameSpecifier(NestedNameSpecifier *NNS,
+                                                    SourceRange Range,
+                                              QualType ObjectType = QualType(),
+                                          NamedDecl *FirstQualifierInScope = 0);
+
+  /// \brief Transform the given declaration name.
+  ///
+  /// By default, transforms the types of conversion function, constructor,
+  /// and destructor names and then (if needed) rebuilds the declaration name.
+  /// Identifiers and selectors are returned unmodified. Sublcasses may
+  /// override this function to provide alternate behavior.
+  DeclarationName TransformDeclarationName(DeclarationName Name,
+                                           SourceLocation Loc,
+                                           QualType ObjectType = QualType());
+
+  /// \brief Transform the given template name.
+  ///
+  /// By default, transforms the template name by transforming the declarations
+  /// and nested-name-specifiers that occur within the template name.
+  /// Subclasses may override this function to provide alternate behavior.
+  TemplateName TransformTemplateName(TemplateName Name,
+                                     QualType ObjectType = QualType());
+
+  /// \brief Transform the given template argument.
+  ///
+  /// By default, this operation transforms the type, expression, or
+  /// declaration stored within the template argument and constructs a
+  /// new template argument from the transformed result. Subclasses may
+  /// override this function to provide alternate behavior.
+  ///
+  /// Returns true if there was an error.
+  bool TransformTemplateArgument(const TemplateArgumentLoc &Input,
+                                 TemplateArgumentLoc &Output);
+
+  /// \brief Fakes up a TemplateArgumentLoc for a given TemplateArgument.
+  void InventTemplateArgumentLoc(const TemplateArgument &Arg,
+                                 TemplateArgumentLoc &ArgLoc);
+
+  /// \brief Fakes up a TypeSourceInfo for a type.
+  TypeSourceInfo *InventTypeSourceInfo(QualType T) {
+    return SemaRef.Context.getTrivialTypeSourceInfo(T,
+                       getDerived().getBaseLocation());
+  }
+
+#define ABSTRACT_TYPELOC(CLASS, PARENT)
+#define TYPELOC(CLASS, PARENT)                                   \
+  QualType Transform##CLASS##Type(TypeLocBuilder &TLB, CLASS##TypeLoc T);
+#include "clang/AST/TypeLocNodes.def"
+
+  QualType TransformReferenceType(TypeLocBuilder &TLB, ReferenceTypeLoc TL);
+
+  QualType 
+  TransformTemplateSpecializationType(const TemplateSpecializationType *T,
+                                      QualType ObjectType);
+
+  QualType
+  TransformTemplateSpecializationType(TypeLocBuilder &TLB,
+                                      TemplateSpecializationTypeLoc TL,
+                                      QualType ObjectType);
+  
+  OwningStmtResult TransformCompoundStmt(CompoundStmt *S, bool IsStmtExpr);
+
+#define STMT(Node, Parent)                        \
+  OwningStmtResult Transform##Node(Node *S);
+#define EXPR(Node, Parent)                        \
+  OwningExprResult Transform##Node(Node *E);
+#define ABSTRACT_EXPR(Node, Parent)
+#include "clang/AST/StmtNodes.def"
+
+  /// \brief Build a new pointer type given its pointee type.
+  ///
+  /// By default, performs semantic analysis when building the pointer type.
+  /// Subclasses may override this routine to provide different behavior.
+  QualType RebuildPointerType(QualType PointeeType, SourceLocation Sigil);
+
+  /// \brief Build a new block pointer type given its pointee type.
+  ///
+  /// By default, performs semantic analysis when building the block pointer
+  /// type. Subclasses may override this routine to provide different behavior.
+  QualType RebuildBlockPointerType(QualType PointeeType, SourceLocation Sigil);
+
+  /// \brief Build a new reference type given the type it references.
+  ///
+  /// By default, performs semantic analysis when building the
+  /// reference type. Subclasses may override this routine to provide
+  /// different behavior.
+  ///
+  /// \param LValue whether the type was written with an lvalue sigil
+  /// or an rvalue sigil.
+  QualType RebuildReferenceType(QualType ReferentType,
+                                bool LValue,
+                                SourceLocation Sigil);
+
+  /// \brief Build a new member pointer type given the pointee type and the
+  /// class type it refers into.
+  ///
+  /// By default, performs semantic analysis when building the member pointer
+  /// type. Subclasses may override this routine to provide different behavior.
+  QualType RebuildMemberPointerType(QualType PointeeType, QualType ClassType,
+                                    SourceLocation Sigil);
+
+  /// \brief Build a new Objective C object pointer type.
+  QualType RebuildObjCObjectPointerType(QualType PointeeType,
+                                        SourceLocation Sigil);
+
+  /// \brief Build a new array type given the element type, size
+  /// modifier, size of the array (if known), size expression, and index type
+  /// qualifiers.
+  ///
+  /// By default, performs semantic analysis when building the array type.
+  /// Subclasses may override this routine to provide different behavior.
+  /// Also by default, all of the other Rebuild*Array
+  QualType RebuildArrayType(QualType ElementType,
+                            ArrayType::ArraySizeModifier SizeMod,
+                            const llvm::APInt *Size,
+                            Expr *SizeExpr,
+                            unsigned IndexTypeQuals,
+                            SourceRange BracketsRange);
+
+  /// \brief Build a new constant array type given the element type, size
+  /// modifier, (known) size of the array, and index type qualifiers.
+  ///
+  /// By default, performs semantic analysis when building the array type.
+  /// Subclasses may override this routine to provide different behavior.
+  QualType RebuildConstantArrayType(QualType ElementType,
+                                    ArrayType::ArraySizeModifier SizeMod,
+                                    const llvm::APInt &Size,
+                                    unsigned IndexTypeQuals,
+                                    SourceRange BracketsRange);
+
+  /// \brief Build a new incomplete array type given the element type, size
+  /// modifier, and index type qualifiers.
+  ///
+  /// By default, performs semantic analysis when building the array type.
+  /// Subclasses may override this routine to provide different behavior.
+  QualType RebuildIncompleteArrayType(QualType ElementType,
+                                      ArrayType::ArraySizeModifier SizeMod,
+                                      unsigned IndexTypeQuals,
+                                      SourceRange BracketsRange);
+
+  /// \brief Build a new variable-length array type given the element type,
+  /// size modifier, size expression, and index type qualifiers.
+  ///
+  /// By default, performs semantic analysis when building the array type.
+  /// Subclasses may override this routine to provide different behavior.
+  QualType RebuildVariableArrayType(QualType ElementType,
+                                    ArrayType::ArraySizeModifier SizeMod,
+                                    ExprArg SizeExpr,
+                                    unsigned IndexTypeQuals,
+                                    SourceRange BracketsRange);
+
+  /// \brief Build a new dependent-sized array type given the element type,
+  /// size modifier, size expression, and index type qualifiers.
+  ///
+  /// By default, performs semantic analysis when building the array type.
+  /// Subclasses may override this routine to provide different behavior.
+  QualType RebuildDependentSizedArrayType(QualType ElementType,
+                                          ArrayType::ArraySizeModifier SizeMod,
+                                          ExprArg SizeExpr,
+                                          unsigned IndexTypeQuals,
+                                          SourceRange BracketsRange);
+
+  /// \brief Build a new vector type given the element type and
+  /// number of elements.
+  ///
+  /// By default, performs semantic analysis when building the vector type.
+  /// Subclasses may override this routine to provide different behavior.
+  QualType RebuildVectorType(QualType ElementType, unsigned NumElements,
+    bool IsAltiVec, bool IsPixel);
+
+  /// \brief Build a new extended vector type given the element type and
+  /// number of elements.
+  ///
+  /// By default, performs semantic analysis when building the vector type.
+  /// Subclasses may override this routine to provide different behavior.
+  QualType RebuildExtVectorType(QualType ElementType, unsigned NumElements,
+                                SourceLocation AttributeLoc);
+
+  /// \brief Build a new potentially dependently-sized extended vector type
+  /// given the element type and number of elements.
+  ///
+  /// By default, performs semantic analysis when building the vector type.
+  /// Subclasses may override this routine to provide different behavior.
+  QualType RebuildDependentSizedExtVectorType(QualType ElementType,
+                                              ExprArg SizeExpr,
+                                              SourceLocation AttributeLoc);
+
+  /// \brief Build a new function type.
+  ///
+  /// By default, performs semantic analysis when building the function type.
+  /// Subclasses may override this routine to provide different behavior.
+  QualType RebuildFunctionProtoType(QualType T,
+                                    QualType *ParamTypes,
+                                    unsigned NumParamTypes,
+                                    bool Variadic, unsigned Quals);
+
+  /// \brief Build a new unprototyped function type.
+  QualType RebuildFunctionNoProtoType(QualType ResultType);
+
+  /// \brief Rebuild an unresolved typename type, given the decl that
+  /// the UnresolvedUsingTypenameDecl was transformed to.
+  QualType RebuildUnresolvedUsingType(Decl *D);
+
+  /// \brief Build a new typedef type.
+  QualType RebuildTypedefType(TypedefDecl *Typedef) {
+    return SemaRef.Context.getTypeDeclType(Typedef);
+  }
+
+  /// \brief Build a new class/struct/union type.
+  QualType RebuildRecordType(RecordDecl *Record) {
+    return SemaRef.Context.getTypeDeclType(Record);
+  }
+
+  /// \brief Build a new Enum type.
+  QualType RebuildEnumType(EnumDecl *Enum) {
+    return SemaRef.Context.getTypeDeclType(Enum);
+  }
+
+  /// \brief Build a new elaborated type.
+  QualType RebuildElaboratedType(QualType T, ElaboratedType::TagKind Tag) {
+    return SemaRef.Context.getElaboratedType(T, Tag);
+  }
+
+  /// \brief Build a new typeof(expr) type.
+  ///
+  /// By default, performs semantic analysis when building the typeof type.
+  /// Subclasses may override this routine to provide different behavior.
+  QualType RebuildTypeOfExprType(ExprArg Underlying);
+
+  /// \brief Build a new typeof(type) type.
+  ///
+  /// By default, builds a new TypeOfType with the given underlying type.
+  QualType RebuildTypeOfType(QualType Underlying);
+
+  /// \brief Build a new C++0x decltype type.
+  ///
+  /// By default, performs semantic analysis when building the decltype type.
+  /// Subclasses may override this routine to provide different behavior.
+  QualType RebuildDecltypeType(ExprArg Underlying);
+
+  /// \brief Build a new template specialization type.
+  ///
+  /// By default, performs semantic analysis when building the template
+  /// specialization type. Subclasses may override this routine to provide
+  /// different behavior.
+  QualType RebuildTemplateSpecializationType(TemplateName Template,
+                                             SourceLocation TemplateLoc,
+                                       const TemplateArgumentListInfo &Args);
+
+  /// \brief Build a new qualified name type.
+  ///
+  /// By default, builds a new QualifiedNameType type from the
+  /// nested-name-specifier and the named type. Subclasses may override
+  /// this routine to provide different behavior.
+  QualType RebuildQualifiedNameType(NestedNameSpecifier *NNS, QualType Named) {
+    return SemaRef.Context.getQualifiedNameType(NNS, Named);
+  }
+
+  /// \brief Build a new typename type that refers to a template-id.
+  ///
+  /// By default, builds a new TypenameType type from the nested-name-specifier
+  /// and the given type. Subclasses may override this routine to provide
+  /// different behavior.
+  QualType RebuildTypenameType(NestedNameSpecifier *NNS, QualType T) {
+    if (NNS->isDependent())
+      return SemaRef.Context.getTypenameType(NNS,
+                                          cast<TemplateSpecializationType>(T));
+
+    return SemaRef.Context.getQualifiedNameType(NNS, T);
+  }
+
+  /// \brief Build a new typename type that refers to an identifier.
+  ///
+  /// By default, performs semantic analysis when building the typename type
+  /// (or qualified name type). Subclasses may override this routine to provide
+  /// different behavior.
+  QualType RebuildTypenameType(NestedNameSpecifier *NNS,
+                               const IdentifierInfo *Id,
+                               SourceRange SR) {
+    return SemaRef.CheckTypenameType(NNS, *Id, SR);
+  }
+
+  /// \brief Build a new nested-name-specifier given the prefix and an
+  /// identifier that names the next step in the nested-name-specifier.
+  ///
+  /// By default, performs semantic analysis when building the new
+  /// nested-name-specifier. Subclasses may override this routine to provide
+  /// different behavior.
+  NestedNameSpecifier *RebuildNestedNameSpecifier(NestedNameSpecifier *Prefix,
+                                                  SourceRange Range,
+                                                  IdentifierInfo &II,
+                                                  QualType ObjectType,
+                                              NamedDecl *FirstQualifierInScope);
+
+  /// \brief Build a new nested-name-specifier given the prefix and the
+  /// namespace named in the next step in the nested-name-specifier.
+  ///
+  /// By default, performs semantic analysis when building the new
+  /// nested-name-specifier. Subclasses may override this routine to provide
+  /// different behavior.
+  NestedNameSpecifier *RebuildNestedNameSpecifier(NestedNameSpecifier *Prefix,
+                                                  SourceRange Range,
+                                                  NamespaceDecl *NS);
+
+  /// \brief Build a new nested-name-specifier given the prefix and the
+  /// type named in the next step in the nested-name-specifier.
+  ///
+  /// By default, performs semantic analysis when building the new
+  /// nested-name-specifier. Subclasses may override this routine to provide
+  /// different behavior.
+  NestedNameSpecifier *RebuildNestedNameSpecifier(NestedNameSpecifier *Prefix,
+                                                  SourceRange Range,
+                                                  bool TemplateKW,
+                                                  QualType T);
+
+  /// \brief Build a new template name given a nested name specifier, a flag
+  /// indicating whether the "template" keyword was provided, and the template
+  /// that the template name refers to.
+  ///
+  /// By default, builds the new template name directly. Subclasses may override
+  /// this routine to provide different behavior.
+  TemplateName RebuildTemplateName(NestedNameSpecifier *Qualifier,
+                                   bool TemplateKW,
+                                   TemplateDecl *Template);
+
+  /// \brief Build a new template name given a nested name specifier and the
+  /// name that is referred to as a template.
+  ///
+  /// By default, performs semantic analysis to determine whether the name can
+  /// be resolved to a specific template, then builds the appropriate kind of
+  /// template name. Subclasses may override this routine to provide different
+  /// behavior.
+  TemplateName RebuildTemplateName(NestedNameSpecifier *Qualifier,
+                                   const IdentifierInfo &II,
+                                   QualType ObjectType);
+
+  /// \brief Build a new template name given a nested name specifier and the
+  /// overloaded operator name that is referred to as a template.
+  ///
+  /// By default, performs semantic analysis to determine whether the name can
+  /// be resolved to a specific template, then builds the appropriate kind of
+  /// template name. Subclasses may override this routine to provide different
+  /// behavior.
+  TemplateName RebuildTemplateName(NestedNameSpecifier *Qualifier,
+                                   OverloadedOperatorKind Operator,
+                                   QualType ObjectType);
+  
+  /// \brief Build a new compound statement.
+  ///
+  /// By default, performs semantic analysis to build the new statement.
+  /// Subclasses may override this routine to provide different behavior.
+  OwningStmtResult RebuildCompoundStmt(SourceLocation LBraceLoc,
+                                       MultiStmtArg Statements,
+                                       SourceLocation RBraceLoc,
+                                       bool IsStmtExpr) {
+    return getSema().ActOnCompoundStmt(LBraceLoc, RBraceLoc, move(Statements),
+                                       IsStmtExpr);
+  }
+
+  /// \brief Build a new case statement.
+  ///
+  /// By default, performs semantic analysis to build the new statement.
+  /// Subclasses may override this routine to provide different behavior.
+  OwningStmtResult RebuildCaseStmt(SourceLocation CaseLoc,
+                                   ExprArg LHS,
+                                   SourceLocation EllipsisLoc,
+                                   ExprArg RHS,
+                                   SourceLocation ColonLoc) {
+    return getSema().ActOnCaseStmt(CaseLoc, move(LHS), EllipsisLoc, move(RHS),
+                                   ColonLoc);
+  }
+
+  /// \brief Attach the body to a new case statement.
+  ///
+  /// By default, performs semantic analysis to build the new statement.
+  /// Subclasses may override this routine to provide different behavior.
+  OwningStmtResult RebuildCaseStmtBody(StmtArg S, StmtArg Body) {
+    getSema().ActOnCaseStmtBody(S.get(), move(Body));
+    return move(S);
+  }
+
+  /// \brief Build a new default statement.
+  ///
+  /// By default, performs semantic analysis to build the new statement.
+  /// Subclasses may override this routine to provide different behavior.
+  OwningStmtResult RebuildDefaultStmt(SourceLocation DefaultLoc,
+                                      SourceLocation ColonLoc,
+                                      StmtArg SubStmt) {
+    return getSema().ActOnDefaultStmt(DefaultLoc, ColonLoc, move(SubStmt),
+                                      /*CurScope=*/0);
+  }
+
+  /// \brief Build a new label statement.
+  ///
+  /// By default, performs semantic analysis to build the new statement.
+  /// Subclasses may override this routine to provide different behavior.
+  OwningStmtResult RebuildLabelStmt(SourceLocation IdentLoc,
+                                    IdentifierInfo *Id,
+                                    SourceLocation ColonLoc,
+                                    StmtArg SubStmt) {
+    return SemaRef.ActOnLabelStmt(IdentLoc, Id, ColonLoc, move(SubStmt));
+  }
+
+  /// \brief Build a new "if" statement.
+  ///
+  /// By default, performs semantic analysis to build the new statement.
+  /// Subclasses may override this routine to provide different behavior.
+  OwningStmtResult RebuildIfStmt(SourceLocation IfLoc, Sema::FullExprArg Cond,
+                                 VarDecl *CondVar, StmtArg Then, 
+                                 SourceLocation ElseLoc, StmtArg Else) {
+    return getSema().ActOnIfStmt(IfLoc, Cond, DeclPtrTy::make(CondVar), 
+                                 move(Then), ElseLoc, move(Else));
+  }
+
+  /// \brief Start building a new switch statement.
+  ///
+  /// By default, performs semantic analysis to build the new statement.
+  /// Subclasses may override this routine to provide different behavior.
+  OwningStmtResult RebuildSwitchStmtStart(Sema::FullExprArg Cond, 
+                                          VarDecl *CondVar) {
+    return getSema().ActOnStartOfSwitchStmt(Cond, DeclPtrTy::make(CondVar));
+  }
+
+  /// \brief Attach the body to the switch statement.
+  ///
+  /// By default, performs semantic analysis to build the new statement.
+  /// Subclasses may override this routine to provide different behavior.
+  OwningStmtResult RebuildSwitchStmtBody(SourceLocation SwitchLoc,
+                                         StmtArg Switch, StmtArg Body) {
+    return getSema().ActOnFinishSwitchStmt(SwitchLoc, move(Switch),
+                                         move(Body));
+  }
+
+  /// \brief Build a new while statement.
+  ///
+  /// By default, performs semantic analysis to build the new statement.
+  /// Subclasses may override this routine to provide different behavior.
+  OwningStmtResult RebuildWhileStmt(SourceLocation WhileLoc,
+                                    Sema::FullExprArg Cond,
+                                    VarDecl *CondVar,
+                                    StmtArg Body) {
+    return getSema().ActOnWhileStmt(WhileLoc, Cond, DeclPtrTy::make(CondVar),
+                                    move(Body));
+  }
+
+  /// \brief Build a new do-while statement.
+  ///
+  /// By default, performs semantic analysis to build the new statement.
+  /// Subclasses may override this routine to provide different behavior.
+  OwningStmtResult RebuildDoStmt(SourceLocation DoLoc, StmtArg Body,
+                                 SourceLocation WhileLoc,
+                                 SourceLocation LParenLoc,
+                                 ExprArg Cond,
+                                 SourceLocation RParenLoc) {
+    return getSema().ActOnDoStmt(DoLoc, move(Body), WhileLoc, LParenLoc,
+                                 move(Cond), RParenLoc);
+  }
+
+  /// \brief Build a new for statement.
+  ///
+  /// By default, performs semantic analysis to build the new statement.
+  /// Subclasses may override this routine to provide different behavior.
+  OwningStmtResult RebuildForStmt(SourceLocation ForLoc,
+                                  SourceLocation LParenLoc,
+                                  StmtArg Init, Sema::FullExprArg Cond, 
+                                  VarDecl *CondVar, Sema::FullExprArg Inc,
+                                  SourceLocation RParenLoc, StmtArg Body) {
+    return getSema().ActOnForStmt(ForLoc, LParenLoc, move(Init), Cond, 
+                                  DeclPtrTy::make(CondVar),
+                                  Inc, RParenLoc, move(Body));
+  }
+
+  /// \brief Build a new goto statement.
+  ///
+  /// By default, performs semantic analysis to build the new statement.
+  /// Subclasses may override this routine to provide different behavior.
+  OwningStmtResult RebuildGotoStmt(SourceLocation GotoLoc,
+                                   SourceLocation LabelLoc,
+                                   LabelStmt *Label) {
+    return getSema().ActOnGotoStmt(GotoLoc, LabelLoc, Label->getID());
+  }
+
+  /// \brief Build a new indirect goto statement.
+  ///
+  /// By default, performs semantic analysis to build the new statement.
+  /// Subclasses may override this routine to provide different behavior.
+  OwningStmtResult RebuildIndirectGotoStmt(SourceLocation GotoLoc,
+                                           SourceLocation StarLoc,
+                                           ExprArg Target) {
+    return getSema().ActOnIndirectGotoStmt(GotoLoc, StarLoc, move(Target));
+  }
+
+  /// \brief Build a new return statement.
+  ///
+  /// By default, performs semantic analysis to build the new statement.
+  /// Subclasses may override this routine to provide different behavior.
+  OwningStmtResult RebuildReturnStmt(SourceLocation ReturnLoc,
+                                     ExprArg Result) {
+
+    return getSema().ActOnReturnStmt(ReturnLoc, move(Result));
+  }
+
+  /// \brief Build a new declaration statement.
+  ///
+  /// By default, performs semantic analysis to build the new statement.
+  /// Subclasses may override this routine to provide different behavior.
+  OwningStmtResult RebuildDeclStmt(Decl **Decls, unsigned NumDecls,
+                                   SourceLocation StartLoc,
+                                   SourceLocation EndLoc) {
+    return getSema().Owned(
+             new (getSema().Context) DeclStmt(
+                                        DeclGroupRef::Create(getSema().Context,
+                                                             Decls, NumDecls),
+                                              StartLoc, EndLoc));
+  }
+
+  /// \brief Build a new inline asm statement.
+  ///
+  /// By default, performs semantic analysis to build the new statement.
+  /// Subclasses may override this routine to provide different behavior.
+  OwningStmtResult RebuildAsmStmt(SourceLocation AsmLoc,
+                                  bool IsSimple,
+                                  bool IsVolatile,
+                                  unsigned NumOutputs,
+                                  unsigned NumInputs,
+                                  IdentifierInfo **Names,
+                                  MultiExprArg Constraints,
+                                  MultiExprArg Exprs,
+                                  ExprArg AsmString,
+                                  MultiExprArg Clobbers,
+                                  SourceLocation RParenLoc,
+                                  bool MSAsm) {
+    return getSema().ActOnAsmStmt(AsmLoc, IsSimple, IsVolatile, NumOutputs, 
+                                  NumInputs, Names, move(Constraints),
+                                  move(Exprs), move(AsmString), move(Clobbers),
+                                  RParenLoc, MSAsm);
+  }
+  
+  /// \brief Build a new C++ exception declaration.
+  ///
+  /// By default, performs semantic analysis to build the new decaration.
+  /// Subclasses may override this routine to provide different behavior.
+  VarDecl *RebuildExceptionDecl(VarDecl *ExceptionDecl, QualType T,
+                                TypeSourceInfo *Declarator,
+                                IdentifierInfo *Name,
+                                SourceLocation Loc,
+                                SourceRange TypeRange) {
+    return getSema().BuildExceptionDeclaration(0, T, Declarator, Name, Loc,
+                                               TypeRange);
+  }
+
+  /// \brief Build a new C++ catch statement.
+  ///
+  /// By default, performs semantic analysis to build the new statement.
+  /// Subclasses may override this routine to provide different behavior.
+  OwningStmtResult RebuildCXXCatchStmt(SourceLocation CatchLoc,
+                                       VarDecl *ExceptionDecl,
+                                       StmtArg Handler) {
+    return getSema().Owned(
+             new (getSema().Context) CXXCatchStmt(CatchLoc, ExceptionDecl,
+                                                  Handler.takeAs<Stmt>()));
+  }
+
+  /// \brief Build a new C++ try statement.
+  ///
+  /// By default, performs semantic analysis to build the new statement.
+  /// Subclasses may override this routine to provide different behavior.
+  OwningStmtResult RebuildCXXTryStmt(SourceLocation TryLoc,
+                                     StmtArg TryBlock,
+                                     MultiStmtArg Handlers) {
+    return getSema().ActOnCXXTryBlock(TryLoc, move(TryBlock), move(Handlers));
+  }
+
+  /// \brief Build a new expression that references a declaration.
+  ///
+  /// By default, performs semantic analysis to build the new expression.
+  /// Subclasses may override this routine to provide different behavior.
+  OwningExprResult RebuildDeclarationNameExpr(const CXXScopeSpec &SS,
+                                              LookupResult &R,
+                                              bool RequiresADL) {
+    return getSema().BuildDeclarationNameExpr(SS, R, RequiresADL);
+  }
+
+
+  /// \brief Build a new expression that references a declaration.
+  ///
+  /// By default, performs semantic analysis to build the new expression.
+  /// Subclasses may override this routine to provide different behavior.
+  OwningExprResult RebuildDeclRefExpr(NestedNameSpecifier *Qualifier,
+                                      SourceRange QualifierRange,
+                                      ValueDecl *VD, SourceLocation Loc,
+                                      TemplateArgumentListInfo *TemplateArgs) {
+    CXXScopeSpec SS;
+    SS.setScopeRep(Qualifier);
+    SS.setRange(QualifierRange);
+
+    // FIXME: loses template args.
+    
+    return getSema().BuildDeclarationNameExpr(SS, Loc, VD);
+  }
+
+  /// \brief Build a new expression in parentheses.
+  ///
+  /// By default, performs semantic analysis to build the new expression.
+  /// Subclasses may override this routine to provide different behavior.
+  OwningExprResult RebuildParenExpr(ExprArg SubExpr, SourceLocation LParen,
+                                    SourceLocation RParen) {
+    return getSema().ActOnParenExpr(LParen, RParen, move(SubExpr));
+  }
+
+  /// \brief Build a new pseudo-destructor expression.
+  ///
+  /// By default, performs semantic analysis to build the new expression.
+  /// Subclasses may override this routine to provide different behavior.
+  OwningExprResult RebuildCXXPseudoDestructorExpr(ExprArg Base,
+                                                  SourceLocation OperatorLoc,
+                                                  bool isArrow,
+                                              SourceLocation DestroyedTypeLoc,
+                                                  QualType DestroyedType,
+                                               NestedNameSpecifier *Qualifier,
+                                                  SourceRange QualifierRange) {
+    CXXScopeSpec SS;
+    if (Qualifier) {
+      SS.setRange(QualifierRange);
+      SS.setScopeRep(Qualifier);
+    }
+
+    QualType BaseType = ((Expr*) Base.get())->getType();
+
+    DeclarationName Name
+      = SemaRef.Context.DeclarationNames.getCXXDestructorName(
+                               SemaRef.Context.getCanonicalType(DestroyedType));
+
+    return getSema().BuildMemberReferenceExpr(move(Base), BaseType,
+                                              OperatorLoc, isArrow,
+                                              SS, /*FIXME: FirstQualifier*/ 0,
+                                              Name, DestroyedTypeLoc,
+                                              /*TemplateArgs*/ 0);
+  }
+
+  /// \brief Build a new unary operator expression.
+  ///
+  /// By default, performs semantic analysis to build the new expression.
+  /// Subclasses may override this routine to provide different behavior.
+  OwningExprResult RebuildUnaryOperator(SourceLocation OpLoc,
+                                        UnaryOperator::Opcode Opc,
+                                        ExprArg SubExpr) {
+    return getSema().BuildUnaryOp(/*Scope=*/0, OpLoc, Opc, move(SubExpr));
+  }
+
+  /// \brief Build a new sizeof or alignof expression with a type argument.
+  ///
+  /// By default, performs semantic analysis to build the new expression.
+  /// Subclasses may override this routine to provide different behavior.
+  OwningExprResult RebuildSizeOfAlignOf(TypeSourceInfo *TInfo,
+                                        SourceLocation OpLoc,
+                                        bool isSizeOf, SourceRange R) {
+    return getSema().CreateSizeOfAlignOfExpr(TInfo, OpLoc, isSizeOf, R);
+  }
+
+  /// \brief Build a new sizeof or alignof expression with an expression
+  /// argument.
+  ///
+  /// By default, performs semantic analysis to build the new expression.
+  /// Subclasses may override this routine to provide different behavior.
+  OwningExprResult RebuildSizeOfAlignOf(ExprArg SubExpr, SourceLocation OpLoc,
+                                        bool isSizeOf, SourceRange R) {
+    OwningExprResult Result
+      = getSema().CreateSizeOfAlignOfExpr((Expr *)SubExpr.get(),
+                                          OpLoc, isSizeOf, R);
+    if (Result.isInvalid())
+      return getSema().ExprError();
+
+    SubExpr.release();
+    return move(Result);
+  }
+
+  /// \brief Build a new array subscript expression.
+  ///
+  /// By default, performs semantic analysis to build the new expression.
+  /// Subclasses may override this routine to provide different behavior.
+  OwningExprResult RebuildArraySubscriptExpr(ExprArg LHS,
+                                             SourceLocation LBracketLoc,
+                                             ExprArg RHS,
+                                             SourceLocation RBracketLoc) {
+    return getSema().ActOnArraySubscriptExpr(/*Scope=*/0, move(LHS),
+                                             LBracketLoc, move(RHS),
+                                             RBracketLoc);
+  }
+
+  /// \brief Build a new call expression.
+  ///
+  /// By default, performs semantic analysis to build the new expression.
+  /// Subclasses may override this routine to provide different behavior.
+  OwningExprResult RebuildCallExpr(ExprArg Callee, SourceLocation LParenLoc,
+                                   MultiExprArg Args,
+                                   SourceLocation *CommaLocs,
+                                   SourceLocation RParenLoc) {
+    return getSema().ActOnCallExpr(/*Scope=*/0, move(Callee), LParenLoc,
+                                   move(Args), CommaLocs, RParenLoc);
+  }
+
+  /// \brief Build a new member access expression.
+  ///
+  /// By default, performs semantic analysis to build the new expression.
+  /// Subclasses may override this routine to provide different behavior.
+  OwningExprResult RebuildMemberExpr(ExprArg Base, SourceLocation OpLoc,
+                                     bool isArrow,
+                                     NestedNameSpecifier *Qualifier,
+                                     SourceRange QualifierRange,
+                                     SourceLocation MemberLoc,
+                                     ValueDecl *Member,
+                        const TemplateArgumentListInfo *ExplicitTemplateArgs,
+                                     NamedDecl *FirstQualifierInScope) {
+    if (!Member->getDeclName()) {
+      // We have a reference to an unnamed field.
+      assert(!Qualifier && "Can't have an unnamed field with a qualifier!");
+
+      Expr *BaseExpr = Base.takeAs<Expr>();
+      if (getSema().PerformObjectMemberConversion(BaseExpr, Member))
+        return getSema().ExprError();
+
+      MemberExpr *ME =
+        new (getSema().Context) MemberExpr(BaseExpr, isArrow,
+                                           Member, MemberLoc,
+                                           cast<FieldDecl>(Member)->getType());
+      return getSema().Owned(ME);
+    }
+
+    CXXScopeSpec SS;
+    if (Qualifier) {
+      SS.setRange(QualifierRange);
+      SS.setScopeRep(Qualifier);
+    }
+
+    QualType BaseType = ((Expr*) Base.get())->getType();
+
+    LookupResult R(getSema(), Member->getDeclName(), MemberLoc,
+                   Sema::LookupMemberName);
+    R.addDecl(Member);
+    R.resolveKind();
+
+    return getSema().BuildMemberReferenceExpr(move(Base), BaseType,
+                                              OpLoc, isArrow,
+                                              SS, FirstQualifierInScope,
+                                              R, ExplicitTemplateArgs);
+  }
+
+  /// \brief Build a new binary operator expression.
+  ///
+  /// By default, performs semantic analysis to build the new expression.
+  /// Subclasses may override this routine to provide different behavior.
+  OwningExprResult RebuildBinaryOperator(SourceLocation OpLoc,
+                                         BinaryOperator::Opcode Opc,
+                                         ExprArg LHS, ExprArg RHS) {
+    return getSema().BuildBinOp(/*Scope=*/0, OpLoc, Opc, 
+                                LHS.takeAs<Expr>(), RHS.takeAs<Expr>());
+  }
+
+  /// \brief Build a new conditional operator expression.
+  ///
+  /// By default, performs semantic analysis to build the new expression.
+  /// Subclasses may override this routine to provide different behavior.
+  OwningExprResult RebuildConditionalOperator(ExprArg Cond,
+                                              SourceLocation QuestionLoc,
+                                              ExprArg LHS,
+                                              SourceLocation ColonLoc,
+                                              ExprArg RHS) {
+    return getSema().ActOnConditionalOp(QuestionLoc, ColonLoc, move(Cond),
+                                        move(LHS), move(RHS));
+  }
+
+  /// \brief Build a new C-style cast expression.
+  ///
+  /// By default, performs semantic analysis to build the new expression.
+  /// Subclasses may override this routine to provide different behavior.
+  OwningExprResult RebuildCStyleCastExpr(SourceLocation LParenLoc,
+                                         TypeSourceInfo *TInfo,
+                                         SourceLocation RParenLoc,
+                                         ExprArg SubExpr) {
+    return getSema().BuildCStyleCastExpr(LParenLoc, TInfo, RParenLoc,
+                                         move(SubExpr));
+  }
+
+  /// \brief Build a new compound literal expression.
+  ///
+  /// By default, performs semantic analysis to build the new expression.
+  /// Subclasses may override this routine to provide different behavior.
+  OwningExprResult RebuildCompoundLiteralExpr(SourceLocation LParenLoc,
+                                              TypeSourceInfo *TInfo,
+                                              SourceLocation RParenLoc,
+                                              ExprArg Init) {
+    return getSema().BuildCompoundLiteralExpr(LParenLoc, TInfo, RParenLoc,
+                                              move(Init));
+  }
+
+  /// \brief Build a new extended vector element access expression.
+  ///
+  /// By default, performs semantic analysis to build the new expression.
+  /// Subclasses may override this routine to provide different behavior.
+  OwningExprResult RebuildExtVectorElementExpr(ExprArg Base,
+                                               SourceLocation OpLoc,
+                                               SourceLocation AccessorLoc,
+                                               IdentifierInfo &Accessor) {
+
+    CXXScopeSpec SS;
+    QualType BaseType = ((Expr*) Base.get())->getType();
+    return getSema().BuildMemberReferenceExpr(move(Base), BaseType,
+                                              OpLoc, /*IsArrow*/ false,
+                                              SS, /*FirstQualifierInScope*/ 0,
+                                              DeclarationName(&Accessor),
+                                              AccessorLoc,
+                                              /* TemplateArgs */ 0);
+  }
+
+  /// \brief Build a new initializer list expression.
+  ///
+  /// By default, performs semantic analysis to build the new expression.
+  /// Subclasses may override this routine to provide different behavior.
+  OwningExprResult RebuildInitList(SourceLocation LBraceLoc,
+                                   MultiExprArg Inits,
+                                   SourceLocation RBraceLoc,
+                                   QualType ResultTy) {
+    OwningExprResult Result
+      = SemaRef.ActOnInitList(LBraceLoc, move(Inits), RBraceLoc);
+    if (Result.isInvalid() || ResultTy->isDependentType())
+      return move(Result);
+    
+    // Patch in the result type we were given, which may have been computed
+    // when the initial InitListExpr was built.
+    InitListExpr *ILE = cast<InitListExpr>((Expr *)Result.get());
+    ILE->setType(ResultTy);
+    return move(Result);
+  }
+
+  /// \brief Build a new designated initializer expression.
+  ///
+  /// By default, performs semantic analysis to build the new expression.
+  /// Subclasses may override this routine to provide different behavior.
+  OwningExprResult RebuildDesignatedInitExpr(Designation &Desig,
+                                             MultiExprArg ArrayExprs,
+                                             SourceLocation EqualOrColonLoc,
+                                             bool GNUSyntax,
+                                             ExprArg Init) {
+    OwningExprResult Result
+      = SemaRef.ActOnDesignatedInitializer(Desig, EqualOrColonLoc, GNUSyntax,
+                                           move(Init));
+    if (Result.isInvalid())
+      return SemaRef.ExprError();
+
+    ArrayExprs.release();
+    return move(Result);
+  }
+
+  /// \brief Build a new value-initialized expression.
+  ///
+  /// By default, builds the implicit value initialization without performing
+  /// any semantic analysis. Subclasses may override this routine to provide
+  /// different behavior.
+  OwningExprResult RebuildImplicitValueInitExpr(QualType T) {
+    return SemaRef.Owned(new (SemaRef.Context) ImplicitValueInitExpr(T));
+  }
+
+  /// \brief Build a new \c va_arg expression.
+  ///
+  /// By default, performs semantic analysis to build the new expression.
+  /// Subclasses may override this routine to provide different behavior.
+  OwningExprResult RebuildVAArgExpr(SourceLocation BuiltinLoc, ExprArg SubExpr,
+                                    QualType T, SourceLocation RParenLoc) {
+    return getSema().ActOnVAArg(BuiltinLoc, move(SubExpr), T.getAsOpaquePtr(),
+                                RParenLoc);
+  }
+
+  /// \brief Build a new expression list in parentheses.
+  ///
+  /// By default, performs semantic analysis to build the new expression.
+  /// Subclasses may override this routine to provide different behavior.
+  OwningExprResult RebuildParenListExpr(SourceLocation LParenLoc,
+                                        MultiExprArg SubExprs,
+                                        SourceLocation RParenLoc) {
+    return getSema().ActOnParenOrParenListExpr(LParenLoc, RParenLoc, 
+                                               move(SubExprs));
+  }
+
+  /// \brief Build a new address-of-label expression.
+  ///
+  /// By default, performs semantic analysis, using the name of the label
+  /// rather than attempting to map the label statement itself.
+  /// Subclasses may override this routine to provide different behavior.
+  OwningExprResult RebuildAddrLabelExpr(SourceLocation AmpAmpLoc,
+                                        SourceLocation LabelLoc,
+                                        LabelStmt *Label) {
+    return getSema().ActOnAddrLabel(AmpAmpLoc, LabelLoc, Label->getID());
+  }
+
+  /// \brief Build a new GNU statement expression.
+  ///
+  /// By default, performs semantic analysis to build the new expression.
+  /// Subclasses may override this routine to provide different behavior.
+  OwningExprResult RebuildStmtExpr(SourceLocation LParenLoc,
+                                   StmtArg SubStmt,
+                                   SourceLocation RParenLoc) {
+    return getSema().ActOnStmtExpr(LParenLoc, move(SubStmt), RParenLoc);
+  }
+
+  /// \brief Build a new __builtin_types_compatible_p expression.
+  ///
+  /// By default, performs semantic analysis to build the new expression.
+  /// Subclasses may override this routine to provide different behavior.
+  OwningExprResult RebuildTypesCompatibleExpr(SourceLocation BuiltinLoc,
+                                              QualType T1, QualType T2,
+                                              SourceLocation RParenLoc) {
+    return getSema().ActOnTypesCompatibleExpr(BuiltinLoc,
+                                              T1.getAsOpaquePtr(),
+                                              T2.getAsOpaquePtr(),
+                                              RParenLoc);
+  }
+
+  /// \brief Build a new __builtin_choose_expr expression.
+  ///
+  /// By default, performs semantic analysis to build the new expression.
+  /// Subclasses may override this routine to provide different behavior.
+  OwningExprResult RebuildChooseExpr(SourceLocation BuiltinLoc,
+                                     ExprArg Cond, ExprArg LHS, ExprArg RHS,
+                                     SourceLocation RParenLoc) {
+    return SemaRef.ActOnChooseExpr(BuiltinLoc,
+                                   move(Cond), move(LHS), move(RHS),
+                                   RParenLoc);
+  }
+
+  /// \brief Build a new overloaded operator call expression.
+  ///
+  /// By default, performs semantic analysis to build the new expression.
+  /// The semantic analysis provides the behavior of template instantiation,
+  /// copying with transformations that turn what looks like an overloaded
+  /// operator call into a use of a builtin operator, performing
+  /// argument-dependent lookup, etc. Subclasses may override this routine to
+  /// provide different behavior.
+  OwningExprResult RebuildCXXOperatorCallExpr(OverloadedOperatorKind Op,
+                                              SourceLocation OpLoc,
+                                              ExprArg Callee,
+                                              ExprArg First,
+                                              ExprArg Second);
+
+  /// \brief Build a new C++ "named" cast expression, such as static_cast or
+  /// reinterpret_cast.
+  ///
+  /// By default, this routine dispatches to one of the more-specific routines
+  /// for a particular named case, e.g., RebuildCXXStaticCastExpr().
+  /// Subclasses may override this routine to provide different behavior.
+  OwningExprResult RebuildCXXNamedCastExpr(SourceLocation OpLoc,
+                                           Stmt::StmtClass Class,
+                                           SourceLocation LAngleLoc,
+                                           TypeSourceInfo *TInfo,
+                                           SourceLocation RAngleLoc,
+                                           SourceLocation LParenLoc,
+                                           ExprArg SubExpr,
+                                           SourceLocation RParenLoc) {
+    switch (Class) {
+    case Stmt::CXXStaticCastExprClass:
+      return getDerived().RebuildCXXStaticCastExpr(OpLoc, LAngleLoc, TInfo,
+                                                   RAngleLoc, LParenLoc,
+                                                   move(SubExpr), RParenLoc);
+
+    case Stmt::CXXDynamicCastExprClass:
+      return getDerived().RebuildCXXDynamicCastExpr(OpLoc, LAngleLoc, TInfo,
+                                                    RAngleLoc, LParenLoc,
+                                                    move(SubExpr), RParenLoc);
+
+    case Stmt::CXXReinterpretCastExprClass:
+      return getDerived().RebuildCXXReinterpretCastExpr(OpLoc, LAngleLoc, TInfo,
+                                                        RAngleLoc, LParenLoc,
+                                                        move(SubExpr),
+                                                        RParenLoc);
+
+    case Stmt::CXXConstCastExprClass:
+      return getDerived().RebuildCXXConstCastExpr(OpLoc, LAngleLoc, TInfo,
+                                                   RAngleLoc, LParenLoc,
+                                                   move(SubExpr), RParenLoc);
+
+    default:
+      assert(false && "Invalid C++ named cast");
+      break;
+    }
+
+    return getSema().ExprError();
+  }
+
+  /// \brief Build a new C++ static_cast expression.
+  ///
+  /// By default, performs semantic analysis to build the new expression.
+  /// Subclasses may override this routine to provide different behavior.
+  OwningExprResult RebuildCXXStaticCastExpr(SourceLocation OpLoc,
+                                            SourceLocation LAngleLoc,
+                                            TypeSourceInfo *TInfo,
+                                            SourceLocation RAngleLoc,
+                                            SourceLocation LParenLoc,
+                                            ExprArg SubExpr,
+                                            SourceLocation RParenLoc) {
+    return getSema().BuildCXXNamedCast(OpLoc, tok::kw_static_cast,
+                                       TInfo, move(SubExpr),
+                                       SourceRange(LAngleLoc, RAngleLoc),
+                                       SourceRange(LParenLoc, RParenLoc));
+  }
+
+  /// \brief Build a new C++ dynamic_cast expression.
+  ///
+  /// By default, performs semantic analysis to build the new expression.
+  /// Subclasses may override this routine to provide different behavior.
+  OwningExprResult RebuildCXXDynamicCastExpr(SourceLocation OpLoc,
+                                             SourceLocation LAngleLoc,
+                                             TypeSourceInfo *TInfo,
+                                             SourceLocation RAngleLoc,
+                                             SourceLocation LParenLoc,
+                                             ExprArg SubExpr,
+                                             SourceLocation RParenLoc) {
+    return getSema().BuildCXXNamedCast(OpLoc, tok::kw_dynamic_cast,
+                                       TInfo, move(SubExpr),
+                                       SourceRange(LAngleLoc, RAngleLoc),
+                                       SourceRange(LParenLoc, RParenLoc));
+  }
+
+  /// \brief Build a new C++ reinterpret_cast expression.
+  ///
+  /// By default, performs semantic analysis to build the new expression.
+  /// Subclasses may override this routine to provide different behavior.
+  OwningExprResult RebuildCXXReinterpretCastExpr(SourceLocation OpLoc,
+                                                 SourceLocation LAngleLoc,
+                                                 TypeSourceInfo *TInfo,
+                                                 SourceLocation RAngleLoc,
+                                                 SourceLocation LParenLoc,
+                                                 ExprArg SubExpr,
+                                                 SourceLocation RParenLoc) {
+    return getSema().BuildCXXNamedCast(OpLoc, tok::kw_reinterpret_cast,
+                                       TInfo, move(SubExpr),
+                                       SourceRange(LAngleLoc, RAngleLoc),
+                                       SourceRange(LParenLoc, RParenLoc));
+  }
+
+  /// \brief Build a new C++ const_cast expression.
+  ///
+  /// By default, performs semantic analysis to build the new expression.
+  /// Subclasses may override this routine to provide different behavior.
+  OwningExprResult RebuildCXXConstCastExpr(SourceLocation OpLoc,
+                                           SourceLocation LAngleLoc,
+                                           TypeSourceInfo *TInfo,
+                                           SourceLocation RAngleLoc,
+                                           SourceLocation LParenLoc,
+                                           ExprArg SubExpr,
+                                           SourceLocation RParenLoc) {
+    return getSema().BuildCXXNamedCast(OpLoc, tok::kw_const_cast,
+                                       TInfo, move(SubExpr),
+                                       SourceRange(LAngleLoc, RAngleLoc),
+                                       SourceRange(LParenLoc, RParenLoc));
+  }
+
+  /// \brief Build a new C++ functional-style cast expression.
+  ///
+  /// By default, performs semantic analysis to build the new expression.
+  /// Subclasses may override this routine to provide different behavior.
+  OwningExprResult RebuildCXXFunctionalCastExpr(SourceRange TypeRange,
+                                                TypeSourceInfo *TInfo,
+                                                SourceLocation LParenLoc,
+                                                ExprArg SubExpr,
+                                                SourceLocation RParenLoc) {
+    void *Sub = SubExpr.takeAs<Expr>();
+    return getSema().ActOnCXXTypeConstructExpr(TypeRange,
+                                               TInfo->getType().getAsOpaquePtr(),
+                                               LParenLoc,
+                                         Sema::MultiExprArg(getSema(), &Sub, 1),
+                                               /*CommaLocs=*/0,
+                                               RParenLoc);
+  }
+
+  /// \brief Build a new C++ typeid(type) expression.
+  ///
+  /// By default, performs semantic analysis to build the new expression.
+  /// Subclasses may override this routine to provide different behavior.
+  OwningExprResult RebuildCXXTypeidExpr(SourceLocation TypeidLoc,
+                                        SourceLocation LParenLoc,
+                                        QualType T,
+                                        SourceLocation RParenLoc) {
+    return getSema().ActOnCXXTypeid(TypeidLoc, LParenLoc, true,
+                                    T.getAsOpaquePtr(), RParenLoc);
+  }
+
+  /// \brief Build a new C++ typeid(expr) expression.
+  ///
+  /// By default, performs semantic analysis to build the new expression.
+  /// Subclasses may override this routine to provide different behavior.
+  OwningExprResult RebuildCXXTypeidExpr(SourceLocation TypeidLoc,
+                                        SourceLocation LParenLoc,
+                                        ExprArg Operand,
+                                        SourceLocation RParenLoc) {
+    OwningExprResult Result
+      = getSema().ActOnCXXTypeid(TypeidLoc, LParenLoc, false, Operand.get(),
+                                 RParenLoc);
+    if (Result.isInvalid())
+      return getSema().ExprError();
+
+    Operand.release(); // FIXME: since ActOnCXXTypeid silently took ownership
+    return move(Result);
+  }
+
+  /// \brief Build a new C++ "this" expression.
+  ///
+  /// By default, builds a new "this" expression without performing any
+  /// semantic analysis. Subclasses may override this routine to provide
+  /// different behavior.
+  OwningExprResult RebuildCXXThisExpr(SourceLocation ThisLoc,
+                                      QualType ThisType,
+                                      bool isImplicit) {
+    return getSema().Owned(
+                      new (getSema().Context) CXXThisExpr(ThisLoc, ThisType,
+                                                          isImplicit));
+  }
+
+  /// \brief Build a new C++ throw expression.
+  ///
+  /// By default, performs semantic analysis to build the new expression.
+  /// Subclasses may override this routine to provide different behavior.
+  OwningExprResult RebuildCXXThrowExpr(SourceLocation ThrowLoc, ExprArg Sub) {
+    return getSema().ActOnCXXThrow(ThrowLoc, move(Sub));
+  }
+
+  /// \brief Build a new C++ default-argument expression.
+  ///
+  /// By default, builds a new default-argument expression, which does not
+  /// require any semantic analysis. Subclasses may override this routine to
+  /// provide different behavior.
+  OwningExprResult RebuildCXXDefaultArgExpr(SourceLocation Loc, 
+                                            ParmVarDecl *Param) {
+    return getSema().Owned(CXXDefaultArgExpr::Create(getSema().Context, Loc,
+                                                     Param));
+  }
+
+  /// \brief Build a new C++ zero-initialization expression.
+  ///
+  /// By default, performs semantic analysis to build the new expression.
+  /// Subclasses may override this routine to provide different behavior.
+  OwningExprResult RebuildCXXZeroInitValueExpr(SourceLocation TypeStartLoc,
+                                               SourceLocation LParenLoc,
+                                               QualType T,
+                                               SourceLocation RParenLoc) {
+    return getSema().ActOnCXXTypeConstructExpr(SourceRange(TypeStartLoc),
+                                               T.getAsOpaquePtr(), LParenLoc,
+                                               MultiExprArg(getSema(), 0, 0),
+                                               0, RParenLoc);
+  }
+
+  /// \brief Build a new C++ "new" expression.
+  ///
+  /// By default, performs semantic analysis to build the new expression.
+  /// Subclasses may override this routine to provide different behavior.
+  OwningExprResult RebuildCXXNewExpr(SourceLocation StartLoc,
+                                     bool UseGlobal,
+                                     SourceLocation PlacementLParen,
+                                     MultiExprArg PlacementArgs,
+                                     SourceLocation PlacementRParen,
+                                     bool ParenTypeId,
+                                     QualType AllocType,
+                                     SourceLocation TypeLoc,
+                                     SourceRange TypeRange,
+                                     ExprArg ArraySize,
+                                     SourceLocation ConstructorLParen,
+                                     MultiExprArg ConstructorArgs,
+                                     SourceLocation ConstructorRParen) {
+    return getSema().BuildCXXNew(StartLoc, UseGlobal,
+                                 PlacementLParen,
+                                 move(PlacementArgs),
+                                 PlacementRParen,
+                                 ParenTypeId,
+                                 AllocType,
+                                 TypeLoc,
+                                 TypeRange,
+                                 move(ArraySize),
+                                 ConstructorLParen,
+                                 move(ConstructorArgs),
+                                 ConstructorRParen);
+  }
+
+  /// \brief Build a new C++ "delete" expression.
+  ///
+  /// By default, performs semantic analysis to build the new expression.
+  /// Subclasses may override this routine to provide different behavior.
+  OwningExprResult RebuildCXXDeleteExpr(SourceLocation StartLoc,
+                                        bool IsGlobalDelete,
+                                        bool IsArrayForm,
+                                        ExprArg Operand) {
+    return getSema().ActOnCXXDelete(StartLoc, IsGlobalDelete, IsArrayForm,
+                                    move(Operand));
+  }
+
+  /// \brief Build a new unary type trait expression.
+  ///
+  /// By default, performs semantic analysis to build the new expression.
+  /// Subclasses may override this routine to provide different behavior.
+  OwningExprResult RebuildUnaryTypeTrait(UnaryTypeTrait Trait,
+                                         SourceLocation StartLoc,
+                                         SourceLocation LParenLoc,
+                                         QualType T,
+                                         SourceLocation RParenLoc) {
+    return getSema().ActOnUnaryTypeTrait(Trait, StartLoc, LParenLoc,
+                                         T.getAsOpaquePtr(), RParenLoc);
+  }
+
+  /// \brief Build a new (previously unresolved) declaration reference
+  /// expression.
+  ///
+  /// By default, performs semantic analysis to build the new expression.
+  /// Subclasses may override this routine to provide different behavior.
+  OwningExprResult RebuildDependentScopeDeclRefExpr(NestedNameSpecifier *NNS,
+                                                SourceRange QualifierRange,
+                                                DeclarationName Name,
+                                                SourceLocation Location,
+                              const TemplateArgumentListInfo *TemplateArgs) {
+    CXXScopeSpec SS;
+    SS.setRange(QualifierRange);
+    SS.setScopeRep(NNS);
+
+    if (TemplateArgs)
+      return getSema().BuildQualifiedTemplateIdExpr(SS, Name, Location,
+                                                    *TemplateArgs);
+
+    return getSema().BuildQualifiedDeclarationNameExpr(SS, Name, Location);
+  }
+
+  /// \brief Build a new template-id expression.
+  ///
+  /// By default, performs semantic analysis to build the new expression.
+  /// Subclasses may override this routine to provide different behavior.
+  OwningExprResult RebuildTemplateIdExpr(const CXXScopeSpec &SS,
+                                         LookupResult &R,
+                                         bool RequiresADL,
+                              const TemplateArgumentListInfo &TemplateArgs) {
+    return getSema().BuildTemplateIdExpr(SS, R, RequiresADL, TemplateArgs);
+  }
+
+  /// \brief Build a new object-construction expression.
+  ///
+  /// By default, performs semantic analysis to build the new expression.
+  /// Subclasses may override this routine to provide different behavior.
+  OwningExprResult RebuildCXXConstructExpr(QualType T,
+                                           SourceLocation Loc,
+                                           CXXConstructorDecl *Constructor,
+                                           bool IsElidable,
+                                           MultiExprArg Args) {
+    ASTOwningVector<&ActionBase::DeleteExpr> ConvertedArgs(SemaRef);
+    if (getSema().CompleteConstructorCall(Constructor, move(Args), Loc, 
+                                          ConvertedArgs))
+      return getSema().ExprError();
+    
+    return getSema().BuildCXXConstructExpr(Loc, T, Constructor, IsElidable,
+                                           move_arg(ConvertedArgs));
+  }
+
+  /// \brief Build a new object-construction expression.
+  ///
+  /// By default, performs semantic analysis to build the new expression.
+  /// Subclasses may override this routine to provide different behavior.
+  OwningExprResult RebuildCXXTemporaryObjectExpr(SourceLocation TypeBeginLoc,
+                                                 QualType T,
+                                                 SourceLocation LParenLoc,
+                                                 MultiExprArg Args,
+                                                 SourceLocation *Commas,
+                                                 SourceLocation RParenLoc) {
+    return getSema().ActOnCXXTypeConstructExpr(SourceRange(TypeBeginLoc),
+                                               T.getAsOpaquePtr(),
+                                               LParenLoc,
+                                               move(Args),
+                                               Commas,
+                                               RParenLoc);
+  }
+
+  /// \brief Build a new object-construction expression.
+  ///
+  /// By default, performs semantic analysis to build the new expression.
+  /// Subclasses may override this routine to provide different behavior.
+  OwningExprResult RebuildCXXUnresolvedConstructExpr(SourceLocation TypeBeginLoc,
+                                                     QualType T,
+                                                     SourceLocation LParenLoc,
+                                                     MultiExprArg Args,
+                                                     SourceLocation *Commas,
+                                                     SourceLocation RParenLoc) {
+    return getSema().ActOnCXXTypeConstructExpr(SourceRange(TypeBeginLoc,
+                                                           /*FIXME*/LParenLoc),
+                                               T.getAsOpaquePtr(),
+                                               LParenLoc,
+                                               move(Args),
+                                               Commas,
+                                               RParenLoc);
+  }
+
+  /// \brief Build a new member reference expression.
+  ///
+  /// By default, performs semantic analysis to build the new expression.
+  /// Subclasses may override this routine to provide different behavior.
+  OwningExprResult RebuildCXXDependentScopeMemberExpr(ExprArg BaseE,
+                                                  QualType BaseType,
+                                                  bool IsArrow,
+                                                  SourceLocation OperatorLoc,
+                                              NestedNameSpecifier *Qualifier,
+                                                  SourceRange QualifierRange,
+                                            NamedDecl *FirstQualifierInScope,
+                                                  DeclarationName Name,
+                                                  SourceLocation MemberLoc,
+                              const TemplateArgumentListInfo *TemplateArgs) {
+    CXXScopeSpec SS;
+    SS.setRange(QualifierRange);
+    SS.setScopeRep(Qualifier);
+
+    return SemaRef.BuildMemberReferenceExpr(move(BaseE), BaseType,
+                                            OperatorLoc, IsArrow,
+                                            SS, FirstQualifierInScope,
+                                            Name, MemberLoc, TemplateArgs);
+  }
+
+  /// \brief Build a new member reference expression.
+  ///
+  /// By default, performs semantic analysis to build the new expression.
+  /// Subclasses may override this routine to provide different behavior.
+  OwningExprResult RebuildUnresolvedMemberExpr(ExprArg BaseE,
+                                               QualType BaseType,
+                                               SourceLocation OperatorLoc,
+                                               bool IsArrow,
+                                               NestedNameSpecifier *Qualifier,
+                                               SourceRange QualifierRange,
+                                               NamedDecl *FirstQualifierInScope,
+                                               LookupResult &R,
+                                const TemplateArgumentListInfo *TemplateArgs) {
+    CXXScopeSpec SS;
+    SS.setRange(QualifierRange);
+    SS.setScopeRep(Qualifier);
+
+    return SemaRef.BuildMemberReferenceExpr(move(BaseE), BaseType,
+                                            OperatorLoc, IsArrow,
+                                            SS, FirstQualifierInScope,
+                                            R, TemplateArgs);
+  }
+
+  /// \brief Build a new Objective-C @encode expression.
+  ///
+  /// By default, performs semantic analysis to build the new expression.
+  /// Subclasses may override this routine to provide different behavior.
+  OwningExprResult RebuildObjCEncodeExpr(SourceLocation AtLoc,
+                                         QualType T,
+                                         SourceLocation RParenLoc) {
+    return SemaRef.Owned(SemaRef.BuildObjCEncodeExpression(AtLoc, T,
+                                                           RParenLoc));
+  }
+
+  /// \brief Build a new Objective-C protocol expression.
+  ///
+  /// By default, performs semantic analysis to build the new expression.
+  /// Subclasses may override this routine to provide different behavior.
+  OwningExprResult RebuildObjCProtocolExpr(ObjCProtocolDecl *Protocol,
+                                           SourceLocation AtLoc,
+                                           SourceLocation ProtoLoc,
+                                           SourceLocation LParenLoc,
+                                           SourceLocation RParenLoc) {
+    return SemaRef.Owned(SemaRef.ParseObjCProtocolExpression(
+                                              Protocol->getIdentifier(),
+                                                             AtLoc,
+                                                             ProtoLoc,
+                                                             LParenLoc,
+                                                             RParenLoc));
+  }
+
+  /// \brief Build a new shuffle vector expression.
+  ///
+  /// By default, performs semantic analysis to build the new expression.
+  /// Subclasses may override this routine to provide different behavior.
+  OwningExprResult RebuildShuffleVectorExpr(SourceLocation BuiltinLoc,
+                                            MultiExprArg SubExprs,
+                                            SourceLocation RParenLoc) {
+    // Find the declaration for __builtin_shufflevector
+    const IdentifierInfo &Name
+      = SemaRef.Context.Idents.get("__builtin_shufflevector");
+    TranslationUnitDecl *TUDecl = SemaRef.Context.getTranslationUnitDecl();
+    DeclContext::lookup_result Lookup = TUDecl->lookup(DeclarationName(&Name));
+    assert(Lookup.first != Lookup.second && "No __builtin_shufflevector?");
+
+    // Build a reference to the __builtin_shufflevector builtin
+    FunctionDecl *Builtin = cast<FunctionDecl>(*Lookup.first);
+    Expr *Callee
+      = new (SemaRef.Context) DeclRefExpr(Builtin, Builtin->getType(),
+                                          BuiltinLoc);
+    SemaRef.UsualUnaryConversions(Callee);
+
+    // Build the CallExpr
+    unsigned NumSubExprs = SubExprs.size();
+    Expr **Subs = (Expr **)SubExprs.release();
+    CallExpr *TheCall = new (SemaRef.Context) CallExpr(SemaRef.Context, Callee,
+                                                       Subs, NumSubExprs,
+                                                       Builtin->getResultType(),
+                                                       RParenLoc);
+    OwningExprResult OwnedCall(SemaRef.Owned(TheCall));
+
+    // Type-check the __builtin_shufflevector expression.
+    OwningExprResult Result = SemaRef.SemaBuiltinShuffleVector(TheCall);
+    if (Result.isInvalid())
+      return SemaRef.ExprError();
+
+    OwnedCall.release();
+    return move(Result);
+  }
+};
+
+template<typename Derived>
+Sema::OwningStmtResult TreeTransform<Derived>::TransformStmt(Stmt *S) {
+  if (!S)
+    return SemaRef.Owned(S);
+
+  switch (S->getStmtClass()) {
+  case Stmt::NoStmtClass: break;
+
+  // Transform individual statement nodes
+#define STMT(Node, Parent)                                              \
+  case Stmt::Node##Class: return getDerived().Transform##Node(cast<Node>(S));
+#define EXPR(Node, Parent)
+#include "clang/AST/StmtNodes.def"
+
+  // Transform expressions by calling TransformExpr.
+#define STMT(Node, Parent)
+#define ABSTRACT_EXPR(Node, Parent)
+#define EXPR(Node, Parent) case Stmt::Node##Class:
+#include "clang/AST/StmtNodes.def"
+    {
+      Sema::OwningExprResult E = getDerived().TransformExpr(cast<Expr>(S));
+      if (E.isInvalid())
+        return getSema().StmtError();
+
+      return getSema().ActOnExprStmt(getSema().MakeFullExpr(E));
+    }
+  }
+
+  return SemaRef.Owned(S->Retain());
+}
+
+
+template<typename Derived>
+Sema::OwningExprResult TreeTransform<Derived>::TransformExpr(Expr *E) {
+  if (!E)
+    return SemaRef.Owned(E);
+
+  switch (E->getStmtClass()) {
+    case Stmt::NoStmtClass: break;
+#define STMT(Node, Parent) case Stmt::Node##Class: break;
+#define ABSTRACT_EXPR(Node, Parent)
+#define EXPR(Node, Parent)                                              \
+    case Stmt::Node##Class: return getDerived().Transform##Node(cast<Node>(E));
+#include "clang/AST/StmtNodes.def"
+  }
+
+  return SemaRef.Owned(E->Retain());
+}
+
+template<typename Derived>
+NestedNameSpecifier *
+TreeTransform<Derived>::TransformNestedNameSpecifier(NestedNameSpecifier *NNS,
+                                                     SourceRange Range,
+                                                     QualType ObjectType,
+                                             NamedDecl *FirstQualifierInScope) {
+  if (!NNS)
+    return 0;
+
+  // Transform the prefix of this nested name specifier.
+  NestedNameSpecifier *Prefix = NNS->getPrefix();
+  if (Prefix) {
+    Prefix = getDerived().TransformNestedNameSpecifier(Prefix, Range,
+                                                       ObjectType,
+                                                       FirstQualifierInScope);
+    if (!Prefix)
+      return 0;
+
+    // Clear out the object type and the first qualifier in scope; they only
+    // apply to the first element in the nested-name-specifier.
+    ObjectType = QualType();
+    FirstQualifierInScope = 0;
+  }
+
+  switch (NNS->getKind()) {
+  case NestedNameSpecifier::Identifier:
+    assert((Prefix || !ObjectType.isNull()) &&
+            "Identifier nested-name-specifier with no prefix or object type");
+    if (!getDerived().AlwaysRebuild() && Prefix == NNS->getPrefix() &&
+        ObjectType.isNull())
+      return NNS;
+
+    return getDerived().RebuildNestedNameSpecifier(Prefix, Range,
+                                                   *NNS->getAsIdentifier(),
+                                                   ObjectType,
+                                                   FirstQualifierInScope);
+
+  case NestedNameSpecifier::Namespace: {
+    NamespaceDecl *NS
+      = cast_or_null<NamespaceDecl>(
+                            getDerived().TransformDecl(NNS->getAsNamespace()));
+    if (!getDerived().AlwaysRebuild() &&
+        Prefix == NNS->getPrefix() &&
+        NS == NNS->getAsNamespace())
+      return NNS;
+
+    return getDerived().RebuildNestedNameSpecifier(Prefix, Range, NS);
+  }
+
+  case NestedNameSpecifier::Global:
+    // There is no meaningful transformation that one could perform on the
+    // global scope.
+    return NNS;
+
+  case NestedNameSpecifier::TypeSpecWithTemplate:
+  case NestedNameSpecifier::TypeSpec: {
+    TemporaryBase Rebase(*this, Range.getBegin(), DeclarationName());
+    QualType T = getDerived().TransformType(QualType(NNS->getAsType(), 0));
+    if (T.isNull())
+      return 0;
+
+    if (!getDerived().AlwaysRebuild() &&
+        Prefix == NNS->getPrefix() &&
+        T == QualType(NNS->getAsType(), 0))
+      return NNS;
+
+    return getDerived().RebuildNestedNameSpecifier(Prefix, Range,
+                  NNS->getKind() == NestedNameSpecifier::TypeSpecWithTemplate,
+                                                   T);
+  }
+  }
+
+  // Required to silence a GCC warning
+  return 0;
+}
+
+template<typename Derived>
+DeclarationName
+TreeTransform<Derived>::TransformDeclarationName(DeclarationName Name,
+                                                 SourceLocation Loc,
+                                                 QualType ObjectType) {
+  if (!Name)
+    return Name;
+
+  switch (Name.getNameKind()) {
+  case DeclarationName::Identifier:
+  case DeclarationName::ObjCZeroArgSelector:
+  case DeclarationName::ObjCOneArgSelector:
+  case DeclarationName::ObjCMultiArgSelector:
+  case DeclarationName::CXXOperatorName:
+  case DeclarationName::CXXLiteralOperatorName:
+  case DeclarationName::CXXUsingDirective:
+    return Name;
+
+  case DeclarationName::CXXConstructorName:
+  case DeclarationName::CXXDestructorName:
+  case DeclarationName::CXXConversionFunctionName: {
+    TemporaryBase Rebase(*this, Loc, Name);
+    QualType T;
+    if (!ObjectType.isNull() && 
+        isa<TemplateSpecializationType>(Name.getCXXNameType())) {
+      TemplateSpecializationType *SpecType
+        = cast<TemplateSpecializationType>(Name.getCXXNameType());
+      T = TransformTemplateSpecializationType(SpecType, ObjectType);
+    } else
+      T = getDerived().TransformType(Name.getCXXNameType());
+    if (T.isNull())
+      return DeclarationName();
+
+    return SemaRef.Context.DeclarationNames.getCXXSpecialName(
+                                                           Name.getNameKind(),
+                                          SemaRef.Context.getCanonicalType(T));
+  }
+  }
+
+  return DeclarationName();
+}
+
+template<typename Derived>
+TemplateName
+TreeTransform<Derived>::TransformTemplateName(TemplateName Name,
+                                              QualType ObjectType) {
+  if (QualifiedTemplateName *QTN = Name.getAsQualifiedTemplateName()) {
+    NestedNameSpecifier *NNS
+      = getDerived().TransformNestedNameSpecifier(QTN->getQualifier(),
+                      /*FIXME:*/SourceRange(getDerived().getBaseLocation()));
+    if (!NNS)
+      return TemplateName();
+
+    if (TemplateDecl *Template = QTN->getTemplateDecl()) {
+      TemplateDecl *TransTemplate
+        = cast_or_null<TemplateDecl>(getDerived().TransformDecl(Template));
+      if (!TransTemplate)
+        return TemplateName();
+
+      if (!getDerived().AlwaysRebuild() &&
+          NNS == QTN->getQualifier() &&
+          TransTemplate == Template)
+        return Name;
+
+      return getDerived().RebuildTemplateName(NNS, QTN->hasTemplateKeyword(),
+                                              TransTemplate);
+    }
+
+    // These should be getting filtered out before they make it into the AST.
+    assert(false && "overloaded template name survived to here");
+  }
+
+  if (DependentTemplateName *DTN = Name.getAsDependentTemplateName()) {
+    NestedNameSpecifier *NNS
+      = getDerived().TransformNestedNameSpecifier(DTN->getQualifier(),
+                        /*FIXME:*/SourceRange(getDerived().getBaseLocation()));
+    if (!NNS && DTN->getQualifier())
+      return TemplateName();
+
+    if (!getDerived().AlwaysRebuild() &&
+        NNS == DTN->getQualifier() &&
+        ObjectType.isNull())
+      return Name;
+
+    if (DTN->isIdentifier())
+      return getDerived().RebuildTemplateName(NNS, *DTN->getIdentifier(), 
+                                              ObjectType);
+    
+    return getDerived().RebuildTemplateName(NNS, DTN->getOperator(), 
+                                            ObjectType);
+  }
+
+  if (TemplateDecl *Template = Name.getAsTemplateDecl()) {
+    TemplateDecl *TransTemplate
+      = cast_or_null<TemplateDecl>(getDerived().TransformDecl(Template));
+    if (!TransTemplate)
+      return TemplateName();
+
+    if (!getDerived().AlwaysRebuild() &&
+        TransTemplate == Template)
+      return Name;
+
+    return TemplateName(TransTemplate);
+  }
+
+  // These should be getting filtered out before they reach the AST.
+  assert(false && "overloaded function decl survived to here");
+  return TemplateName();
+}
+
+template<typename Derived>
+void TreeTransform<Derived>::InventTemplateArgumentLoc(
+                                         const TemplateArgument &Arg,
+                                         TemplateArgumentLoc &Output) {
+  SourceLocation Loc = getDerived().getBaseLocation();
+  switch (Arg.getKind()) {
+  case TemplateArgument::Null:
+    llvm_unreachable("null template argument in TreeTransform");
+    break;
+
+  case TemplateArgument::Type:
+    Output = TemplateArgumentLoc(Arg,
+               SemaRef.Context.getTrivialTypeSourceInfo(Arg.getAsType(), Loc));
+                                            
+    break;
+
+  case TemplateArgument::Template:
+    Output = TemplateArgumentLoc(Arg, SourceRange(), Loc);
+    break;
+      
+  case TemplateArgument::Expression:
+    Output = TemplateArgumentLoc(Arg, Arg.getAsExpr());
+    break;
+
+  case TemplateArgument::Declaration:
+  case TemplateArgument::Integral:
+  case TemplateArgument::Pack:
+    Output = TemplateArgumentLoc(Arg, TemplateArgumentLocInfo());
+    break;
+  }
+}
+
+template<typename Derived>
+bool TreeTransform<Derived>::TransformTemplateArgument(
+                                         const TemplateArgumentLoc &Input,
+                                         TemplateArgumentLoc &Output) {
+  const TemplateArgument &Arg = Input.getArgument();
+  switch (Arg.getKind()) {
+  case TemplateArgument::Null:
+  case TemplateArgument::Integral:
+    Output = Input;
+    return false;
+
+  case TemplateArgument::Type: {
+    TypeSourceInfo *DI = Input.getTypeSourceInfo();
+    if (DI == NULL)
+      DI = InventTypeSourceInfo(Input.getArgument().getAsType());
+
+    DI = getDerived().TransformType(DI);
+    if (!DI) return true;
+
+    Output = TemplateArgumentLoc(TemplateArgument(DI->getType()), DI);
+    return false;
+  }
+
+  case TemplateArgument::Declaration: {
+    // FIXME: we should never have to transform one of these.
+    DeclarationName Name;
+    if (NamedDecl *ND = dyn_cast<NamedDecl>(Arg.getAsDecl()))
+      Name = ND->getDeclName();
+    TemporaryBase Rebase(*this, Input.getLocation(), Name);
+    Decl *D = getDerived().TransformDecl(Arg.getAsDecl());
+    if (!D) return true;
+
+    Expr *SourceExpr = Input.getSourceDeclExpression();
+    if (SourceExpr) {
+      EnterExpressionEvaluationContext Unevaluated(getSema(),
+                                                   Action::Unevaluated);
+      Sema::OwningExprResult E = getDerived().TransformExpr(SourceExpr);
+      if (E.isInvalid())
+        SourceExpr = NULL;
+      else {
+        SourceExpr = E.takeAs<Expr>();
+        SourceExpr->Retain();
+      }
+    }
+
+    Output = TemplateArgumentLoc(TemplateArgument(D), SourceExpr);
+    return false;
+  }
+
+  case TemplateArgument::Template: {
+    TemporaryBase Rebase(*this, Input.getLocation(), DeclarationName());    
+    TemplateName Template
+      = getDerived().TransformTemplateName(Arg.getAsTemplate());
+    if (Template.isNull())
+      return true;
+    
+    Output = TemplateArgumentLoc(TemplateArgument(Template),
+                                 Input.getTemplateQualifierRange(),
+                                 Input.getTemplateNameLoc());
+    return false;
+  }
+      
+  case TemplateArgument::Expression: {
+    // Template argument expressions are not potentially evaluated.
+    EnterExpressionEvaluationContext Unevaluated(getSema(),
+                                                 Action::Unevaluated);
+
+    Expr *InputExpr = Input.getSourceExpression();
+    if (!InputExpr) InputExpr = Input.getArgument().getAsExpr();
+
+    Sema::OwningExprResult E
+      = getDerived().TransformExpr(InputExpr);
+    if (E.isInvalid()) return true;
+
+    Expr *ETaken = E.takeAs<Expr>();
+    ETaken->Retain();
+    Output = TemplateArgumentLoc(TemplateArgument(ETaken), ETaken);
+    return false;
+  }
+
+  case TemplateArgument::Pack: {
+    llvm::SmallVector<TemplateArgument, 4> TransformedArgs;
+    TransformedArgs.reserve(Arg.pack_size());
+    for (TemplateArgument::pack_iterator A = Arg.pack_begin(),
+                                      AEnd = Arg.pack_end();
+         A != AEnd; ++A) {
+
+      // FIXME: preserve source information here when we start
+      // caring about parameter packs.
+
+      TemplateArgumentLoc InputArg;
+      TemplateArgumentLoc OutputArg;
+      getDerived().InventTemplateArgumentLoc(*A, InputArg);
+      if (getDerived().TransformTemplateArgument(InputArg, OutputArg))
+        return true;
+
+      TransformedArgs.push_back(OutputArg.getArgument());
+    }
+    TemplateArgument Result;
+    Result.setArgumentPack(TransformedArgs.data(), TransformedArgs.size(),
+                           true);
+    Output = TemplateArgumentLoc(Result, Input.getLocInfo());
+    return false;
+  }
+  }
+
+  // Work around bogus GCC warning
+  return true;
+}
+
+//===----------------------------------------------------------------------===//
+// Type transformation
+//===----------------------------------------------------------------------===//
+
+template<typename Derived>
+QualType TreeTransform<Derived>::TransformType(QualType T) {
+  if (getDerived().AlreadyTransformed(T))
+    return T;
+
+  // Temporary workaround.  All of these transformations should
+  // eventually turn into transformations on TypeLocs.
+  TypeSourceInfo *DI = getSema().Context.CreateTypeSourceInfo(T);
+  DI->getTypeLoc().initialize(getDerived().getBaseLocation());
+  
+  TypeSourceInfo *NewDI = getDerived().TransformType(DI);
+
+  if (!NewDI)
+    return QualType();
+
+  return NewDI->getType();
+}
+
+template<typename Derived>
+TypeSourceInfo *TreeTransform<Derived>::TransformType(TypeSourceInfo *DI) {
+  if (getDerived().AlreadyTransformed(DI->getType()))
+    return DI;
+
+  TypeLocBuilder TLB;
+
+  TypeLoc TL = DI->getTypeLoc();
+  TLB.reserve(TL.getFullDataSize());
+
+  QualType Result = getDerived().TransformType(TLB, TL);
+  if (Result.isNull())
+    return 0;
+
+  return TLB.getTypeSourceInfo(SemaRef.Context, Result);
+}
+
+template<typename Derived>
+QualType
+TreeTransform<Derived>::TransformType(TypeLocBuilder &TLB, TypeLoc T) {
+  switch (T.getTypeLocClass()) {
+#define ABSTRACT_TYPELOC(CLASS, PARENT)
+#define TYPELOC(CLASS, PARENT) \
+  case TypeLoc::CLASS: \
+    return getDerived().Transform##CLASS##Type(TLB, cast<CLASS##TypeLoc>(T));
+#include "clang/AST/TypeLocNodes.def"
+  }
+
+  llvm_unreachable("unhandled type loc!");
+  return QualType();
+}
+
+/// FIXME: By default, this routine adds type qualifiers only to types
+/// that can have qualifiers, and silently suppresses those qualifiers
+/// that are not permitted (e.g., qualifiers on reference or function
+/// types). This is the right thing for template instantiation, but
+/// probably not for other clients.
+template<typename Derived>
+QualType
+TreeTransform<Derived>::TransformQualifiedType(TypeLocBuilder &TLB,
+                                               QualifiedTypeLoc T) {
+  Qualifiers Quals = T.getType().getLocalQualifiers();
+
+  QualType Result = getDerived().TransformType(TLB, T.getUnqualifiedLoc());
+  if (Result.isNull())
+    return QualType();
+
+  // Silently suppress qualifiers if the result type can't be qualified.
+  // FIXME: this is the right thing for template instantiation, but
+  // probably not for other clients.
+  if (Result->isFunctionType() || Result->isReferenceType())
+    return Result;
+
+  Result = SemaRef.Context.getQualifiedType(Result, Quals);
+
+  TLB.push<QualifiedTypeLoc>(Result);
+
+  // No location information to preserve.
+
+  return Result;
+}
+
+template <class TyLoc> static inline
+QualType TransformTypeSpecType(TypeLocBuilder &TLB, TyLoc T) {
+  TyLoc NewT = TLB.push<TyLoc>(T.getType());
+  NewT.setNameLoc(T.getNameLoc());
+  return T.getType();
+}
+
+// Ugly metaprogramming macros because I couldn't be bothered to make
+// the equivalent template version work.
+#define TransformPointerLikeType(TypeClass) do { \
+  QualType PointeeType                                       \
+    = getDerived().TransformType(TLB, TL.getPointeeLoc());   \
+  if (PointeeType.isNull())                                  \
+    return QualType();                                       \
+                                                             \
+  QualType Result = TL.getType();                            \
+  if (getDerived().AlwaysRebuild() ||                        \
+      PointeeType != TL.getPointeeLoc().getType()) {         \
+    Result = getDerived().Rebuild##TypeClass(PointeeType,    \
+                                          TL.getSigilLoc()); \
+    if (Result.isNull())                                     \
+      return QualType();                                     \
+  }                                                          \
+                                                             \
+  TypeClass##Loc NewT = TLB.push<TypeClass##Loc>(Result);    \
+  NewT.setSigilLoc(TL.getSigilLoc());                        \
+                                                             \
+  return Result;                                             \
+} while(0)
+
+template<typename Derived>
+QualType TreeTransform<Derived>::TransformBuiltinType(TypeLocBuilder &TLB,
+                                                      BuiltinTypeLoc T) {
+  BuiltinTypeLoc NewT = TLB.push<BuiltinTypeLoc>(T.getType());
+  NewT.setBuiltinLoc(T.getBuiltinLoc());
+  if (T.needsExtraLocalData())
+    NewT.getWrittenBuiltinSpecs() = T.getWrittenBuiltinSpecs();
+  return T.getType();
+}
+
+template<typename Derived>
+QualType TreeTransform<Derived>::TransformComplexType(TypeLocBuilder &TLB,
+                                                      ComplexTypeLoc T) {
+  // FIXME: recurse?
+  return TransformTypeSpecType(TLB, T);
+}
+
+template<typename Derived>
+QualType TreeTransform<Derived>::TransformPointerType(TypeLocBuilder &TLB,
+                                                      PointerTypeLoc TL) {
+  TransformPointerLikeType(PointerType);
+}
+
+template<typename Derived>
+QualType
+TreeTransform<Derived>::TransformBlockPointerType(TypeLocBuilder &TLB,
+                                                  BlockPointerTypeLoc TL) {
+  TransformPointerLikeType(BlockPointerType);
+}
+
+/// Transforms a reference type.  Note that somewhat paradoxically we
+/// don't care whether the type itself is an l-value type or an r-value
+/// type;  we only care if the type was *written* as an l-value type
+/// or an r-value type.
+template<typename Derived>
+QualType
+TreeTransform<Derived>::TransformReferenceType(TypeLocBuilder &TLB,
+                                               ReferenceTypeLoc TL) {
+  const ReferenceType *T = TL.getTypePtr();
+
+  // Note that this works with the pointee-as-written.
+  QualType PointeeType = getDerived().TransformType(TLB, TL.getPointeeLoc());
+  if (PointeeType.isNull())
+    return QualType();
+
+  QualType Result = TL.getType();
+  if (getDerived().AlwaysRebuild() ||
+      PointeeType != T->getPointeeTypeAsWritten()) {
+    Result = getDerived().RebuildReferenceType(PointeeType,
+                                               T->isSpelledAsLValue(),
+                                               TL.getSigilLoc());
+    if (Result.isNull())
+      return QualType();
+  }
+
+  // r-value references can be rebuilt as l-value references.
+  ReferenceTypeLoc NewTL;
+  if (isa<LValueReferenceType>(Result))
+    NewTL = TLB.push<LValueReferenceTypeLoc>(Result);
+  else
+    NewTL = TLB.push<RValueReferenceTypeLoc>(Result);
+  NewTL.setSigilLoc(TL.getSigilLoc());
+
+  return Result;
+}
+
+template<typename Derived>
+QualType
+TreeTransform<Derived>::TransformLValueReferenceType(TypeLocBuilder &TLB,
+                                                 LValueReferenceTypeLoc TL) {
+  return TransformReferenceType(TLB, TL);
+}
+
+template<typename Derived>
+QualType
+TreeTransform<Derived>::TransformRValueReferenceType(TypeLocBuilder &TLB,
+                                                 RValueReferenceTypeLoc TL) {
+  return TransformReferenceType(TLB, TL);
+}
+
+template<typename Derived>
+QualType
+TreeTransform<Derived>::TransformMemberPointerType(TypeLocBuilder &TLB,
+                                                   MemberPointerTypeLoc TL) {
+  MemberPointerType *T = TL.getTypePtr();
+
+  QualType PointeeType = getDerived().TransformType(TLB, TL.getPointeeLoc());
+  if (PointeeType.isNull())
+    return QualType();
+
+  // TODO: preserve source information for this.
+  QualType ClassType
+    = getDerived().TransformType(QualType(T->getClass(), 0));
+  if (ClassType.isNull())
+    return QualType();
+
+  QualType Result = TL.getType();
+  if (getDerived().AlwaysRebuild() ||
+      PointeeType != T->getPointeeType() ||
+      ClassType != QualType(T->getClass(), 0)) {
+    Result = getDerived().RebuildMemberPointerType(PointeeType, ClassType,
+                                                   TL.getStarLoc());
+    if (Result.isNull())
+      return QualType();
+  }
+
+  MemberPointerTypeLoc NewTL = TLB.push<MemberPointerTypeLoc>(Result);
+  NewTL.setSigilLoc(TL.getSigilLoc());
+
+  return Result;
+}
+
+template<typename Derived>
+QualType
+TreeTransform<Derived>::TransformConstantArrayType(TypeLocBuilder &TLB,
+                                                   ConstantArrayTypeLoc TL) {
+  ConstantArrayType *T = TL.getTypePtr();
+  QualType ElementType = getDerived().TransformType(TLB, TL.getElementLoc());
+  if (ElementType.isNull())
+    return QualType();
+
+  QualType Result = TL.getType();
+  if (getDerived().AlwaysRebuild() ||
+      ElementType != T->getElementType()) {
+    Result = getDerived().RebuildConstantArrayType(ElementType,
+                                                   T->getSizeModifier(),
+                                                   T->getSize(),
+                                             T->getIndexTypeCVRQualifiers(),
+                                                   TL.getBracketsRange());
+    if (Result.isNull())
+      return QualType();
+  }
+  
+  ConstantArrayTypeLoc NewTL = TLB.push<ConstantArrayTypeLoc>(Result);
+  NewTL.setLBracketLoc(TL.getLBracketLoc());
+  NewTL.setRBracketLoc(TL.getRBracketLoc());
+
+  Expr *Size = TL.getSizeExpr();
+  if (Size) {
+    EnterExpressionEvaluationContext Unevaluated(SemaRef, Action::Unevaluated);
+    Size = getDerived().TransformExpr(Size).template takeAs<Expr>();
+  }
+  NewTL.setSizeExpr(Size);
+
+  return Result;
+}
+
+template<typename Derived>
+QualType TreeTransform<Derived>::TransformIncompleteArrayType(
+                                              TypeLocBuilder &TLB,
+                                              IncompleteArrayTypeLoc TL) {
+  IncompleteArrayType *T = TL.getTypePtr();
+  QualType ElementType = getDerived().TransformType(TLB, TL.getElementLoc());
+  if (ElementType.isNull())
+    return QualType();
+
+  QualType Result = TL.getType();
+  if (getDerived().AlwaysRebuild() ||
+      ElementType != T->getElementType()) {
+    Result = getDerived().RebuildIncompleteArrayType(ElementType,
+                                                     T->getSizeModifier(),
+                                           T->getIndexTypeCVRQualifiers(),
+                                                     TL.getBracketsRange());
+    if (Result.isNull())
+      return QualType();
+  }
+  
+  IncompleteArrayTypeLoc NewTL = TLB.push<IncompleteArrayTypeLoc>(Result);
+  NewTL.setLBracketLoc(TL.getLBracketLoc());
+  NewTL.setRBracketLoc(TL.getRBracketLoc());
+  NewTL.setSizeExpr(0);
+
+  return Result;
+}
+
+template<typename Derived>
+QualType
+TreeTransform<Derived>::TransformVariableArrayType(TypeLocBuilder &TLB,
+                                                   VariableArrayTypeLoc TL) {
+  VariableArrayType *T = TL.getTypePtr();
+  QualType ElementType = getDerived().TransformType(TLB, TL.getElementLoc());
+  if (ElementType.isNull())
+    return QualType();
+
+  // Array bounds are not potentially evaluated contexts
+  EnterExpressionEvaluationContext Unevaluated(SemaRef, Action::Unevaluated);
+
+  Sema::OwningExprResult SizeResult
+    = getDerived().TransformExpr(T->getSizeExpr());
+  if (SizeResult.isInvalid())
+    return QualType();
+
+  Expr *Size = static_cast<Expr*>(SizeResult.get());
+
+  QualType Result = TL.getType();
+  if (getDerived().AlwaysRebuild() ||
+      ElementType != T->getElementType() ||
+      Size != T->getSizeExpr()) {
+    Result = getDerived().RebuildVariableArrayType(ElementType,
+                                                   T->getSizeModifier(),
+                                                   move(SizeResult),
+                                             T->getIndexTypeCVRQualifiers(),
+                                                   TL.getBracketsRange());
+    if (Result.isNull())
+      return QualType();
+  }
+  else SizeResult.take();
+  
+  VariableArrayTypeLoc NewTL = TLB.push<VariableArrayTypeLoc>(Result);
+  NewTL.setLBracketLoc(TL.getLBracketLoc());
+  NewTL.setRBracketLoc(TL.getRBracketLoc());
+  NewTL.setSizeExpr(Size);
+
+  return Result;
+}
+
+template<typename Derived>
+QualType
+TreeTransform<Derived>::TransformDependentSizedArrayType(TypeLocBuilder &TLB,
+                                             DependentSizedArrayTypeLoc TL) {
+  DependentSizedArrayType *T = TL.getTypePtr();
+  QualType ElementType = getDerived().TransformType(TLB, TL.getElementLoc());
+  if (ElementType.isNull())
+    return QualType();
+
+  // Array bounds are not potentially evaluated contexts
+  EnterExpressionEvaluationContext Unevaluated(SemaRef, Action::Unevaluated);
+
+  Sema::OwningExprResult SizeResult
+    = getDerived().TransformExpr(T->getSizeExpr());
+  if (SizeResult.isInvalid())
+    return QualType();
+
+  Expr *Size = static_cast<Expr*>(SizeResult.get());
+
+  QualType Result = TL.getType();
+  if (getDerived().AlwaysRebuild() ||
+      ElementType != T->getElementType() ||
+      Size != T->getSizeExpr()) {
+    Result = getDerived().RebuildDependentSizedArrayType(ElementType,
+                                                         T->getSizeModifier(),
+                                                         move(SizeResult),
+                                                T->getIndexTypeCVRQualifiers(),
+                                                        TL.getBracketsRange());
+    if (Result.isNull())
+      return QualType();
+  }
+  else SizeResult.take();
+
+  // We might have any sort of array type now, but fortunately they
+  // all have the same location layout.
+  ArrayTypeLoc NewTL = TLB.push<ArrayTypeLoc>(Result);
+  NewTL.setLBracketLoc(TL.getLBracketLoc());
+  NewTL.setRBracketLoc(TL.getRBracketLoc());
+  NewTL.setSizeExpr(Size);
+
+  return Result;
+}
+
+template<typename Derived>
+QualType TreeTransform<Derived>::TransformDependentSizedExtVectorType(
+                                      TypeLocBuilder &TLB,
+                                      DependentSizedExtVectorTypeLoc TL) {
+  DependentSizedExtVectorType *T = TL.getTypePtr();
+
+  // FIXME: ext vector locs should be nested
+  QualType ElementType = getDerived().TransformType(T->getElementType());
+  if (ElementType.isNull())
+    return QualType();
+
+  // Vector sizes are not potentially evaluated contexts
+  EnterExpressionEvaluationContext Unevaluated(SemaRef, Action::Unevaluated);
+
+  Sema::OwningExprResult Size = getDerived().TransformExpr(T->getSizeExpr());
+  if (Size.isInvalid())
+    return QualType();
+
+  QualType Result = TL.getType();
+  if (getDerived().AlwaysRebuild() ||
+      ElementType != T->getElementType() ||
+      Size.get() != T->getSizeExpr()) {
+    Result = getDerived().RebuildDependentSizedExtVectorType(ElementType,
+                                                         move(Size),
+                                                         T->getAttributeLoc());
+    if (Result.isNull())
+      return QualType();
+  }
+  else Size.take();
+
+  // Result might be dependent or not.
+  if (isa<DependentSizedExtVectorType>(Result)) {
+    DependentSizedExtVectorTypeLoc NewTL
+      = TLB.push<DependentSizedExtVectorTypeLoc>(Result);
+    NewTL.setNameLoc(TL.getNameLoc());
+  } else {
+    ExtVectorTypeLoc NewTL = TLB.push<ExtVectorTypeLoc>(Result);
+    NewTL.setNameLoc(TL.getNameLoc());
+  }
+
+  return Result;
+}
+
+template<typename Derived>
+QualType TreeTransform<Derived>::TransformVectorType(TypeLocBuilder &TLB,
+                                                     VectorTypeLoc TL) {
+  VectorType *T = TL.getTypePtr();
+  QualType ElementType = getDerived().TransformType(T->getElementType());
+  if (ElementType.isNull())
+    return QualType();
+
+  QualType Result = TL.getType();
+  if (getDerived().AlwaysRebuild() ||
+      ElementType != T->getElementType()) {
+    Result = getDerived().RebuildVectorType(ElementType, T->getNumElements(),
+      T->isAltiVec(), T->isPixel());
+    if (Result.isNull())
+      return QualType();
+  }
+  
+  VectorTypeLoc NewTL = TLB.push<VectorTypeLoc>(Result);
+  NewTL.setNameLoc(TL.getNameLoc());
+
+  return Result;
+}
+
+template<typename Derived>
+QualType TreeTransform<Derived>::TransformExtVectorType(TypeLocBuilder &TLB,
+                                                        ExtVectorTypeLoc TL) {
+  VectorType *T = TL.getTypePtr();
+  QualType ElementType = getDerived().TransformType(T->getElementType());
+  if (ElementType.isNull())
+    return QualType();
+
+  QualType Result = TL.getType();
+  if (getDerived().AlwaysRebuild() ||
+      ElementType != T->getElementType()) {
+    Result = getDerived().RebuildExtVectorType(ElementType,
+                                               T->getNumElements(),
+                                               /*FIXME*/ SourceLocation());
+    if (Result.isNull())
+      return QualType();
+  }
+  
+  ExtVectorTypeLoc NewTL = TLB.push<ExtVectorTypeLoc>(Result);
+  NewTL.setNameLoc(TL.getNameLoc());
+
+  return Result;
+}
+
+template<typename Derived>
+QualType
+TreeTransform<Derived>::TransformFunctionProtoType(TypeLocBuilder &TLB,
+                                                   FunctionProtoTypeLoc TL) {
+  FunctionProtoType *T = TL.getTypePtr();
+  QualType ResultType = getDerived().TransformType(TLB, TL.getResultLoc());
+  if (ResultType.isNull())
+    return QualType();
+
+  // Transform the parameters.
+  llvm::SmallVector<QualType, 4> ParamTypes;
+  llvm::SmallVector<ParmVarDecl*, 4> ParamDecls;
+  for (unsigned i = 0, e = TL.getNumArgs(); i != e; ++i) {
+    ParmVarDecl *OldParm = TL.getArg(i);
+
+    QualType NewType;
+    ParmVarDecl *NewParm;
+
+    if (OldParm) {
+      TypeSourceInfo *OldDI = OldParm->getTypeSourceInfo();
+      assert(OldDI->getType() == T->getArgType(i));
+
+      TypeSourceInfo *NewDI = getDerived().TransformType(OldDI);
+      if (!NewDI)
+        return QualType();
+
+      if (NewDI == OldDI)
+        NewParm = OldParm;
+      else
+        NewParm = ParmVarDecl::Create(SemaRef.Context,
+                                      OldParm->getDeclContext(),
+                                      OldParm->getLocation(),
+                                      OldParm->getIdentifier(),
+                                      NewDI->getType(),
+                                      NewDI,
+                                      OldParm->getStorageClass(),
+                                      /* DefArg */ NULL);
+      NewType = NewParm->getType();
+
+    // Deal with the possibility that we don't have a parameter
+    // declaration for this parameter.
+    } else {
+      NewParm = 0;
+
+      QualType OldType = T->getArgType(i);
+      NewType = getDerived().TransformType(OldType);
+      if (NewType.isNull())
+        return QualType();
+    }
+
+    ParamTypes.push_back(NewType);
+    ParamDecls.push_back(NewParm);
+  }
+
+  QualType Result = TL.getType();
+  if (getDerived().AlwaysRebuild() ||
+      ResultType != T->getResultType() ||
+      !std::equal(T->arg_type_begin(), T->arg_type_end(), ParamTypes.begin())) {
+    Result = getDerived().RebuildFunctionProtoType(ResultType,
+                                                   ParamTypes.data(),
+                                                   ParamTypes.size(),
+                                                   T->isVariadic(),
+                                                   T->getTypeQuals());
+    if (Result.isNull())
+      return QualType();
+  }
+
+  FunctionProtoTypeLoc NewTL = TLB.push<FunctionProtoTypeLoc>(Result);
+  NewTL.setLParenLoc(TL.getLParenLoc());
+  NewTL.setRParenLoc(TL.getRParenLoc());
+  for (unsigned i = 0, e = NewTL.getNumArgs(); i != e; ++i)
+    NewTL.setArg(i, ParamDecls[i]);
+
+  return Result;
+}
+
+template<typename Derived>
+QualType TreeTransform<Derived>::TransformFunctionNoProtoType(
+                                                 TypeLocBuilder &TLB,
+                                                 FunctionNoProtoTypeLoc TL) {
+  FunctionNoProtoType *T = TL.getTypePtr();
+  QualType ResultType = getDerived().TransformType(TLB, TL.getResultLoc());
+  if (ResultType.isNull())
+    return QualType();
+
+  QualType Result = TL.getType();
+  if (getDerived().AlwaysRebuild() ||
+      ResultType != T->getResultType())
+    Result = getDerived().RebuildFunctionNoProtoType(ResultType);
+
+  FunctionNoProtoTypeLoc NewTL = TLB.push<FunctionNoProtoTypeLoc>(Result);
+  NewTL.setLParenLoc(TL.getLParenLoc());
+  NewTL.setRParenLoc(TL.getRParenLoc());
+
+  return Result;
+}
+
+template<typename Derived> QualType
+TreeTransform<Derived>::TransformUnresolvedUsingType(TypeLocBuilder &TLB,
+                                                 UnresolvedUsingTypeLoc TL) {
+  UnresolvedUsingType *T = TL.getTypePtr();
+  Decl *D = getDerived().TransformDecl(T->getDecl());
+  if (!D)
+    return QualType();
+
+  QualType Result = TL.getType();
+  if (getDerived().AlwaysRebuild() || D != T->getDecl()) {
+    Result = getDerived().RebuildUnresolvedUsingType(D);
+    if (Result.isNull())
+      return QualType();
+  }
+
+  // We might get an arbitrary type spec type back.  We should at
+  // least always get a type spec type, though.
+  TypeSpecTypeLoc NewTL = TLB.pushTypeSpec(Result);
+  NewTL.setNameLoc(TL.getNameLoc());
+
+  return Result;
+}
+
+template<typename Derived>
+QualType TreeTransform<Derived>::TransformTypedefType(TypeLocBuilder &TLB,
+                                                      TypedefTypeLoc TL) {
+  TypedefType *T = TL.getTypePtr();
+  TypedefDecl *Typedef
+    = cast_or_null<TypedefDecl>(getDerived().TransformDecl(T->getDecl()));
+  if (!Typedef)
+    return QualType();
+
+  QualType Result = TL.getType();
+  if (getDerived().AlwaysRebuild() ||
+      Typedef != T->getDecl()) {
+    Result = getDerived().RebuildTypedefType(Typedef);
+    if (Result.isNull())
+      return QualType();
+  }
+
+  TypedefTypeLoc NewTL = TLB.push<TypedefTypeLoc>(Result);
+  NewTL.setNameLoc(TL.getNameLoc());
+
+  return Result;
+}
+
+template<typename Derived>
+QualType TreeTransform<Derived>::TransformTypeOfExprType(TypeLocBuilder &TLB,
+                                                      TypeOfExprTypeLoc TL) {
+  // typeof expressions are not potentially evaluated contexts
+  EnterExpressionEvaluationContext Unevaluated(SemaRef, Action::Unevaluated);
+
+  Sema::OwningExprResult E = getDerived().TransformExpr(TL.getUnderlyingExpr());
+  if (E.isInvalid())
+    return QualType();
+
+  QualType Result = TL.getType();
+  if (getDerived().AlwaysRebuild() ||
+      E.get() != TL.getUnderlyingExpr()) {
+    Result = getDerived().RebuildTypeOfExprType(move(E));
+    if (Result.isNull())
+      return QualType();
+  }
+  else E.take();
+
+  TypeOfExprTypeLoc NewTL = TLB.push<TypeOfExprTypeLoc>(Result);
+  NewTL.setTypeofLoc(TL.getTypeofLoc());
+  NewTL.setLParenLoc(TL.getLParenLoc());
+  NewTL.setRParenLoc(TL.getRParenLoc());
+
+  return Result;
+}
+
+template<typename Derived>
+QualType TreeTransform<Derived>::TransformTypeOfType(TypeLocBuilder &TLB,
+                                                     TypeOfTypeLoc TL) {
+  TypeSourceInfo* Old_Under_TI = TL.getUnderlyingTInfo();
+  TypeSourceInfo* New_Under_TI = getDerived().TransformType(Old_Under_TI);
+  if (!New_Under_TI)
+    return QualType();
+
+  QualType Result = TL.getType();
+  if (getDerived().AlwaysRebuild() || New_Under_TI != Old_Under_TI) {
+    Result = getDerived().RebuildTypeOfType(New_Under_TI->getType());
+    if (Result.isNull())
+      return QualType();
+  }
+
+  TypeOfTypeLoc NewTL = TLB.push<TypeOfTypeLoc>(Result);
+  NewTL.setTypeofLoc(TL.getTypeofLoc());
+  NewTL.setLParenLoc(TL.getLParenLoc());
+  NewTL.setRParenLoc(TL.getRParenLoc());
+  NewTL.setUnderlyingTInfo(New_Under_TI);
+
+  return Result;
+}
+
+template<typename Derived>
+QualType TreeTransform<Derived>::TransformDecltypeType(TypeLocBuilder &TLB,
+                                                       DecltypeTypeLoc TL) {
+  DecltypeType *T = TL.getTypePtr();
+
+  // decltype expressions are not potentially evaluated contexts
+  EnterExpressionEvaluationContext Unevaluated(SemaRef, Action::Unevaluated);
+
+  Sema::OwningExprResult E = getDerived().TransformExpr(T->getUnderlyingExpr());
+  if (E.isInvalid())
+    return QualType();
+
+  QualType Result = TL.getType();
+  if (getDerived().AlwaysRebuild() ||
+      E.get() != T->getUnderlyingExpr()) {
+    Result = getDerived().RebuildDecltypeType(move(E));
+    if (Result.isNull())
+      return QualType();
+  }
+  else E.take();
+
+  DecltypeTypeLoc NewTL = TLB.push<DecltypeTypeLoc>(Result);
+  NewTL.setNameLoc(TL.getNameLoc());
+
+  return Result;
+}
+
+template<typename Derived>
+QualType TreeTransform<Derived>::TransformRecordType(TypeLocBuilder &TLB,
+                                                     RecordTypeLoc TL) {
+  RecordType *T = TL.getTypePtr();
+  RecordDecl *Record
+    = cast_or_null<RecordDecl>(getDerived().TransformDecl(T->getDecl()));
+  if (!Record)
+    return QualType();
+
+  QualType Result = TL.getType();
+  if (getDerived().AlwaysRebuild() ||
+      Record != T->getDecl()) {
+    Result = getDerived().RebuildRecordType(Record);
+    if (Result.isNull())
+      return QualType();
+  }
+
+  RecordTypeLoc NewTL = TLB.push<RecordTypeLoc>(Result);
+  NewTL.setNameLoc(TL.getNameLoc());
+
+  return Result;
+}
+
+template<typename Derived>
+QualType TreeTransform<Derived>::TransformEnumType(TypeLocBuilder &TLB,
+                                                   EnumTypeLoc TL) {
+  EnumType *T = TL.getTypePtr();
+  EnumDecl *Enum
+    = cast_or_null<EnumDecl>(getDerived().TransformDecl(T->getDecl()));
+  if (!Enum)
+    return QualType();
+
+  QualType Result = TL.getType();
+  if (getDerived().AlwaysRebuild() ||
+      Enum != T->getDecl()) {
+    Result = getDerived().RebuildEnumType(Enum);
+    if (Result.isNull())
+      return QualType();
+  }
+
+  EnumTypeLoc NewTL = TLB.push<EnumTypeLoc>(Result);
+  NewTL.setNameLoc(TL.getNameLoc());
+
+  return Result;
+}
+
+template <typename Derived>
+QualType TreeTransform<Derived>::TransformElaboratedType(TypeLocBuilder &TLB,
+                                                      ElaboratedTypeLoc TL) {
+  ElaboratedType *T = TL.getTypePtr();
+
+  // FIXME: this should be a nested type.
+  QualType Underlying = getDerived().TransformType(T->getUnderlyingType());
+  if (Underlying.isNull())
+    return QualType();
+
+  QualType Result = TL.getType();
+  if (getDerived().AlwaysRebuild() ||
+      Underlying != T->getUnderlyingType()) {
+    Result = getDerived().RebuildElaboratedType(Underlying, T->getTagKind());
+    if (Result.isNull())
+      return QualType();
+  }
+
+  ElaboratedTypeLoc NewTL = TLB.push<ElaboratedTypeLoc>(Result);
+  NewTL.setNameLoc(TL.getNameLoc());
+
+  return Result;
+}
+
+
+template<typename Derived>
+QualType TreeTransform<Derived>::TransformTemplateTypeParmType(
+                                                TypeLocBuilder &TLB,
+                                                TemplateTypeParmTypeLoc TL) {
+  return TransformTypeSpecType(TLB, TL);
+}
+
+template<typename Derived>
+QualType TreeTransform<Derived>::TransformSubstTemplateTypeParmType(
+                                         TypeLocBuilder &TLB,
+                                         SubstTemplateTypeParmTypeLoc TL) {
+  return TransformTypeSpecType(TLB, TL);
+}
+
+template<typename Derived>
+inline QualType 
+TreeTransform<Derived>::TransformTemplateSpecializationType(
+                                          TypeLocBuilder &TLB,
+                                          TemplateSpecializationTypeLoc TL) {
+  return TransformTemplateSpecializationType(TLB, TL, QualType());
+}
+
+template<typename Derived>
+QualType TreeTransform<Derived>::TransformTemplateSpecializationType(
+                                      const TemplateSpecializationType *TST,
+                                                        QualType ObjectType) {
+  // FIXME: this entire method is a temporary workaround; callers
+  // should be rewritten to provide real type locs.
+
+  // Fake up a TemplateSpecializationTypeLoc.
+  TypeLocBuilder TLB;
+  TemplateSpecializationTypeLoc TL
+    = TLB.push<TemplateSpecializationTypeLoc>(QualType(TST, 0));
+
+  SourceLocation BaseLoc = getDerived().getBaseLocation();
+
+  TL.setTemplateNameLoc(BaseLoc);
+  TL.setLAngleLoc(BaseLoc);
+  TL.setRAngleLoc(BaseLoc);
+  for (unsigned i = 0, e = TL.getNumArgs(); i != e; ++i) {
+    const TemplateArgument &TA = TST->getArg(i);
+    TemplateArgumentLoc TAL;
+    getDerived().InventTemplateArgumentLoc(TA, TAL);
+    TL.setArgLocInfo(i, TAL.getLocInfo());
+  }
+
+  TypeLocBuilder IgnoredTLB;
+  return TransformTemplateSpecializationType(IgnoredTLB, TL, ObjectType);
+}
+  
+template<typename Derived>
+QualType TreeTransform<Derived>::TransformTemplateSpecializationType(
+                                                        TypeLocBuilder &TLB,
+                                           TemplateSpecializationTypeLoc TL,
+                                                        QualType ObjectType) {
+  const TemplateSpecializationType *T = TL.getTypePtr();
+
+  TemplateName Template
+    = getDerived().TransformTemplateName(T->getTemplateName(), ObjectType);
+  if (Template.isNull())
+    return QualType();
+
+  TemplateArgumentListInfo NewTemplateArgs;
+  NewTemplateArgs.setLAngleLoc(TL.getLAngleLoc());
+  NewTemplateArgs.setRAngleLoc(TL.getRAngleLoc());
+
+  for (unsigned i = 0, e = T->getNumArgs(); i != e; ++i) {
+    TemplateArgumentLoc Loc;
+    if (getDerived().TransformTemplateArgument(TL.getArgLoc(i), Loc))
+      return QualType();
+    NewTemplateArgs.addArgument(Loc);
+  }
+
+  // FIXME: maybe don't rebuild if all the template arguments are the same.
+
+  QualType Result =
+    getDerived().RebuildTemplateSpecializationType(Template,
+                                                   TL.getTemplateNameLoc(),
+                                                   NewTemplateArgs);
+
+  if (!Result.isNull()) {
+    TemplateSpecializationTypeLoc NewTL
+      = TLB.push<TemplateSpecializationTypeLoc>(Result);
+    NewTL.setTemplateNameLoc(TL.getTemplateNameLoc());
+    NewTL.setLAngleLoc(TL.getLAngleLoc());
+    NewTL.setRAngleLoc(TL.getRAngleLoc());
+    for (unsigned i = 0, e = NewTemplateArgs.size(); i != e; ++i)
+      NewTL.setArgLocInfo(i, NewTemplateArgs[i].getLocInfo());
+  }
+
+  return Result;
+}
+
+template<typename Derived>
+QualType
+TreeTransform<Derived>::TransformQualifiedNameType(TypeLocBuilder &TLB,
+                                                   QualifiedNameTypeLoc TL) {
+  QualifiedNameType *T = TL.getTypePtr();
+  NestedNameSpecifier *NNS
+    = getDerived().TransformNestedNameSpecifier(T->getQualifier(),
+                                                SourceRange());
+  if (!NNS)
+    return QualType();
+
+  QualType Named = getDerived().TransformType(T->getNamedType());
+  if (Named.isNull())
+    return QualType();
+
+  QualType Result = TL.getType();
+  if (getDerived().AlwaysRebuild() ||
+      NNS != T->getQualifier() ||
+      Named != T->getNamedType()) {
+    Result = getDerived().RebuildQualifiedNameType(NNS, Named);
+    if (Result.isNull())
+      return QualType();
+  }
+
+  QualifiedNameTypeLoc NewTL = TLB.push<QualifiedNameTypeLoc>(Result);
+  NewTL.setNameLoc(TL.getNameLoc());
+
+  return Result;
+}
+
+template<typename Derived>
+QualType TreeTransform<Derived>::TransformTypenameType(TypeLocBuilder &TLB,
+                                                       TypenameTypeLoc TL) {
+  TypenameType *T = TL.getTypePtr();
+
+  /* FIXME: preserve source information better than this */
+  SourceRange SR(TL.getNameLoc());
+
+  NestedNameSpecifier *NNS
+    = getDerived().TransformNestedNameSpecifier(T->getQualifier(), SR);
+  if (!NNS)
+    return QualType();
+
+  QualType Result;
+
+  if (const TemplateSpecializationType *TemplateId = T->getTemplateId()) {
+    QualType NewTemplateId
+      = getDerived().TransformType(QualType(TemplateId, 0));
+    if (NewTemplateId.isNull())
+      return QualType();
+
+    if (!getDerived().AlwaysRebuild() &&
+        NNS == T->getQualifier() &&
+        NewTemplateId == QualType(TemplateId, 0))
+      return QualType(T, 0);
+
+    Result = getDerived().RebuildTypenameType(NNS, NewTemplateId);
+  } else {
+    Result = getDerived().RebuildTypenameType(NNS, T->getIdentifier(), SR);
+  }
+  if (Result.isNull())
+    return QualType();
+
+  TypenameTypeLoc NewTL = TLB.push<TypenameTypeLoc>(Result);
+  NewTL.setNameLoc(TL.getNameLoc());
+
+  return Result;
+}
+
+template<typename Derived>
+QualType
+TreeTransform<Derived>::TransformObjCInterfaceType(TypeLocBuilder &TLB,
+                                                   ObjCInterfaceTypeLoc TL) {
+  assert(false && "TransformObjCInterfaceType unimplemented");
+  return QualType();
+}
+
+template<typename Derived>
+QualType
+TreeTransform<Derived>::TransformObjCObjectPointerType(TypeLocBuilder &TLB,
+                                               ObjCObjectPointerTypeLoc TL) {
+  assert(false && "TransformObjCObjectPointerType unimplemented");
+  return QualType();
+}
+
+//===----------------------------------------------------------------------===//
+// Statement transformation
+//===----------------------------------------------------------------------===//
+template<typename Derived>
+Sema::OwningStmtResult
+TreeTransform<Derived>::TransformNullStmt(NullStmt *S) {
+  return SemaRef.Owned(S->Retain());
+}
+
+template<typename Derived>
+Sema::OwningStmtResult
+TreeTransform<Derived>::TransformCompoundStmt(CompoundStmt *S) {
+  return getDerived().TransformCompoundStmt(S, false);
+}
+
+template<typename Derived>
+Sema::OwningStmtResult
+TreeTransform<Derived>::TransformCompoundStmt(CompoundStmt *S,
+                                              bool IsStmtExpr) {
+  bool SubStmtChanged = false;
+  ASTOwningVector<&ActionBase::DeleteStmt> Statements(getSema());
+  for (CompoundStmt::body_iterator B = S->body_begin(), BEnd = S->body_end();
+       B != BEnd; ++B) {
+    OwningStmtResult Result = getDerived().TransformStmt(*B);
+    if (Result.isInvalid())
+      return getSema().StmtError();
+
+    SubStmtChanged = SubStmtChanged || Result.get() != *B;
+    Statements.push_back(Result.takeAs<Stmt>());
+  }
+
+  if (!getDerived().AlwaysRebuild() &&
+      !SubStmtChanged)
+    return SemaRef.Owned(S->Retain());
+
+  return getDerived().RebuildCompoundStmt(S->getLBracLoc(),
+                                          move_arg(Statements),
+                                          S->getRBracLoc(),
+                                          IsStmtExpr);
+}
+
+template<typename Derived>
+Sema::OwningStmtResult
+TreeTransform<Derived>::TransformCaseStmt(CaseStmt *S) {
+  OwningExprResult LHS(SemaRef), RHS(SemaRef);
+  {
+    // The case value expressions are not potentially evaluated.
+    EnterExpressionEvaluationContext Unevaluated(SemaRef, Action::Unevaluated);
+
+    // Transform the left-hand case value.
+    LHS = getDerived().TransformExpr(S->getLHS());
+    if (LHS.isInvalid())
+      return SemaRef.StmtError();
+
+    // Transform the right-hand case value (for the GNU case-range extension).
+    RHS = getDerived().TransformExpr(S->getRHS());
+    if (RHS.isInvalid())
+      return SemaRef.StmtError();
+  }
+
+  // Build the case statement.
+  // Case statements are always rebuilt so that they will attached to their
+  // transformed switch statement.
+  OwningStmtResult Case = getDerived().RebuildCaseStmt(S->getCaseLoc(),
+                                                       move(LHS),
+                                                       S->getEllipsisLoc(),
+                                                       move(RHS),
+                                                       S->getColonLoc());
+  if (Case.isInvalid())
+    return SemaRef.StmtError();
+
+  // Transform the statement following the case
+  OwningStmtResult SubStmt = getDerived().TransformStmt(S->getSubStmt());
+  if (SubStmt.isInvalid())
+    return SemaRef.StmtError();
+
+  // Attach the body to the case statement
+  return getDerived().RebuildCaseStmtBody(move(Case), move(SubStmt));
+}
+
+template<typename Derived>
+Sema::OwningStmtResult
+TreeTransform<Derived>::TransformDefaultStmt(DefaultStmt *S) {
+  // Transform the statement following the default case
+  OwningStmtResult SubStmt = getDerived().TransformStmt(S->getSubStmt());
+  if (SubStmt.isInvalid())
+    return SemaRef.StmtError();
+
+  // Default statements are always rebuilt
+  return getDerived().RebuildDefaultStmt(S->getDefaultLoc(), S->getColonLoc(),
+                                         move(SubStmt));
+}
+
+template<typename Derived>
+Sema::OwningStmtResult
+TreeTransform<Derived>::TransformLabelStmt(LabelStmt *S) {
+  OwningStmtResult SubStmt = getDerived().TransformStmt(S->getSubStmt());
+  if (SubStmt.isInvalid())
+    return SemaRef.StmtError();
+
+  // FIXME: Pass the real colon location in.
+  SourceLocation ColonLoc = SemaRef.PP.getLocForEndOfToken(S->getIdentLoc());
+  return getDerived().RebuildLabelStmt(S->getIdentLoc(), S->getID(), ColonLoc,
+                                       move(SubStmt));
+}
+
+template<typename Derived>
+Sema::OwningStmtResult
+TreeTransform<Derived>::TransformIfStmt(IfStmt *S) {
+  // Transform the condition
+  OwningExprResult Cond(SemaRef);
+  VarDecl *ConditionVar = 0;
+  if (S->getConditionVariable()) {
+    ConditionVar 
+      = cast_or_null<VarDecl>(
+                   getDerived().TransformDefinition(S->getConditionVariable()));
+    if (!ConditionVar)
+      return SemaRef.StmtError();
+  } else {
+    Cond = getDerived().TransformExpr(S->getCond());
+  
+    if (Cond.isInvalid())
+      return SemaRef.StmtError();
+  }
+  
+  Sema::FullExprArg FullCond(getSema().MakeFullExpr(Cond));
+
+  // Transform the "then" branch.
+  OwningStmtResult Then = getDerived().TransformStmt(S->getThen());
+  if (Then.isInvalid())
+    return SemaRef.StmtError();
+
+  // Transform the "else" branch.
+  OwningStmtResult Else = getDerived().TransformStmt(S->getElse());
+  if (Else.isInvalid())
+    return SemaRef.StmtError();
+
+  if (!getDerived().AlwaysRebuild() &&
+      FullCond->get() == S->getCond() &&
+      ConditionVar == S->getConditionVariable() &&
+      Then.get() == S->getThen() &&
+      Else.get() == S->getElse())
+    return SemaRef.Owned(S->Retain());
+
+  return getDerived().RebuildIfStmt(S->getIfLoc(), FullCond, ConditionVar,
+                                    move(Then),
+                                    S->getElseLoc(), move(Else));
+}
+
+template<typename Derived>
+Sema::OwningStmtResult
+TreeTransform<Derived>::TransformSwitchStmt(SwitchStmt *S) {
+  // Transform the condition.
+  OwningExprResult Cond(SemaRef);
+  VarDecl *ConditionVar = 0;
+  if (S->getConditionVariable()) {
+    ConditionVar 
+      = cast_or_null<VarDecl>(
+                   getDerived().TransformDefinition(S->getConditionVariable()));
+    if (!ConditionVar)
+      return SemaRef.StmtError();
+  } else {
+    Cond = getDerived().TransformExpr(S->getCond());
+    
+    if (Cond.isInvalid())
+      return SemaRef.StmtError();
+  }
+
+  Sema::FullExprArg FullCond(getSema().MakeFullExpr(Cond));
+  
+  // Rebuild the switch statement.
+  OwningStmtResult Switch = getDerived().RebuildSwitchStmtStart(FullCond,
+                                                                ConditionVar);
+  if (Switch.isInvalid())
+    return SemaRef.StmtError();
+
+  // Transform the body of the switch statement.
+  OwningStmtResult Body = getDerived().TransformStmt(S->getBody());
+  if (Body.isInvalid())
+    return SemaRef.StmtError();
+
+  // Complete the switch statement.
+  return getDerived().RebuildSwitchStmtBody(S->getSwitchLoc(), move(Switch),
+                                            move(Body));
+}
+
+template<typename Derived>
+Sema::OwningStmtResult
+TreeTransform<Derived>::TransformWhileStmt(WhileStmt *S) {
+  // Transform the condition
+  OwningExprResult Cond(SemaRef);
+  VarDecl *ConditionVar = 0;
+  if (S->getConditionVariable()) {
+    ConditionVar 
+      = cast_or_null<VarDecl>(
+                   getDerived().TransformDefinition(S->getConditionVariable()));
+    if (!ConditionVar)
+      return SemaRef.StmtError();
+  } else {
+    Cond = getDerived().TransformExpr(S->getCond());
+    
+    if (Cond.isInvalid())
+      return SemaRef.StmtError();
+  }
+
+  Sema::FullExprArg FullCond(getSema().MakeFullExpr(Cond));
+
+  // Transform the body
+  OwningStmtResult Body = getDerived().TransformStmt(S->getBody());
+  if (Body.isInvalid())
+    return SemaRef.StmtError();
+
+  if (!getDerived().AlwaysRebuild() &&
+      FullCond->get() == S->getCond() &&
+      ConditionVar == S->getConditionVariable() &&
+      Body.get() == S->getBody())
+    return SemaRef.Owned(S->Retain());
+
+  return getDerived().RebuildWhileStmt(S->getWhileLoc(), FullCond, ConditionVar,
+                                       move(Body));
+}
+
+template<typename Derived>
+Sema::OwningStmtResult
+TreeTransform<Derived>::TransformDoStmt(DoStmt *S) {
+  // Transform the condition
+  OwningExprResult Cond = getDerived().TransformExpr(S->getCond());
+  if (Cond.isInvalid())
+    return SemaRef.StmtError();
+
+  // Transform the body
+  OwningStmtResult Body = getDerived().TransformStmt(S->getBody());
+  if (Body.isInvalid())
+    return SemaRef.StmtError();
+
+  if (!getDerived().AlwaysRebuild() &&
+      Cond.get() == S->getCond() &&
+      Body.get() == S->getBody())
+    return SemaRef.Owned(S->Retain());
+
+  return getDerived().RebuildDoStmt(S->getDoLoc(), move(Body), S->getWhileLoc(),
+                                    /*FIXME:*/S->getWhileLoc(), move(Cond),
+                                    S->getRParenLoc());
+}
+
+template<typename Derived>
+Sema::OwningStmtResult
+TreeTransform<Derived>::TransformForStmt(ForStmt *S) {
+  // Transform the initialization statement
+  OwningStmtResult Init = getDerived().TransformStmt(S->getInit());
+  if (Init.isInvalid())
+    return SemaRef.StmtError();
+
+  // Transform the condition
+  OwningExprResult Cond(SemaRef);
+  VarDecl *ConditionVar = 0;
+  if (S->getConditionVariable()) {
+    ConditionVar 
+      = cast_or_null<VarDecl>(
+                   getDerived().TransformDefinition(S->getConditionVariable()));
+    if (!ConditionVar)
+      return SemaRef.StmtError();
+  } else {
+    Cond = getDerived().TransformExpr(S->getCond());
+    
+    if (Cond.isInvalid())
+      return SemaRef.StmtError();
+  }
+
+  // Transform the increment
+  OwningExprResult Inc = getDerived().TransformExpr(S->getInc());
+  if (Inc.isInvalid())
+    return SemaRef.StmtError();
+
+  // Transform the body
+  OwningStmtResult Body = getDerived().TransformStmt(S->getBody());
+  if (Body.isInvalid())
+    return SemaRef.StmtError();
+
+  if (!getDerived().AlwaysRebuild() &&
+      Init.get() == S->getInit() &&
+      Cond.get() == S->getCond() &&
+      Inc.get() == S->getInc() &&
+      Body.get() == S->getBody())
+    return SemaRef.Owned(S->Retain());
+
+  return getDerived().RebuildForStmt(S->getForLoc(), S->getLParenLoc(),
+                                     move(Init), getSema().MakeFullExpr(Cond),
+                                     ConditionVar,
+                                     getSema().MakeFullExpr(Inc),
+                                     S->getRParenLoc(), move(Body));
+}
+
+template<typename Derived>
+Sema::OwningStmtResult
+TreeTransform<Derived>::TransformGotoStmt(GotoStmt *S) {
+  // Goto statements must always be rebuilt, to resolve the label.
+  return getDerived().RebuildGotoStmt(S->getGotoLoc(), S->getLabelLoc(),
+                                      S->getLabel());
+}
+
+template<typename Derived>
+Sema::OwningStmtResult
+TreeTransform<Derived>::TransformIndirectGotoStmt(IndirectGotoStmt *S) {
+  OwningExprResult Target = getDerived().TransformExpr(S->getTarget());
+  if (Target.isInvalid())
+    return SemaRef.StmtError();
+
+  if (!getDerived().AlwaysRebuild() &&
+      Target.get() == S->getTarget())
+    return SemaRef.Owned(S->Retain());
+
+  return getDerived().RebuildIndirectGotoStmt(S->getGotoLoc(), S->getStarLoc(),
+                                              move(Target));
+}
+
+template<typename Derived>
+Sema::OwningStmtResult
+TreeTransform<Derived>::TransformContinueStmt(ContinueStmt *S) {
+  return SemaRef.Owned(S->Retain());
+}
+
+template<typename Derived>
+Sema::OwningStmtResult
+TreeTransform<Derived>::TransformBreakStmt(BreakStmt *S) {
+  return SemaRef.Owned(S->Retain());
+}
+
+template<typename Derived>
+Sema::OwningStmtResult
+TreeTransform<Derived>::TransformReturnStmt(ReturnStmt *S) {
+  Sema::OwningExprResult Result = getDerived().TransformExpr(S->getRetValue());
+  if (Result.isInvalid())
+    return SemaRef.StmtError();
+
+  // FIXME: We always rebuild the return statement because there is no way
+  // to tell whether the return type of the function has changed.
+  return getDerived().RebuildReturnStmt(S->getReturnLoc(), move(Result));
+}
+
+template<typename Derived>
+Sema::OwningStmtResult
+TreeTransform<Derived>::TransformDeclStmt(DeclStmt *S) {
+  bool DeclChanged = false;
+  llvm::SmallVector<Decl *, 4> Decls;
+  for (DeclStmt::decl_iterator D = S->decl_begin(), DEnd = S->decl_end();
+       D != DEnd; ++D) {
+    Decl *Transformed = getDerived().TransformDefinition(*D);
+    if (!Transformed)
+      return SemaRef.StmtError();
+
+    if (Transformed != *D)
+      DeclChanged = true;
+
+    Decls.push_back(Transformed);
+  }
+
+  if (!getDerived().AlwaysRebuild() && !DeclChanged)
+    return SemaRef.Owned(S->Retain());
+
+  return getDerived().RebuildDeclStmt(Decls.data(), Decls.size(),
+                                      S->getStartLoc(), S->getEndLoc());
+}
+
+template<typename Derived>
+Sema::OwningStmtResult
+TreeTransform<Derived>::TransformSwitchCase(SwitchCase *S) {
+  assert(false && "SwitchCase is abstract and cannot be transformed");
+  return SemaRef.Owned(S->Retain());
+}
+
+template<typename Derived>
+Sema::OwningStmtResult
+TreeTransform<Derived>::TransformAsmStmt(AsmStmt *S) {
+  
+  ASTOwningVector<&ActionBase::DeleteExpr> Constraints(getSema());
+  ASTOwningVector<&ActionBase::DeleteExpr> Exprs(getSema());
+  llvm::SmallVector<IdentifierInfo *, 4> Names;
+
+  OwningExprResult AsmString(SemaRef);
+  ASTOwningVector<&ActionBase::DeleteExpr> Clobbers(getSema());
+
+  bool ExprsChanged = false;
+  
+  // Go through the outputs.
+  for (unsigned I = 0, E = S->getNumOutputs(); I != E; ++I) {
+    Names.push_back(S->getOutputIdentifier(I));
+    
+    // No need to transform the constraint literal.
+    Constraints.push_back(S->getOutputConstraintLiteral(I)->Retain());
+    
+    // Transform the output expr.
+    Expr *OutputExpr = S->getOutputExpr(I);
+    OwningExprResult Result = getDerived().TransformExpr(OutputExpr);
+    if (Result.isInvalid())
+      return SemaRef.StmtError();
+    
+    ExprsChanged |= Result.get() != OutputExpr;
+    
+    Exprs.push_back(Result.takeAs<Expr>());
+  }
+  
+  // Go through the inputs.
+  for (unsigned I = 0, E = S->getNumInputs(); I != E; ++I) {
+    Names.push_back(S->getInputIdentifier(I));
+    
+    // No need to transform the constraint literal.
+    Constraints.push_back(S->getInputConstraintLiteral(I)->Retain());
+    
+    // Transform the input expr.
+    Expr *InputExpr = S->getInputExpr(I);
+    OwningExprResult Result = getDerived().TransformExpr(InputExpr);
+    if (Result.isInvalid())
+      return SemaRef.StmtError();
+    
+    ExprsChanged |= Result.get() != InputExpr;
+    
+    Exprs.push_back(Result.takeAs<Expr>());
+  }
+  
+  if (!getDerived().AlwaysRebuild() && !ExprsChanged)
+    return SemaRef.Owned(S->Retain());
+
+  // Go through the clobbers.
+  for (unsigned I = 0, E = S->getNumClobbers(); I != E; ++I)
+    Clobbers.push_back(S->getClobber(I)->Retain());
+
+  // No need to transform the asm string literal.
+  AsmString = SemaRef.Owned(S->getAsmString());
+
+  return getDerived().RebuildAsmStmt(S->getAsmLoc(),
+                                     S->isSimple(),
+                                     S->isVolatile(),
+                                     S->getNumOutputs(),
+                                     S->getNumInputs(),
+                                     Names.data(),
+                                     move_arg(Constraints),
+                                     move_arg(Exprs),
+                                     move(AsmString),
+                                     move_arg(Clobbers),
+                                     S->getRParenLoc(),
+                                     S->isMSAsm());
+}
+
+
+template<typename Derived>
+Sema::OwningStmtResult
+TreeTransform<Derived>::TransformObjCAtTryStmt(ObjCAtTryStmt *S) {
+  // FIXME: Implement this
+  assert(false && "Cannot transform an Objective-C @try statement");
+  return SemaRef.Owned(S->Retain());
+}
+
+template<typename Derived>
+Sema::OwningStmtResult
+TreeTransform<Derived>::TransformObjCAtCatchStmt(ObjCAtCatchStmt *S) {
+  // FIXME: Implement this
+  assert(false && "Cannot transform an Objective-C @catch statement");
+  return SemaRef.Owned(S->Retain());
+}
+
+template<typename Derived>
+Sema::OwningStmtResult
+TreeTransform<Derived>::TransformObjCAtFinallyStmt(ObjCAtFinallyStmt *S) {
+  // FIXME: Implement this
+  assert(false && "Cannot transform an Objective-C @finally statement");
+  return SemaRef.Owned(S->Retain());
+}
+
+template<typename Derived>
+Sema::OwningStmtResult
+TreeTransform<Derived>::TransformObjCAtThrowStmt(ObjCAtThrowStmt *S) {
+  // FIXME: Implement this
+  assert(false && "Cannot transform an Objective-C @throw statement");
+  return SemaRef.Owned(S->Retain());
+}
+
+template<typename Derived>
+Sema::OwningStmtResult
+TreeTransform<Derived>::TransformObjCAtSynchronizedStmt(
+                                                  ObjCAtSynchronizedStmt *S) {
+  // FIXME: Implement this
+  assert(false && "Cannot transform an Objective-C @synchronized statement");
+  return SemaRef.Owned(S->Retain());
+}
+
+template<typename Derived>
+Sema::OwningStmtResult
+TreeTransform<Derived>::TransformObjCForCollectionStmt(
+                                                  ObjCForCollectionStmt *S) {
+  // FIXME: Implement this
+  assert(false && "Cannot transform an Objective-C for-each statement");
+  return SemaRef.Owned(S->Retain());
+}
+
+
+template<typename Derived>
+Sema::OwningStmtResult
+TreeTransform<Derived>::TransformCXXCatchStmt(CXXCatchStmt *S) {
+  // Transform the exception declaration, if any.
+  VarDecl *Var = 0;
+  if (S->getExceptionDecl()) {
+    VarDecl *ExceptionDecl = S->getExceptionDecl();
+    TemporaryBase Rebase(*this, ExceptionDecl->getLocation(),
+                         ExceptionDecl->getDeclName());
+
+    QualType T = getDerived().TransformType(ExceptionDecl->getType());
+    if (T.isNull())
+      return SemaRef.StmtError();
+
+    Var = getDerived().RebuildExceptionDecl(ExceptionDecl,
+                                            T,
+                                            ExceptionDecl->getTypeSourceInfo(),
+                                            ExceptionDecl->getIdentifier(),
+                                            ExceptionDecl->getLocation(),
+                                            /*FIXME: Inaccurate*/
+                                    SourceRange(ExceptionDecl->getLocation()));
+    if (!Var || Var->isInvalidDecl()) {
+      if (Var)
+        Var->Destroy(SemaRef.Context);
+      return SemaRef.StmtError();
+    }
+  }
+
+  // Transform the actual exception handler.
+  OwningStmtResult Handler = getDerived().TransformStmt(S->getHandlerBlock());
+  if (Handler.isInvalid()) {
+    if (Var)
+      Var->Destroy(SemaRef.Context);
+    return SemaRef.StmtError();
+  }
+
+  if (!getDerived().AlwaysRebuild() &&
+      !Var &&
+      Handler.get() == S->getHandlerBlock())
+    return SemaRef.Owned(S->Retain());
+
+  return getDerived().RebuildCXXCatchStmt(S->getCatchLoc(),
+                                          Var,
+                                          move(Handler));
+}
+
+template<typename Derived>
+Sema::OwningStmtResult
+TreeTransform<Derived>::TransformCXXTryStmt(CXXTryStmt *S) {
+  // Transform the try block itself.
+  OwningStmtResult TryBlock
+    = getDerived().TransformCompoundStmt(S->getTryBlock());
+  if (TryBlock.isInvalid())
+    return SemaRef.StmtError();
+
+  // Transform the handlers.
+  bool HandlerChanged = false;
+  ASTOwningVector<&ActionBase::DeleteStmt> Handlers(SemaRef);
+  for (unsigned I = 0, N = S->getNumHandlers(); I != N; ++I) {
+    OwningStmtResult Handler
+      = getDerived().TransformCXXCatchStmt(S->getHandler(I));
+    if (Handler.isInvalid())
+      return SemaRef.StmtError();
+
+    HandlerChanged = HandlerChanged || Handler.get() != S->getHandler(I);
+    Handlers.push_back(Handler.takeAs<Stmt>());
+  }
+
+  if (!getDerived().AlwaysRebuild() &&
+      TryBlock.get() == S->getTryBlock() &&
+      !HandlerChanged)
+    return SemaRef.Owned(S->Retain());
+
+  return getDerived().RebuildCXXTryStmt(S->getTryLoc(), move(TryBlock),
+                                        move_arg(Handlers));
+}
+
+//===----------------------------------------------------------------------===//
+// Expression transformation
+//===----------------------------------------------------------------------===//
+template<typename Derived>
+Sema::OwningExprResult
+TreeTransform<Derived>::TransformPredefinedExpr(PredefinedExpr *E) {
+  return SemaRef.Owned(E->Retain());
+}
+
+template<typename Derived>
+Sema::OwningExprResult
+TreeTransform<Derived>::TransformDeclRefExpr(DeclRefExpr *E) {
+  NestedNameSpecifier *Qualifier = 0;
+  if (E->getQualifier()) {
+    Qualifier = getDerived().TransformNestedNameSpecifier(E->getQualifier(),
+                                                       E->getQualifierRange());
+    if (!Qualifier)
+      return SemaRef.ExprError();
+  }
+
+  ValueDecl *ND
+    = cast_or_null<ValueDecl>(getDerived().TransformDecl(E->getDecl()));
+  if (!ND)
+    return SemaRef.ExprError();
+
+  if (!getDerived().AlwaysRebuild() && 
+      Qualifier == E->getQualifier() &&
+      ND == E->getDecl() &&
+      !E->hasExplicitTemplateArgumentList()) {
+
+    // Mark it referenced in the new context regardless.
+    // FIXME: this is a bit instantiation-specific.
+    SemaRef.MarkDeclarationReferenced(E->getLocation(), ND);
+
+    return SemaRef.Owned(E->Retain());
+  }
+
+  TemplateArgumentListInfo TransArgs, *TemplateArgs = 0;
+  if (E->hasExplicitTemplateArgumentList()) {
+    TemplateArgs = &TransArgs;
+    TransArgs.setLAngleLoc(E->getLAngleLoc());
+    TransArgs.setRAngleLoc(E->getRAngleLoc());
+    for (unsigned I = 0, N = E->getNumTemplateArgs(); I != N; ++I) {
+      TemplateArgumentLoc Loc;
+      if (getDerived().TransformTemplateArgument(E->getTemplateArgs()[I], Loc))
+        return SemaRef.ExprError();
+      TransArgs.addArgument(Loc);
+    }
+  }
+
+  return getDerived().RebuildDeclRefExpr(Qualifier, E->getQualifierRange(),
+                                         ND, E->getLocation(), TemplateArgs);
+}
+
+template<typename Derived>
+Sema::OwningExprResult
+TreeTransform<Derived>::TransformIntegerLiteral(IntegerLiteral *E) {
+  return SemaRef.Owned(E->Retain());
+}
+
+template<typename Derived>
+Sema::OwningExprResult
+TreeTransform<Derived>::TransformFloatingLiteral(FloatingLiteral *E) {
+  return SemaRef.Owned(E->Retain());
+}
+
+template<typename Derived>
+Sema::OwningExprResult
+TreeTransform<Derived>::TransformImaginaryLiteral(ImaginaryLiteral *E) {
+  return SemaRef.Owned(E->Retain());
+}
+
+template<typename Derived>
+Sema::OwningExprResult
+TreeTransform<Derived>::TransformStringLiteral(StringLiteral *E) {
+  return SemaRef.Owned(E->Retain());
+}
+
+template<typename Derived>
+Sema::OwningExprResult
+TreeTransform<Derived>::TransformCharacterLiteral(CharacterLiteral *E) {
+  return SemaRef.Owned(E->Retain());
+}
+
+template<typename Derived>
+Sema::OwningExprResult
+TreeTransform<Derived>::TransformParenExpr(ParenExpr *E) {
+  OwningExprResult SubExpr = getDerived().TransformExpr(E->getSubExpr());
+  if (SubExpr.isInvalid())
+    return SemaRef.ExprError();
+
+  if (!getDerived().AlwaysRebuild() && SubExpr.get() == E->getSubExpr())
+    return SemaRef.Owned(E->Retain());
+
+  return getDerived().RebuildParenExpr(move(SubExpr), E->getLParen(),
+                                       E->getRParen());
+}
+
+template<typename Derived>
+Sema::OwningExprResult
+TreeTransform<Derived>::TransformUnaryOperator(UnaryOperator *E) {
+  OwningExprResult SubExpr = getDerived().TransformExpr(E->getSubExpr());
+  if (SubExpr.isInvalid())
+    return SemaRef.ExprError();
+
+  if (!getDerived().AlwaysRebuild() && SubExpr.get() == E->getSubExpr())
+    return SemaRef.Owned(E->Retain());
+
+  return getDerived().RebuildUnaryOperator(E->getOperatorLoc(),
+                                           E->getOpcode(),
+                                           move(SubExpr));
+}
+
+template<typename Derived>
+Sema::OwningExprResult
+TreeTransform<Derived>::TransformSizeOfAlignOfExpr(SizeOfAlignOfExpr *E) {
+  if (E->isArgumentType()) {
+    TypeSourceInfo *OldT = E->getArgumentTypeInfo();
+
+    TypeSourceInfo *NewT = getDerived().TransformType(OldT);
+    if (!NewT)
+      return SemaRef.ExprError();
+
+    if (!getDerived().AlwaysRebuild() && OldT == NewT)
+      return SemaRef.Owned(E->Retain());
+
+    return getDerived().RebuildSizeOfAlignOf(NewT, E->getOperatorLoc(),
+                                             E->isSizeOf(),
+                                             E->getSourceRange());
+  }
+
+  Sema::OwningExprResult SubExpr(SemaRef);
+  {
+    // C++0x [expr.sizeof]p1:
+    //   The operand is either an expression, which is an unevaluated operand
+    //   [...]
+    EnterExpressionEvaluationContext Unevaluated(SemaRef, Action::Unevaluated);
+
+    SubExpr = getDerived().TransformExpr(E->getArgumentExpr());
+    if (SubExpr.isInvalid())
+      return SemaRef.ExprError();
+
+    if (!getDerived().AlwaysRebuild() && SubExpr.get() == E->getArgumentExpr())
+      return SemaRef.Owned(E->Retain());
+  }
+
+  return getDerived().RebuildSizeOfAlignOf(move(SubExpr), E->getOperatorLoc(),
+                                           E->isSizeOf(),
+                                           E->getSourceRange());
+}
+
+template<typename Derived>
+Sema::OwningExprResult
+TreeTransform<Derived>::TransformArraySubscriptExpr(ArraySubscriptExpr *E) {
+  OwningExprResult LHS = getDerived().TransformExpr(E->getLHS());
+  if (LHS.isInvalid())
+    return SemaRef.ExprError();
+
+  OwningExprResult RHS = getDerived().TransformExpr(E->getRHS());
+  if (RHS.isInvalid())
+    return SemaRef.ExprError();
+
+
+  if (!getDerived().AlwaysRebuild() &&
+      LHS.get() == E->getLHS() &&
+      RHS.get() == E->getRHS())
+    return SemaRef.Owned(E->Retain());
+
+  return getDerived().RebuildArraySubscriptExpr(move(LHS),
+                                           /*FIXME:*/E->getLHS()->getLocStart(),
+                                                move(RHS),
+                                                E->getRBracketLoc());
+}
+
+template<typename Derived>
+Sema::OwningExprResult
+TreeTransform<Derived>::TransformCallExpr(CallExpr *E) {
+  // Transform the callee.
+  OwningExprResult Callee = getDerived().TransformExpr(E->getCallee());
+  if (Callee.isInvalid())
+    return SemaRef.ExprError();
+
+  // Transform arguments.
+  bool ArgChanged = false;
+  ASTOwningVector<&ActionBase::DeleteExpr> Args(SemaRef);
+  llvm::SmallVector<SourceLocation, 4> FakeCommaLocs;
+  for (unsigned I = 0, N = E->getNumArgs(); I != N; ++I) {
+    OwningExprResult Arg = getDerived().TransformExpr(E->getArg(I));
+    if (Arg.isInvalid())
+      return SemaRef.ExprError();
+
+    // FIXME: Wrong source location information for the ','.
+    FakeCommaLocs.push_back(
+       SemaRef.PP.getLocForEndOfToken(E->getArg(I)->getSourceRange().getEnd()));
+
+    ArgChanged = ArgChanged || Arg.get() != E->getArg(I);
+    Args.push_back(Arg.takeAs<Expr>());
+  }
+
+  if (!getDerived().AlwaysRebuild() &&
+      Callee.get() == E->getCallee() &&
+      !ArgChanged)
+    return SemaRef.Owned(E->Retain());
+
+  // FIXME: Wrong source location information for the '('.
+  SourceLocation FakeLParenLoc
+    = ((Expr *)Callee.get())->getSourceRange().getBegin();
+  return getDerived().RebuildCallExpr(move(Callee), FakeLParenLoc,
+                                      move_arg(Args),
+                                      FakeCommaLocs.data(),
+                                      E->getRParenLoc());
+}
+
+template<typename Derived>
+Sema::OwningExprResult
+TreeTransform<Derived>::TransformMemberExpr(MemberExpr *E) {
+  OwningExprResult Base = getDerived().TransformExpr(E->getBase());
+  if (Base.isInvalid())
+    return SemaRef.ExprError();
+
+  NestedNameSpecifier *Qualifier = 0;
+  if (E->hasQualifier()) {
+    Qualifier
+      = getDerived().TransformNestedNameSpecifier(E->getQualifier(),
+                                                  E->getQualifierRange());
+    if (Qualifier == 0)
+      return SemaRef.ExprError();
+  }
+
+  ValueDecl *Member
+    = cast_or_null<ValueDecl>(getDerived().TransformDecl(E->getMemberDecl()));
+  if (!Member)
+    return SemaRef.ExprError();
+
+  if (!getDerived().AlwaysRebuild() &&
+      Base.get() == E->getBase() &&
+      Qualifier == E->getQualifier() &&
+      Member == E->getMemberDecl() &&
+      !E->hasExplicitTemplateArgumentList()) {
+    
+    // Mark it referenced in the new context regardless.
+    // FIXME: this is a bit instantiation-specific.
+    SemaRef.MarkDeclarationReferenced(E->getMemberLoc(), Member);
+    return SemaRef.Owned(E->Retain());
+  }
+
+  TemplateArgumentListInfo TransArgs;
+  if (E->hasExplicitTemplateArgumentList()) {
+    TransArgs.setLAngleLoc(E->getLAngleLoc());
+    TransArgs.setRAngleLoc(E->getRAngleLoc());
+    for (unsigned I = 0, N = E->getNumTemplateArgs(); I != N; ++I) {
+      TemplateArgumentLoc Loc;
+      if (getDerived().TransformTemplateArgument(E->getTemplateArgs()[I], Loc))
+        return SemaRef.ExprError();
+      TransArgs.addArgument(Loc);
+    }
+  }
+  
+  // FIXME: Bogus source location for the operator
+  SourceLocation FakeOperatorLoc
+    = SemaRef.PP.getLocForEndOfToken(E->getBase()->getSourceRange().getEnd());
+
+  // FIXME: to do this check properly, we will need to preserve the
+  // first-qualifier-in-scope here, just in case we had a dependent
+  // base (and therefore couldn't do the check) and a
+  // nested-name-qualifier (and therefore could do the lookup).
+  NamedDecl *FirstQualifierInScope = 0;
+
+  return getDerived().RebuildMemberExpr(move(Base), FakeOperatorLoc,
+                                        E->isArrow(),
+                                        Qualifier,
+                                        E->getQualifierRange(),
+                                        E->getMemberLoc(),
+                                        Member,
+                                        (E->hasExplicitTemplateArgumentList()
+                                           ? &TransArgs : 0),
+                                        FirstQualifierInScope);
+}
+
+template<typename Derived>
+Sema::OwningExprResult
+TreeTransform<Derived>::TransformBinaryOperator(BinaryOperator *E) {
+  OwningExprResult LHS = getDerived().TransformExpr(E->getLHS());
+  if (LHS.isInvalid())
+    return SemaRef.ExprError();
+
+  OwningExprResult RHS = getDerived().TransformExpr(E->getRHS());
+  if (RHS.isInvalid())
+    return SemaRef.ExprError();
+
+  if (!getDerived().AlwaysRebuild() &&
+      LHS.get() == E->getLHS() &&
+      RHS.get() == E->getRHS())
+    return SemaRef.Owned(E->Retain());
+
+  return getDerived().RebuildBinaryOperator(E->getOperatorLoc(), E->getOpcode(),
+                                            move(LHS), move(RHS));
+}
+
+template<typename Derived>
+Sema::OwningExprResult
+TreeTransform<Derived>::TransformCompoundAssignOperator(
+                                                      CompoundAssignOperator *E) {
+  return getDerived().TransformBinaryOperator(E);
+}
+
+template<typename Derived>
+Sema::OwningExprResult
+TreeTransform<Derived>::TransformConditionalOperator(ConditionalOperator *E) {
+  OwningExprResult Cond = getDerived().TransformExpr(E->getCond());
+  if (Cond.isInvalid())
+    return SemaRef.ExprError();
+
+  OwningExprResult LHS = getDerived().TransformExpr(E->getLHS());
+  if (LHS.isInvalid())
+    return SemaRef.ExprError();
+
+  OwningExprResult RHS = getDerived().TransformExpr(E->getRHS());
+  if (RHS.isInvalid())
+    return SemaRef.ExprError();
+
+  if (!getDerived().AlwaysRebuild() &&
+      Cond.get() == E->getCond() &&
+      LHS.get() == E->getLHS() &&
+      RHS.get() == E->getRHS())
+    return SemaRef.Owned(E->Retain());
+
+  return getDerived().RebuildConditionalOperator(move(Cond),
+                                                 E->getQuestionLoc(),
+                                                 move(LHS),
+                                                 E->getColonLoc(),
+                                                 move(RHS));
+}
+
+template<typename Derived>
+Sema::OwningExprResult
+TreeTransform<Derived>::TransformImplicitCastExpr(ImplicitCastExpr *E) {
+  // Implicit casts are eliminated during transformation, since they
+  // will be recomputed by semantic analysis after transformation.
+  return getDerived().TransformExpr(E->getSubExprAsWritten());
+}
+
+template<typename Derived>
+Sema::OwningExprResult
+TreeTransform<Derived>::TransformCStyleCastExpr(CStyleCastExpr *E) {
+  TypeSourceInfo *OldT;
+  TypeSourceInfo *NewT;
+  {
+    // FIXME: Source location isn't quite accurate.
+    SourceLocation TypeStartLoc
+      = SemaRef.PP.getLocForEndOfToken(E->getLParenLoc());
+    TemporaryBase Rebase(*this, TypeStartLoc, DeclarationName());
+
+    OldT = E->getTypeInfoAsWritten();
+    NewT = getDerived().TransformType(OldT);
+    if (!NewT)
+      return SemaRef.ExprError();
+  }
+
+  OwningExprResult SubExpr
+    = getDerived().TransformExpr(E->getSubExprAsWritten());
+  if (SubExpr.isInvalid())
+    return SemaRef.ExprError();
+
+  if (!getDerived().AlwaysRebuild() &&
+      OldT == NewT &&
+      SubExpr.get() == E->getSubExpr())
+    return SemaRef.Owned(E->Retain());
+
+  return getDerived().RebuildCStyleCastExpr(E->getLParenLoc(),
+                                            NewT,
+                                            E->getRParenLoc(),
+                                            move(SubExpr));
+}
+
+template<typename Derived>
+Sema::OwningExprResult
+TreeTransform<Derived>::TransformCompoundLiteralExpr(CompoundLiteralExpr *E) {
+  TypeSourceInfo *OldT = E->getTypeSourceInfo();
+  TypeSourceInfo *NewT = getDerived().TransformType(OldT);
+  if (!NewT)
+    return SemaRef.ExprError();
+
+  OwningExprResult Init = getDerived().TransformExpr(E->getInitializer());
+  if (Init.isInvalid())
+    return SemaRef.ExprError();
+
+  if (!getDerived().AlwaysRebuild() &&
+      OldT == NewT &&
+      Init.get() == E->getInitializer())
+    return SemaRef.Owned(E->Retain());
+
+  // Note: the expression type doesn't necessarily match the
+  // type-as-written, but that's okay, because it should always be
+  // derivable from the initializer.
+
+  return getDerived().RebuildCompoundLiteralExpr(E->getLParenLoc(), NewT,
+                                   /*FIXME:*/E->getInitializer()->getLocEnd(),
+                                                 move(Init));
+}
+
+template<typename Derived>
+Sema::OwningExprResult
+TreeTransform<Derived>::TransformExtVectorElementExpr(ExtVectorElementExpr *E) {
+  OwningExprResult Base = getDerived().TransformExpr(E->getBase());
+  if (Base.isInvalid())
+    return SemaRef.ExprError();
+
+  if (!getDerived().AlwaysRebuild() &&
+      Base.get() == E->getBase())
+    return SemaRef.Owned(E->Retain());
+
+  // FIXME: Bad source location
+  SourceLocation FakeOperatorLoc
+    = SemaRef.PP.getLocForEndOfToken(E->getBase()->getLocEnd());
+  return getDerived().RebuildExtVectorElementExpr(move(Base), FakeOperatorLoc,
+                                                  E->getAccessorLoc(),
+                                                  E->getAccessor());
+}
+
+template<typename Derived>
+Sema::OwningExprResult
+TreeTransform<Derived>::TransformInitListExpr(InitListExpr *E) {
+  bool InitChanged = false;
+
+  ASTOwningVector<&ActionBase::DeleteExpr, 4> Inits(SemaRef);
+  for (unsigned I = 0, N = E->getNumInits(); I != N; ++I) {
+    OwningExprResult Init = getDerived().TransformExpr(E->getInit(I));
+    if (Init.isInvalid())
+      return SemaRef.ExprError();
+
+    InitChanged = InitChanged || Init.get() != E->getInit(I);
+    Inits.push_back(Init.takeAs<Expr>());
+  }
+
+  if (!getDerived().AlwaysRebuild() && !InitChanged)
+    return SemaRef.Owned(E->Retain());
+
+  return getDerived().RebuildInitList(E->getLBraceLoc(), move_arg(Inits),
+                                      E->getRBraceLoc(), E->getType());
+}
+
+template<typename Derived>
+Sema::OwningExprResult
+TreeTransform<Derived>::TransformDesignatedInitExpr(DesignatedInitExpr *E) {
+  Designation Desig;
+
+  // transform the initializer value
+  OwningExprResult Init = getDerived().TransformExpr(E->getInit());
+  if (Init.isInvalid())
+    return SemaRef.ExprError();
+
+  // transform the designators.
+  ASTOwningVector<&ActionBase::DeleteExpr, 4> ArrayExprs(SemaRef);
+  bool ExprChanged = false;
+  for (DesignatedInitExpr::designators_iterator D = E->designators_begin(),
+                                             DEnd = E->designators_end();
+       D != DEnd; ++D) {
+    if (D->isFieldDesignator()) {
+      Desig.AddDesignator(Designator::getField(D->getFieldName(),
+                                               D->getDotLoc(),
+                                               D->getFieldLoc()));
+      continue;
+    }
+
+    if (D->isArrayDesignator()) {
+      OwningExprResult Index = getDerived().TransformExpr(E->getArrayIndex(*D));
+      if (Index.isInvalid())
+        return SemaRef.ExprError();
+
+      Desig.AddDesignator(Designator::getArray(Index.get(),
+                                               D->getLBracketLoc()));
+
+      ExprChanged = ExprChanged || Init.get() != E->getArrayIndex(*D);
+      ArrayExprs.push_back(Index.release());
+      continue;
+    }
+
+    assert(D->isArrayRangeDesignator() && "New kind of designator?");
+    OwningExprResult Start
+      = getDerived().TransformExpr(E->getArrayRangeStart(*D));
+    if (Start.isInvalid())
+      return SemaRef.ExprError();
+
+    OwningExprResult End = getDerived().TransformExpr(E->getArrayRangeEnd(*D));
+    if (End.isInvalid())
+      return SemaRef.ExprError();
+
+    Desig.AddDesignator(Designator::getArrayRange(Start.get(),
+                                                  End.get(),
+                                                  D->getLBracketLoc(),
+                                                  D->getEllipsisLoc()));
+
+    ExprChanged = ExprChanged || Start.get() != E->getArrayRangeStart(*D) ||
+      End.get() != E->getArrayRangeEnd(*D);
+
+    ArrayExprs.push_back(Start.release());
+    ArrayExprs.push_back(End.release());
+  }
+
+  if (!getDerived().AlwaysRebuild() &&
+      Init.get() == E->getInit() &&
+      !ExprChanged)
+    return SemaRef.Owned(E->Retain());
+
+  return getDerived().RebuildDesignatedInitExpr(Desig, move_arg(ArrayExprs),
+                                                E->getEqualOrColonLoc(),
+                                                E->usesGNUSyntax(), move(Init));
+}
+
+template<typename Derived>
+Sema::OwningExprResult
+TreeTransform<Derived>::TransformImplicitValueInitExpr(
+                                                     ImplicitValueInitExpr *E) {
+  TemporaryBase Rebase(*this, E->getLocStart(), DeclarationName());
+  
+  // FIXME: Will we ever have proper type location here? Will we actually
+  // need to transform the type?
+  QualType T = getDerived().TransformType(E->getType());
+  if (T.isNull())
+    return SemaRef.ExprError();
+
+  if (!getDerived().AlwaysRebuild() &&
+      T == E->getType())
+    return SemaRef.Owned(E->Retain());
+
+  return getDerived().RebuildImplicitValueInitExpr(T);
+}
+
+template<typename Derived>
+Sema::OwningExprResult
+TreeTransform<Derived>::TransformVAArgExpr(VAArgExpr *E) {
+  // FIXME: Do we want the type as written?
+  QualType T;
+
+  {
+    // FIXME: Source location isn't quite accurate.
+    TemporaryBase Rebase(*this, E->getBuiltinLoc(), DeclarationName());
+    T = getDerived().TransformType(E->getType());
+    if (T.isNull())
+      return SemaRef.ExprError();
+  }
+
+  OwningExprResult SubExpr = getDerived().TransformExpr(E->getSubExpr());
+  if (SubExpr.isInvalid())
+    return SemaRef.ExprError();
+
+  if (!getDerived().AlwaysRebuild() &&
+      T == E->getType() &&
+      SubExpr.get() == E->getSubExpr())
+    return SemaRef.Owned(E->Retain());
+
+  return getDerived().RebuildVAArgExpr(E->getBuiltinLoc(), move(SubExpr),
+                                       T, E->getRParenLoc());
+}
+
+template<typename Derived>
+Sema::OwningExprResult
+TreeTransform<Derived>::TransformParenListExpr(ParenListExpr *E) {
+  bool ArgumentChanged = false;
+  ASTOwningVector<&ActionBase::DeleteExpr, 4> Inits(SemaRef);
+  for (unsigned I = 0, N = E->getNumExprs(); I != N; ++I) {
+    OwningExprResult Init = getDerived().TransformExpr(E->getExpr(I));
+    if (Init.isInvalid())
+      return SemaRef.ExprError();
+
+    ArgumentChanged = ArgumentChanged || Init.get() != E->getExpr(I);
+    Inits.push_back(Init.takeAs<Expr>());
+  }
+
+  return getDerived().RebuildParenListExpr(E->getLParenLoc(),
+                                           move_arg(Inits),
+                                           E->getRParenLoc());
+}
+
+/// \brief Transform an address-of-label expression.
+///
+/// By default, the transformation of an address-of-label expression always
+/// rebuilds the expression, so that the label identifier can be resolved to
+/// the corresponding label statement by semantic analysis.
+template<typename Derived>
+Sema::OwningExprResult
+TreeTransform<Derived>::TransformAddrLabelExpr(AddrLabelExpr *E) {
+  return getDerived().RebuildAddrLabelExpr(E->getAmpAmpLoc(), E->getLabelLoc(),
+                                           E->getLabel());
+}
+
+template<typename Derived>
+Sema::OwningExprResult 
+TreeTransform<Derived>::TransformStmtExpr(StmtExpr *E) {
+  OwningStmtResult SubStmt
+    = getDerived().TransformCompoundStmt(E->getSubStmt(), true);
+  if (SubStmt.isInvalid())
+    return SemaRef.ExprError();
+
+  if (!getDerived().AlwaysRebuild() &&
+      SubStmt.get() == E->getSubStmt())
+    return SemaRef.Owned(E->Retain());
+
+  return getDerived().RebuildStmtExpr(E->getLParenLoc(),
+                                      move(SubStmt),
+                                      E->getRParenLoc());
+}
+
+template<typename Derived>
+Sema::OwningExprResult
+TreeTransform<Derived>::TransformTypesCompatibleExpr(TypesCompatibleExpr *E) {
+  QualType T1, T2;
+  {
+    // FIXME: Source location isn't quite accurate.
+    TemporaryBase Rebase(*this, E->getBuiltinLoc(), DeclarationName());
+
+    T1 = getDerived().TransformType(E->getArgType1());
+    if (T1.isNull())
+      return SemaRef.ExprError();
+
+    T2 = getDerived().TransformType(E->getArgType2());
+    if (T2.isNull())
+      return SemaRef.ExprError();
+  }
+
+  if (!getDerived().AlwaysRebuild() &&
+      T1 == E->getArgType1() &&
+      T2 == E->getArgType2())
+    return SemaRef.Owned(E->Retain());
+
+  return getDerived().RebuildTypesCompatibleExpr(E->getBuiltinLoc(),
+                                                 T1, T2, E->getRParenLoc());
+}
+
+template<typename Derived>
+Sema::OwningExprResult
+TreeTransform<Derived>::TransformChooseExpr(ChooseExpr *E) {
+  OwningExprResult Cond = getDerived().TransformExpr(E->getCond());
+  if (Cond.isInvalid())
+    return SemaRef.ExprError();
+
+  OwningExprResult LHS = getDerived().TransformExpr(E->getLHS());
+  if (LHS.isInvalid())
+    return SemaRef.ExprError();
+
+  OwningExprResult RHS = getDerived().TransformExpr(E->getRHS());
+  if (RHS.isInvalid())
+    return SemaRef.ExprError();
+
+  if (!getDerived().AlwaysRebuild() &&
+      Cond.get() == E->getCond() &&
+      LHS.get() == E->getLHS() &&
+      RHS.get() == E->getRHS())
+    return SemaRef.Owned(E->Retain());
+
+  return getDerived().RebuildChooseExpr(E->getBuiltinLoc(),
+                                        move(Cond), move(LHS), move(RHS),
+                                        E->getRParenLoc());
+}
+
+template<typename Derived>
+Sema::OwningExprResult
+TreeTransform<Derived>::TransformGNUNullExpr(GNUNullExpr *E) {
+  return SemaRef.Owned(E->Retain());
+}
+
+template<typename Derived>
+Sema::OwningExprResult
+TreeTransform<Derived>::TransformCXXOperatorCallExpr(CXXOperatorCallExpr *E) {
+  switch (E->getOperator()) {
+  case OO_New:
+  case OO_Delete:
+  case OO_Array_New:
+  case OO_Array_Delete:
+    llvm_unreachable("new and delete operators cannot use CXXOperatorCallExpr");
+    return SemaRef.ExprError();
+    
+  case OO_Call: {
+    // This is a call to an object's operator().
+    assert(E->getNumArgs() >= 1 && "Object call is missing arguments");
+
+    // Transform the object itself.
+    OwningExprResult Object = getDerived().TransformExpr(E->getArg(0));
+    if (Object.isInvalid())
+      return SemaRef.ExprError();
+
+    // FIXME: Poor location information
+    SourceLocation FakeLParenLoc
+      = SemaRef.PP.getLocForEndOfToken(
+                              static_cast<Expr *>(Object.get())->getLocEnd());
+
+    // Transform the call arguments.
+    ASTOwningVector<&ActionBase::DeleteExpr> Args(SemaRef);
+    llvm::SmallVector<SourceLocation, 4> FakeCommaLocs;
+    for (unsigned I = 1, N = E->getNumArgs(); I != N; ++I) {
+      if (getDerived().DropCallArgument(E->getArg(I)))
+        break;
+      
+      OwningExprResult Arg = getDerived().TransformExpr(E->getArg(I));
+      if (Arg.isInvalid())
+        return SemaRef.ExprError();
+
+      // FIXME: Poor source location information.
+      SourceLocation FakeCommaLoc
+        = SemaRef.PP.getLocForEndOfToken(
+                                 static_cast<Expr *>(Arg.get())->getLocEnd());
+      FakeCommaLocs.push_back(FakeCommaLoc);
+      Args.push_back(Arg.release());
+    }
+
+    return getDerived().RebuildCallExpr(move(Object), FakeLParenLoc,
+                                        move_arg(Args),
+                                        FakeCommaLocs.data(),
+                                        E->getLocEnd());
+  }
+
+#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \
+  case OO_##Name:
+#define OVERLOADED_OPERATOR_MULTI(Name,Spelling,Unary,Binary,MemberOnly)
+#include "clang/Basic/OperatorKinds.def"
+  case OO_Subscript:
+    // Handled below.
+    break;
+
+  case OO_Conditional:
+    llvm_unreachable("conditional operator is not actually overloadable");
+    return SemaRef.ExprError();
+
+  case OO_None:
+  case NUM_OVERLOADED_OPERATORS:
+    llvm_unreachable("not an overloaded operator?");
+    return SemaRef.ExprError();
+  }
+
+  OwningExprResult Callee = getDerived().TransformExpr(E->getCallee());
+  if (Callee.isInvalid())
+    return SemaRef.ExprError();
+
+  OwningExprResult First = getDerived().TransformExpr(E->getArg(0));
+  if (First.isInvalid())
+    return SemaRef.ExprError();
+
+  OwningExprResult Second(SemaRef);
+  if (E->getNumArgs() == 2) {
+    Second = getDerived().TransformExpr(E->getArg(1));
+    if (Second.isInvalid())
+      return SemaRef.ExprError();
+  }
+
+  if (!getDerived().AlwaysRebuild() &&
+      Callee.get() == E->getCallee() &&
+      First.get() == E->getArg(0) &&
+      (E->getNumArgs() != 2 || Second.get() == E->getArg(1)))
+    return SemaRef.Owned(E->Retain());
+
+  return getDerived().RebuildCXXOperatorCallExpr(E->getOperator(),
+                                                 E->getOperatorLoc(),
+                                                 move(Callee),
+                                                 move(First),
+                                                 move(Second));
+}
+
+template<typename Derived>
+Sema::OwningExprResult
+TreeTransform<Derived>::TransformCXXMemberCallExpr(CXXMemberCallExpr *E) {
+  return getDerived().TransformCallExpr(E);
+}
+
+template<typename Derived>
+Sema::OwningExprResult
+TreeTransform<Derived>::TransformCXXNamedCastExpr(CXXNamedCastExpr *E) {
+  TypeSourceInfo *OldT;
+  TypeSourceInfo *NewT;
+  {
+    // FIXME: Source location isn't quite accurate.
+    SourceLocation TypeStartLoc
+      = SemaRef.PP.getLocForEndOfToken(E->getOperatorLoc());
+    TemporaryBase Rebase(*this, TypeStartLoc, DeclarationName());
+
+    OldT = E->getTypeInfoAsWritten();
+    NewT = getDerived().TransformType(OldT);
+    if (!NewT)
+      return SemaRef.ExprError();
+  }
+
+  OwningExprResult SubExpr
+    = getDerived().TransformExpr(E->getSubExprAsWritten());
+  if (SubExpr.isInvalid())
+    return SemaRef.ExprError();
+
+  if (!getDerived().AlwaysRebuild() &&
+      OldT == NewT &&
+      SubExpr.get() == E->getSubExpr())
+    return SemaRef.Owned(E->Retain());
+
+  // FIXME: Poor source location information here.
+  SourceLocation FakeLAngleLoc
+    = SemaRef.PP.getLocForEndOfToken(E->getOperatorLoc());
+  SourceLocation FakeRAngleLoc = E->getSubExpr()->getSourceRange().getBegin();
+  SourceLocation FakeRParenLoc
+    = SemaRef.PP.getLocForEndOfToken(
+                                  E->getSubExpr()->getSourceRange().getEnd());
+  return getDerived().RebuildCXXNamedCastExpr(E->getOperatorLoc(),
+                                              E->getStmtClass(),
+                                              FakeLAngleLoc,
+                                              NewT,
+                                              FakeRAngleLoc,
+                                              FakeRAngleLoc,
+                                              move(SubExpr),
+                                              FakeRParenLoc);
+}
+
+template<typename Derived>
+Sema::OwningExprResult
+TreeTransform<Derived>::TransformCXXStaticCastExpr(CXXStaticCastExpr *E) {
+  return getDerived().TransformCXXNamedCastExpr(E);
+}
+
+template<typename Derived>
+Sema::OwningExprResult
+TreeTransform<Derived>::TransformCXXDynamicCastExpr(CXXDynamicCastExpr *E) {
+  return getDerived().TransformCXXNamedCastExpr(E);
+}
+
+template<typename Derived>
+Sema::OwningExprResult
+TreeTransform<Derived>::TransformCXXReinterpretCastExpr(
+                                                      CXXReinterpretCastExpr *E) {
+  return getDerived().TransformCXXNamedCastExpr(E);
+}
+
+template<typename Derived>
+Sema::OwningExprResult
+TreeTransform<Derived>::TransformCXXConstCastExpr(CXXConstCastExpr *E) {
+  return getDerived().TransformCXXNamedCastExpr(E);
+}
+
+template<typename Derived>
+Sema::OwningExprResult
+TreeTransform<Derived>::TransformCXXFunctionalCastExpr(
+                                                     CXXFunctionalCastExpr *E) {
+  TypeSourceInfo *OldT;
+  TypeSourceInfo *NewT;
+  {
+    TemporaryBase Rebase(*this, E->getTypeBeginLoc(), DeclarationName());
+
+    OldT = E->getTypeInfoAsWritten();
+    NewT = getDerived().TransformType(OldT);
+    if (!NewT)
+      return SemaRef.ExprError();
+  }
+
+  OwningExprResult SubExpr
+    = getDerived().TransformExpr(E->getSubExprAsWritten());
+  if (SubExpr.isInvalid())
+    return SemaRef.ExprError();
+
+  if (!getDerived().AlwaysRebuild() &&
+      OldT == NewT &&
+      SubExpr.get() == E->getSubExpr())
+    return SemaRef.Owned(E->Retain());
+
+  // FIXME: The end of the type's source range is wrong
+  return getDerived().RebuildCXXFunctionalCastExpr(
+                                  /*FIXME:*/SourceRange(E->getTypeBeginLoc()),
+                                                   NewT,
+                                      /*FIXME:*/E->getSubExpr()->getLocStart(),
+                                                   move(SubExpr),
+                                                   E->getRParenLoc());
+}
+
+template<typename Derived>
+Sema::OwningExprResult
+TreeTransform<Derived>::TransformCXXTypeidExpr(CXXTypeidExpr *E) {
+  if (E->isTypeOperand()) {
+    TemporaryBase Rebase(*this, /*FIXME*/E->getLocStart(), DeclarationName());
+
+    QualType T = getDerived().TransformType(E->getTypeOperand());
+    if (T.isNull())
+      return SemaRef.ExprError();
+
+    if (!getDerived().AlwaysRebuild() &&
+        T == E->getTypeOperand())
+      return SemaRef.Owned(E->Retain());
+
+    return getDerived().RebuildCXXTypeidExpr(E->getLocStart(),
+                                             /*FIXME:*/E->getLocStart(),
+                                             T,
+                                             E->getLocEnd());
+  }
+
+  // We don't know whether the expression is potentially evaluated until
+  // after we perform semantic analysis, so the expression is potentially
+  // potentially evaluated.
+  EnterExpressionEvaluationContext Unevaluated(SemaRef,
+                                      Action::PotentiallyPotentiallyEvaluated);
+
+  OwningExprResult SubExpr = getDerived().TransformExpr(E->getExprOperand());
+  if (SubExpr.isInvalid())
+    return SemaRef.ExprError();
+
+  if (!getDerived().AlwaysRebuild() &&
+      SubExpr.get() == E->getExprOperand())
+    return SemaRef.Owned(E->Retain());
+
+  return getDerived().RebuildCXXTypeidExpr(E->getLocStart(),
+                                           /*FIXME:*/E->getLocStart(),
+                                           move(SubExpr),
+                                           E->getLocEnd());
+}
+
+template<typename Derived>
+Sema::OwningExprResult
+TreeTransform<Derived>::TransformCXXBoolLiteralExpr(CXXBoolLiteralExpr *E) {
+  return SemaRef.Owned(E->Retain());
+}
+
+template<typename Derived>
+Sema::OwningExprResult
+TreeTransform<Derived>::TransformCXXNullPtrLiteralExpr(
+                                                     CXXNullPtrLiteralExpr *E) {
+  return SemaRef.Owned(E->Retain());
+}
+
+template<typename Derived>
+Sema::OwningExprResult
+TreeTransform<Derived>::TransformCXXThisExpr(CXXThisExpr *E) {
+  TemporaryBase Rebase(*this, E->getLocStart(), DeclarationName());
+
+  QualType T = getDerived().TransformType(E->getType());
+  if (T.isNull())
+    return SemaRef.ExprError();
+
+  if (!getDerived().AlwaysRebuild() &&
+      T == E->getType())
+    return SemaRef.Owned(E->Retain());
+
+  return getDerived().RebuildCXXThisExpr(E->getLocStart(), T, E->isImplicit());
+}
+
+template<typename Derived>
+Sema::OwningExprResult
+TreeTransform<Derived>::TransformCXXThrowExpr(CXXThrowExpr *E) {
+  OwningExprResult SubExpr = getDerived().TransformExpr(E->getSubExpr());
+  if (SubExpr.isInvalid())
+    return SemaRef.ExprError();
+
+  if (!getDerived().AlwaysRebuild() &&
+      SubExpr.get() == E->getSubExpr())
+    return SemaRef.Owned(E->Retain());
+
+  return getDerived().RebuildCXXThrowExpr(E->getThrowLoc(), move(SubExpr));
+}
+
+template<typename Derived>
+Sema::OwningExprResult
+TreeTransform<Derived>::TransformCXXDefaultArgExpr(CXXDefaultArgExpr *E) {
+  ParmVarDecl *Param
+    = cast_or_null<ParmVarDecl>(getDerived().TransformDecl(E->getParam()));
+  if (!Param)
+    return SemaRef.ExprError();
+
+  if (!getDerived().AlwaysRebuild() &&
+      Param == E->getParam())
+    return SemaRef.Owned(E->Retain());
+
+  return getDerived().RebuildCXXDefaultArgExpr(E->getUsedLocation(), Param);
+}
+
+template<typename Derived>
+Sema::OwningExprResult
+TreeTransform<Derived>::TransformCXXZeroInitValueExpr(CXXZeroInitValueExpr *E) {
+  TemporaryBase Rebase(*this, E->getTypeBeginLoc(), DeclarationName());
+
+  QualType T = getDerived().TransformType(E->getType());
+  if (T.isNull())
+    return SemaRef.ExprError();
+
+  if (!getDerived().AlwaysRebuild() &&
+      T == E->getType())
+    return SemaRef.Owned(E->Retain());
+
+  return getDerived().RebuildCXXZeroInitValueExpr(E->getTypeBeginLoc(),
+                                                /*FIXME:*/E->getTypeBeginLoc(),
+                                                  T,
+                                                  E->getRParenLoc());
+}
+
+template<typename Derived>
+Sema::OwningExprResult
+TreeTransform<Derived>::TransformCXXNewExpr(CXXNewExpr *E) {
+  // Transform the type that we're allocating
+  TemporaryBase Rebase(*this, E->getLocStart(), DeclarationName());
+  QualType AllocType = getDerived().TransformType(E->getAllocatedType());
+  if (AllocType.isNull())
+    return SemaRef.ExprError();
+
+  // Transform the size of the array we're allocating (if any).
+  OwningExprResult ArraySize = getDerived().TransformExpr(E->getArraySize());
+  if (ArraySize.isInvalid())
+    return SemaRef.ExprError();
+
+  // Transform the placement arguments (if any).
+  bool ArgumentChanged = false;
+  ASTOwningVector<&ActionBase::DeleteExpr> PlacementArgs(SemaRef);
+  for (unsigned I = 0, N = E->getNumPlacementArgs(); I != N; ++I) {
+    OwningExprResult Arg = getDerived().TransformExpr(E->getPlacementArg(I));
+    if (Arg.isInvalid())
+      return SemaRef.ExprError();
+
+    ArgumentChanged = ArgumentChanged || Arg.get() != E->getPlacementArg(I);
+    PlacementArgs.push_back(Arg.take());
+  }
+
+  // transform the constructor arguments (if any).
+  ASTOwningVector<&ActionBase::DeleteExpr> ConstructorArgs(SemaRef);
+  for (unsigned I = 0, N = E->getNumConstructorArgs(); I != N; ++I) {
+    OwningExprResult Arg = getDerived().TransformExpr(E->getConstructorArg(I));
+    if (Arg.isInvalid())
+      return SemaRef.ExprError();
+
+    ArgumentChanged = ArgumentChanged || Arg.get() != E->getConstructorArg(I);
+    ConstructorArgs.push_back(Arg.take());
+  }
+
+  if (!getDerived().AlwaysRebuild() &&
+      AllocType == E->getAllocatedType() &&
+      ArraySize.get() == E->getArraySize() &&
+      !ArgumentChanged)
+    return SemaRef.Owned(E->Retain());
+
+  if (!ArraySize.get()) {
+    // If no array size was specified, but the new expression was
+    // instantiated with an array type (e.g., "new T" where T is
+    // instantiated with "int[4]"), extract the outer bound from the
+    // array type as our array size. We do this with constant and
+    // dependently-sized array types.
+    const ArrayType *ArrayT = SemaRef.Context.getAsArrayType(AllocType);
+    if (!ArrayT) {
+      // Do nothing
+    } else if (const ConstantArrayType *ConsArrayT
+                                     = dyn_cast<ConstantArrayType>(ArrayT)) {
+      ArraySize 
+        = SemaRef.Owned(new (SemaRef.Context) IntegerLiteral(
+                                                  ConsArrayT->getSize(), 
+                                                  SemaRef.Context.getSizeType(),
+                                                  /*FIXME:*/E->getLocStart()));
+      AllocType = ConsArrayT->getElementType();
+    } else if (const DependentSizedArrayType *DepArrayT
+                              = dyn_cast<DependentSizedArrayType>(ArrayT)) {
+      if (DepArrayT->getSizeExpr()) {
+        ArraySize = SemaRef.Owned(DepArrayT->getSizeExpr()->Retain());
+        AllocType = DepArrayT->getElementType();
+      }
+    }
+  }
+  return getDerived().RebuildCXXNewExpr(E->getLocStart(),
+                                        E->isGlobalNew(),
+                                        /*FIXME:*/E->getLocStart(),
+                                        move_arg(PlacementArgs),
+                                        /*FIXME:*/E->getLocStart(),
+                                        E->isParenTypeId(),
+                                        AllocType,
+                                        /*FIXME:*/E->getLocStart(),
+                                        /*FIXME:*/SourceRange(),
+                                        move(ArraySize),
+                                        /*FIXME:*/E->getLocStart(),
+                                        move_arg(ConstructorArgs),
+                                        E->getLocEnd());
+}
+
+template<typename Derived>
+Sema::OwningExprResult
+TreeTransform<Derived>::TransformCXXDeleteExpr(CXXDeleteExpr *E) {
+  OwningExprResult Operand = getDerived().TransformExpr(E->getArgument());
+  if (Operand.isInvalid())
+    return SemaRef.ExprError();
+
+  if (!getDerived().AlwaysRebuild() &&
+      Operand.get() == E->getArgument())
+    return SemaRef.Owned(E->Retain());
+
+  return getDerived().RebuildCXXDeleteExpr(E->getLocStart(),
+                                           E->isGlobalDelete(),
+                                           E->isArrayForm(),
+                                           move(Operand));
+}
+
+template<typename Derived>
+Sema::OwningExprResult
+TreeTransform<Derived>::TransformCXXPseudoDestructorExpr(
+                                                     CXXPseudoDestructorExpr *E) {
+  OwningExprResult Base = getDerived().TransformExpr(E->getBase());
+  if (Base.isInvalid())
+    return SemaRef.ExprError();
+
+  NestedNameSpecifier *Qualifier
+    = getDerived().TransformNestedNameSpecifier(E->getQualifier(),
+                                                E->getQualifierRange());
+  if (E->getQualifier() && !Qualifier)
+    return SemaRef.ExprError();
+
+  QualType DestroyedType;
+  {
+    TemporaryBase Rebase(*this, E->getDestroyedTypeLoc(), DeclarationName());
+    DestroyedType = getDerived().TransformType(E->getDestroyedType());
+    if (DestroyedType.isNull())
+      return SemaRef.ExprError();
+  }
+
+  if (!getDerived().AlwaysRebuild() &&
+      Base.get() == E->getBase() &&
+      Qualifier == E->getQualifier() &&
+      DestroyedType == E->getDestroyedType())
+    return SemaRef.Owned(E->Retain());
+
+  return getDerived().RebuildCXXPseudoDestructorExpr(move(Base),
+                                                     E->getOperatorLoc(),
+                                                     E->isArrow(),
+                                                     E->getDestroyedTypeLoc(),
+                                                     DestroyedType,
+                                                     Qualifier,
+                                                     E->getQualifierRange());
+}
+
+template<typename Derived>
+Sema::OwningExprResult
+TreeTransform<Derived>::TransformUnresolvedLookupExpr(
+                                                  UnresolvedLookupExpr *Old) {
+  TemporaryBase Rebase(*this, Old->getNameLoc(), DeclarationName());
+
+  LookupResult R(SemaRef, Old->getName(), Old->getNameLoc(),
+                 Sema::LookupOrdinaryName);
+
+  // Transform all the decls.
+  for (UnresolvedLookupExpr::decls_iterator I = Old->decls_begin(),
+         E = Old->decls_end(); I != E; ++I) {
+    NamedDecl *InstD = static_cast<NamedDecl*>(getDerived().TransformDecl(*I));
+    if (!InstD) {
+      // Silently ignore these if a UsingShadowDecl instantiated to nothing.
+      // This can happen because of dependent hiding.
+      if (isa<UsingShadowDecl>(*I))
+        continue;
+      else
+        return SemaRef.ExprError();
+    }
+
+    // Expand using declarations.
+    if (isa<UsingDecl>(InstD)) {
+      UsingDecl *UD = cast<UsingDecl>(InstD);
+      for (UsingDecl::shadow_iterator I = UD->shadow_begin(),
+             E = UD->shadow_end(); I != E; ++I)
+        R.addDecl(*I);
+      continue;
+    }
+
+    R.addDecl(InstD);
+  }
+
+  // Resolve a kind, but don't do any further analysis.  If it's
+  // ambiguous, the callee needs to deal with it.
+  R.resolveKind();
+
+  // Rebuild the nested-name qualifier, if present.
+  CXXScopeSpec SS;
+  NestedNameSpecifier *Qualifier = 0;
+  if (Old->getQualifier()) {
+    Qualifier = getDerived().TransformNestedNameSpecifier(Old->getQualifier(),
+                                                    Old->getQualifierRange());
+    if (!Qualifier)
+      return SemaRef.ExprError();
+    
+    SS.setScopeRep(Qualifier);
+    SS.setRange(Old->getQualifierRange());
+  }
+
+  // If we have no template arguments, it's a normal declaration name.
+  if (!Old->hasExplicitTemplateArgs())
+    return getDerived().RebuildDeclarationNameExpr(SS, R, Old->requiresADL());
+
+  // If we have template arguments, rebuild them, then rebuild the
+  // templateid expression.
+  TemplateArgumentListInfo TransArgs(Old->getLAngleLoc(), Old->getRAngleLoc());
+  for (unsigned I = 0, N = Old->getNumTemplateArgs(); I != N; ++I) {
+    TemplateArgumentLoc Loc;
+    if (getDerived().TransformTemplateArgument(Old->getTemplateArgs()[I], Loc))
+      return SemaRef.ExprError();
+    TransArgs.addArgument(Loc);
+  }
+
+  return getDerived().RebuildTemplateIdExpr(SS, R, Old->requiresADL(),
+                                            TransArgs);
+}
+
+template<typename Derived>
+Sema::OwningExprResult
+TreeTransform<Derived>::TransformUnaryTypeTraitExpr(UnaryTypeTraitExpr *E) {
+  TemporaryBase Rebase(*this, /*FIXME*/E->getLocStart(), DeclarationName());
+
+  QualType T = getDerived().TransformType(E->getQueriedType());
+  if (T.isNull())
+    return SemaRef.ExprError();
+
+  if (!getDerived().AlwaysRebuild() &&
+      T == E->getQueriedType())
+    return SemaRef.Owned(E->Retain());
+
+  // FIXME: Bad location information
+  SourceLocation FakeLParenLoc
+    = SemaRef.PP.getLocForEndOfToken(E->getLocStart());
+
+  return getDerived().RebuildUnaryTypeTrait(E->getTrait(),
+                                            E->getLocStart(),
+                                            /*FIXME:*/FakeLParenLoc,
+                                            T,
+                                            E->getLocEnd());
+}
+
+template<typename Derived>
+Sema::OwningExprResult
+TreeTransform<Derived>::TransformDependentScopeDeclRefExpr(
+                                                  DependentScopeDeclRefExpr *E) {
+  NestedNameSpecifier *NNS
+    = getDerived().TransformNestedNameSpecifier(E->getQualifier(),
+                                                E->getQualifierRange());
+  if (!NNS)
+    return SemaRef.ExprError();
+
+  DeclarationName Name
+    = getDerived().TransformDeclarationName(E->getDeclName(), E->getLocation());
+  if (!Name)
+    return SemaRef.ExprError();
+
+  if (!E->hasExplicitTemplateArgs()) {
+    if (!getDerived().AlwaysRebuild() &&
+        NNS == E->getQualifier() &&
+        Name == E->getDeclName())
+      return SemaRef.Owned(E->Retain());
+
+    return getDerived().RebuildDependentScopeDeclRefExpr(NNS,
+                                                         E->getQualifierRange(),
+                                                         Name, E->getLocation(),
+                                                         /*TemplateArgs*/ 0);
+  }
+
+  TemplateArgumentListInfo TransArgs(E->getLAngleLoc(), E->getRAngleLoc());
+  for (unsigned I = 0, N = E->getNumTemplateArgs(); I != N; ++I) {
+    TemplateArgumentLoc Loc;
+    if (getDerived().TransformTemplateArgument(E->getTemplateArgs()[I], Loc))
+      return SemaRef.ExprError();
+    TransArgs.addArgument(Loc);
+  }
+
+  return getDerived().RebuildDependentScopeDeclRefExpr(NNS,
+                                                       E->getQualifierRange(),
+                                                       Name, E->getLocation(),
+                                                       &TransArgs);
+}
+
+template<typename Derived>
+Sema::OwningExprResult
+TreeTransform<Derived>::TransformCXXConstructExpr(CXXConstructExpr *E) {
+  // CXXConstructExprs are always implicit, so when we have a
+  // 1-argument construction we just transform that argument.
+  if (E->getNumArgs() == 1 ||
+      (E->getNumArgs() > 1 && getDerived().DropCallArgument(E->getArg(1))))
+    return getDerived().TransformExpr(E->getArg(0));
+
+  TemporaryBase Rebase(*this, /*FIXME*/E->getLocStart(), DeclarationName());
+
+  QualType T = getDerived().TransformType(E->getType());
+  if (T.isNull())
+    return SemaRef.ExprError();
+
+  CXXConstructorDecl *Constructor
+    = cast_or_null<CXXConstructorDecl>(
+                              getDerived().TransformDecl(E->getConstructor()));
+  if (!Constructor)
+    return SemaRef.ExprError();
+
+  bool ArgumentChanged = false;
+  ASTOwningVector<&ActionBase::DeleteExpr> Args(SemaRef);
+  for (CXXConstructExpr::arg_iterator Arg = E->arg_begin(),
+       ArgEnd = E->arg_end();
+       Arg != ArgEnd; ++Arg) {
+    if (getDerived().DropCallArgument(*Arg)) {
+      ArgumentChanged = true;
+      break;
+    }
+
+    OwningExprResult TransArg = getDerived().TransformExpr(*Arg);
+    if (TransArg.isInvalid())
+      return SemaRef.ExprError();
+
+    ArgumentChanged = ArgumentChanged || TransArg.get() != *Arg;
+    Args.push_back(TransArg.takeAs<Expr>());
+  }
+
+  if (!getDerived().AlwaysRebuild() &&
+      T == E->getType() &&
+      Constructor == E->getConstructor() &&
+      !ArgumentChanged)
+    return SemaRef.Owned(E->Retain());
+
+  return getDerived().RebuildCXXConstructExpr(T, /*FIXME:*/E->getLocStart(),
+                                              Constructor, E->isElidable(),
+                                              move_arg(Args));
+}
+
+/// \brief Transform a C++ temporary-binding expression.
+///
+/// Since CXXBindTemporaryExpr nodes are implicitly generated, we just
+/// transform the subexpression and return that.
+template<typename Derived>
+Sema::OwningExprResult
+TreeTransform<Derived>::TransformCXXBindTemporaryExpr(CXXBindTemporaryExpr *E) {
+  return getDerived().TransformExpr(E->getSubExpr());
+}
+
+/// \brief Transform a C++ reference-binding expression.
+///
+/// Since CXXBindReferenceExpr nodes are implicitly generated, we just
+/// transform the subexpression and return that.
+template<typename Derived>
+Sema::OwningExprResult
+TreeTransform<Derived>::TransformCXXBindReferenceExpr(CXXBindReferenceExpr *E) {
+  return getDerived().TransformExpr(E->getSubExpr());
+}
+
+/// \brief Transform a C++ expression that contains temporaries that should
+/// be destroyed after the expression is evaluated.
+///
+/// Since CXXExprWithTemporaries nodes are implicitly generated, we
+/// just transform the subexpression and return that.
+template<typename Derived>
+Sema::OwningExprResult
+TreeTransform<Derived>::TransformCXXExprWithTemporaries(
+                                                    CXXExprWithTemporaries *E) {
+  return getDerived().TransformExpr(E->getSubExpr());
+}
+
+template<typename Derived>
+Sema::OwningExprResult
+TreeTransform<Derived>::TransformCXXTemporaryObjectExpr(
+                                                      CXXTemporaryObjectExpr *E) {
+  TemporaryBase Rebase(*this, E->getTypeBeginLoc(), DeclarationName());
+  QualType T = getDerived().TransformType(E->getType());
+  if (T.isNull())
+    return SemaRef.ExprError();
+
+  CXXConstructorDecl *Constructor
+    = cast_or_null<CXXConstructorDecl>(
+                            getDerived().TransformDecl(E->getConstructor()));
+  if (!Constructor)
+    return SemaRef.ExprError();
+
+  bool ArgumentChanged = false;
+  ASTOwningVector<&ActionBase::DeleteExpr> Args(SemaRef);
+  Args.reserve(E->getNumArgs());
+  for (CXXTemporaryObjectExpr::arg_iterator Arg = E->arg_begin(),
+                                         ArgEnd = E->arg_end();
+       Arg != ArgEnd; ++Arg) {
+    OwningExprResult TransArg = getDerived().TransformExpr(*Arg);
+    if (TransArg.isInvalid())
+      return SemaRef.ExprError();
+
+    ArgumentChanged = ArgumentChanged || TransArg.get() != *Arg;
+    Args.push_back((Expr *)TransArg.release());
+  }
+
+  if (!getDerived().AlwaysRebuild() &&
+      T == E->getType() &&
+      Constructor == E->getConstructor() &&
+      !ArgumentChanged)
+    return SemaRef.Owned(E->Retain());
+
+  // FIXME: Bogus location information
+  SourceLocation CommaLoc;
+  if (Args.size() > 1) {
+    Expr *First = (Expr *)Args[0];
+    CommaLoc
+      = SemaRef.PP.getLocForEndOfToken(First->getSourceRange().getEnd());
+  }
+  return getDerived().RebuildCXXTemporaryObjectExpr(E->getTypeBeginLoc(),
+                                                    T,
+                                                /*FIXME:*/E->getTypeBeginLoc(),
+                                                    move_arg(Args),
+                                                    &CommaLoc,
+                                                    E->getLocEnd());
+}
+
+template<typename Derived>
+Sema::OwningExprResult
+TreeTransform<Derived>::TransformCXXUnresolvedConstructExpr(
+                                                  CXXUnresolvedConstructExpr *E) {
+  TemporaryBase Rebase(*this, E->getTypeBeginLoc(), DeclarationName());
+  QualType T = getDerived().TransformType(E->getTypeAsWritten());
+  if (T.isNull())
+    return SemaRef.ExprError();
+
+  bool ArgumentChanged = false;
+  ASTOwningVector<&ActionBase::DeleteExpr> Args(SemaRef);
+  llvm::SmallVector<SourceLocation, 8> FakeCommaLocs;
+  for (CXXUnresolvedConstructExpr::arg_iterator Arg = E->arg_begin(),
+                                             ArgEnd = E->arg_end();
+       Arg != ArgEnd; ++Arg) {
+    OwningExprResult TransArg = getDerived().TransformExpr(*Arg);
+    if (TransArg.isInvalid())
+      return SemaRef.ExprError();
+
+    ArgumentChanged = ArgumentChanged || TransArg.get() != *Arg;
+    FakeCommaLocs.push_back(
+                        SemaRef.PP.getLocForEndOfToken((*Arg)->getLocEnd()));
+    Args.push_back(TransArg.takeAs<Expr>());
+  }
+
+  if (!getDerived().AlwaysRebuild() &&
+      T == E->getTypeAsWritten() &&
+      !ArgumentChanged)
+    return SemaRef.Owned(E->Retain());
+
+  // FIXME: we're faking the locations of the commas
+  return getDerived().RebuildCXXUnresolvedConstructExpr(E->getTypeBeginLoc(),
+                                                        T,
+                                                        E->getLParenLoc(),
+                                                        move_arg(Args),
+                                                        FakeCommaLocs.data(),
+                                                        E->getRParenLoc());
+}
+
+template<typename Derived>
+Sema::OwningExprResult
+TreeTransform<Derived>::TransformCXXDependentScopeMemberExpr(
+                                                     CXXDependentScopeMemberExpr *E) {
+  // Transform the base of the expression.
+  OwningExprResult Base(SemaRef, (Expr*) 0);
+  Expr *OldBase;
+  QualType BaseType;
+  QualType ObjectType;
+  if (!E->isImplicitAccess()) {
+    OldBase = E->getBase();
+    Base = getDerived().TransformExpr(OldBase);
+    if (Base.isInvalid())
+      return SemaRef.ExprError();
+
+    // Start the member reference and compute the object's type.
+    Sema::TypeTy *ObjectTy = 0;
+    Base = SemaRef.ActOnStartCXXMemberReference(0, move(Base),
+                                                E->getOperatorLoc(),
+                                      E->isArrow()? tok::arrow : tok::period,
+                                                ObjectTy);
+    if (Base.isInvalid())
+      return SemaRef.ExprError();
+
+    ObjectType = QualType::getFromOpaquePtr(ObjectTy);
+    BaseType = ((Expr*) Base.get())->getType();
+  } else {
+    OldBase = 0;
+    BaseType = getDerived().TransformType(E->getBaseType());
+    ObjectType = BaseType->getAs<PointerType>()->getPointeeType();
+  }
+
+  // Transform the first part of the nested-name-specifier that qualifies
+  // the member name.
+  NamedDecl *FirstQualifierInScope
+    = getDerived().TransformFirstQualifierInScope(
+                                          E->getFirstQualifierFoundInScope(),
+                                          E->getQualifierRange().getBegin());
+
+  NestedNameSpecifier *Qualifier = 0;
+  if (E->getQualifier()) {
+    Qualifier = getDerived().TransformNestedNameSpecifier(E->getQualifier(),
+                                                      E->getQualifierRange(),
+                                                      ObjectType,
+                                                      FirstQualifierInScope);
+    if (!Qualifier)
+      return SemaRef.ExprError();
+  }
+
+  DeclarationName Name
+    = getDerived().TransformDeclarationName(E->getMember(), E->getMemberLoc(),
+                                            ObjectType);
+  if (!Name)
+    return SemaRef.ExprError();
+
+  if (!E->hasExplicitTemplateArgs()) {
+    // This is a reference to a member without an explicitly-specified
+    // template argument list. Optimize for this common case.
+    if (!getDerived().AlwaysRebuild() &&
+        Base.get() == OldBase &&
+        BaseType == E->getBaseType() &&
+        Qualifier == E->getQualifier() &&
+        Name == E->getMember() &&
+        FirstQualifierInScope == E->getFirstQualifierFoundInScope())
+      return SemaRef.Owned(E->Retain());
+
+    return getDerived().RebuildCXXDependentScopeMemberExpr(move(Base),
+                                                       BaseType,
+                                                       E->isArrow(),
+                                                       E->getOperatorLoc(),
+                                                       Qualifier,
+                                                       E->getQualifierRange(),
+                                                       FirstQualifierInScope,
+                                                       Name,
+                                                       E->getMemberLoc(),
+                                                       /*TemplateArgs*/ 0);
+  }
+
+  TemplateArgumentListInfo TransArgs(E->getLAngleLoc(), E->getRAngleLoc());
+  for (unsigned I = 0, N = E->getNumTemplateArgs(); I != N; ++I) {
+    TemplateArgumentLoc Loc;
+    if (getDerived().TransformTemplateArgument(E->getTemplateArgs()[I], Loc))
+      return SemaRef.ExprError();
+    TransArgs.addArgument(Loc);
+  }
+
+  return getDerived().RebuildCXXDependentScopeMemberExpr(move(Base),
+                                                     BaseType,
+                                                     E->isArrow(),
+                                                     E->getOperatorLoc(),
+                                                     Qualifier,
+                                                     E->getQualifierRange(),
+                                                     FirstQualifierInScope,
+                                                     Name,
+                                                     E->getMemberLoc(),
+                                                     &TransArgs);
+}
+
+template<typename Derived>
+Sema::OwningExprResult
+TreeTransform<Derived>::TransformUnresolvedMemberExpr(UnresolvedMemberExpr *Old) {
+  // Transform the base of the expression.
+  OwningExprResult Base(SemaRef, (Expr*) 0);
+  QualType BaseType;
+  if (!Old->isImplicitAccess()) {
+    Base = getDerived().TransformExpr(Old->getBase());
+    if (Base.isInvalid())
+      return SemaRef.ExprError();
+    BaseType = ((Expr*) Base.get())->getType();
+  } else {
+    BaseType = getDerived().TransformType(Old->getBaseType());
+  }
+
+  NestedNameSpecifier *Qualifier = 0;
+  if (Old->getQualifier()) {
+    Qualifier
+      = getDerived().TransformNestedNameSpecifier(Old->getQualifier(),
+                                                  Old->getQualifierRange());
+    if (Qualifier == 0)
+      return SemaRef.ExprError();
+  }
+
+  LookupResult R(SemaRef, Old->getMemberName(), Old->getMemberLoc(),
+                 Sema::LookupOrdinaryName);
+
+  // Transform all the decls.
+  for (UnresolvedMemberExpr::decls_iterator I = Old->decls_begin(),
+         E = Old->decls_end(); I != E; ++I) {
+    NamedDecl *InstD = static_cast<NamedDecl*>(getDerived().TransformDecl(*I));
+    if (!InstD) {
+      // Silently ignore these if a UsingShadowDecl instantiated to nothing.
+      // This can happen because of dependent hiding.
+      if (isa<UsingShadowDecl>(*I))
+        continue;
+      else
+        return SemaRef.ExprError();
+    }
+
+    // Expand using declarations.
+    if (isa<UsingDecl>(InstD)) {
+      UsingDecl *UD = cast<UsingDecl>(InstD);
+      for (UsingDecl::shadow_iterator I = UD->shadow_begin(),
+             E = UD->shadow_end(); I != E; ++I)
+        R.addDecl(*I);
+      continue;
+    }
+
+    R.addDecl(InstD);
+  }
+
+  R.resolveKind();
+
+  TemplateArgumentListInfo TransArgs;
+  if (Old->hasExplicitTemplateArgs()) {
+    TransArgs.setLAngleLoc(Old->getLAngleLoc());
+    TransArgs.setRAngleLoc(Old->getRAngleLoc());
+    for (unsigned I = 0, N = Old->getNumTemplateArgs(); I != N; ++I) {
+      TemplateArgumentLoc Loc;
+      if (getDerived().TransformTemplateArgument(Old->getTemplateArgs()[I],
+                                                 Loc))
+        return SemaRef.ExprError();
+      TransArgs.addArgument(Loc);
+    }
+  }
+
+  // FIXME: to do this check properly, we will need to preserve the
+  // first-qualifier-in-scope here, just in case we had a dependent
+  // base (and therefore couldn't do the check) and a
+  // nested-name-qualifier (and therefore could do the lookup).
+  NamedDecl *FirstQualifierInScope = 0;
+  
+  return getDerived().RebuildUnresolvedMemberExpr(move(Base),
+                                                  BaseType,
+                                                  Old->getOperatorLoc(),
+                                                  Old->isArrow(),
+                                                  Qualifier,
+                                                  Old->getQualifierRange(),
+                                                  FirstQualifierInScope,
+                                                  R,
+                                              (Old->hasExplicitTemplateArgs()
+                                                  ? &TransArgs : 0));
+}
+
+template<typename Derived>
+Sema::OwningExprResult
+TreeTransform<Derived>::TransformObjCStringLiteral(ObjCStringLiteral *E) {
+  return SemaRef.Owned(E->Retain());
+}
+
+template<typename Derived>
+Sema::OwningExprResult
+TreeTransform<Derived>::TransformObjCEncodeExpr(ObjCEncodeExpr *E) {
+  // FIXME: poor source location
+  TemporaryBase Rebase(*this, E->getAtLoc(), DeclarationName());
+  QualType EncodedType = getDerived().TransformType(E->getEncodedType());
+  if (EncodedType.isNull())
+    return SemaRef.ExprError();
+
+  if (!getDerived().AlwaysRebuild() &&
+      EncodedType == E->getEncodedType())
+    return SemaRef.Owned(E->Retain());
+
+  return getDerived().RebuildObjCEncodeExpr(E->getAtLoc(),
+                                            EncodedType,
+                                            E->getRParenLoc());
+}
+
+template<typename Derived>
+Sema::OwningExprResult
+TreeTransform<Derived>::TransformObjCMessageExpr(ObjCMessageExpr *E) {
+  // FIXME: Implement this!
+  assert(false && "Cannot transform Objective-C expressions yet");
+  return SemaRef.Owned(E->Retain());
+}
+
+template<typename Derived>
+Sema::OwningExprResult
+TreeTransform<Derived>::TransformObjCSelectorExpr(ObjCSelectorExpr *E) {
+  return SemaRef.Owned(E->Retain());
+}
+
+template<typename Derived>
+Sema::OwningExprResult
+TreeTransform<Derived>::TransformObjCProtocolExpr(ObjCProtocolExpr *E) {
+  ObjCProtocolDecl *Protocol
+    = cast_or_null<ObjCProtocolDecl>(
+                                getDerived().TransformDecl(E->getProtocol()));
+  if (!Protocol)
+    return SemaRef.ExprError();
+
+  if (!getDerived().AlwaysRebuild() &&
+      Protocol == E->getProtocol())
+    return SemaRef.Owned(E->Retain());
+
+  return getDerived().RebuildObjCProtocolExpr(Protocol,
+                                              E->getAtLoc(),
+                                              /*FIXME:*/E->getAtLoc(),
+                                              /*FIXME:*/E->getAtLoc(),
+                                              E->getRParenLoc());
+
+}
+
+template<typename Derived>
+Sema::OwningExprResult
+TreeTransform<Derived>::TransformObjCIvarRefExpr(ObjCIvarRefExpr *E) {
+  // FIXME: Implement this!
+  assert(false && "Cannot transform Objective-C expressions yet");
+  return SemaRef.Owned(E->Retain());
+}
+
+template<typename Derived>
+Sema::OwningExprResult
+TreeTransform<Derived>::TransformObjCPropertyRefExpr(ObjCPropertyRefExpr *E) {
+  // FIXME: Implement this!
+  assert(false && "Cannot transform Objective-C expressions yet");
+  return SemaRef.Owned(E->Retain());
+}
+
+template<typename Derived>
+Sema::OwningExprResult
+TreeTransform<Derived>::TransformObjCImplicitSetterGetterRefExpr(
+                                          ObjCImplicitSetterGetterRefExpr *E) {
+  // FIXME: Implement this!
+  assert(false && "Cannot transform Objective-C expressions yet");
+  return SemaRef.Owned(E->Retain());
+}
+
+template<typename Derived>
+Sema::OwningExprResult
+TreeTransform<Derived>::TransformObjCSuperExpr(ObjCSuperExpr *E) {
+  // FIXME: Implement this!
+  assert(false && "Cannot transform Objective-C expressions yet");
+  return SemaRef.Owned(E->Retain());
+}
+
+template<typename Derived>
+Sema::OwningExprResult
+TreeTransform<Derived>::TransformObjCIsaExpr(ObjCIsaExpr *E) {
+  // FIXME: Implement this!
+  assert(false && "Cannot transform Objective-C expressions yet");
+  return SemaRef.Owned(E->Retain());
+}
+
+template<typename Derived>
+Sema::OwningExprResult
+TreeTransform<Derived>::TransformShuffleVectorExpr(ShuffleVectorExpr *E) {
+  bool ArgumentChanged = false;
+  ASTOwningVector<&ActionBase::DeleteExpr> SubExprs(SemaRef);
+  for (unsigned I = 0, N = E->getNumSubExprs(); I != N; ++I) {
+    OwningExprResult SubExpr = getDerived().TransformExpr(E->getExpr(I));
+    if (SubExpr.isInvalid())
+      return SemaRef.ExprError();
+
+    ArgumentChanged = ArgumentChanged || SubExpr.get() != E->getExpr(I);
+    SubExprs.push_back(SubExpr.takeAs<Expr>());
+  }
+
+  if (!getDerived().AlwaysRebuild() &&
+      !ArgumentChanged)
+    return SemaRef.Owned(E->Retain());
+
+  return getDerived().RebuildShuffleVectorExpr(E->getBuiltinLoc(),
+                                               move_arg(SubExprs),
+                                               E->getRParenLoc());
+}
+
+template<typename Derived>
+Sema::OwningExprResult
+TreeTransform<Derived>::TransformBlockExpr(BlockExpr *E) {
+  // FIXME: Implement this!
+  assert(false && "Cannot transform block expressions yet");
+  return SemaRef.Owned(E->Retain());
+}
+
+template<typename Derived>
+Sema::OwningExprResult
+TreeTransform<Derived>::TransformBlockDeclRefExpr(BlockDeclRefExpr *E) {
+  // FIXME: Implement this!
+  assert(false && "Cannot transform block-related expressions yet");
+  return SemaRef.Owned(E->Retain());
+}
+
+//===----------------------------------------------------------------------===//
+// Type reconstruction
+//===----------------------------------------------------------------------===//
+
+template<typename Derived>
+QualType TreeTransform<Derived>::RebuildPointerType(QualType PointeeType,
+                                                    SourceLocation Star) {
+  return SemaRef.BuildPointerType(PointeeType, Qualifiers(), Star,
+                                  getDerived().getBaseEntity());
+}
+
+template<typename Derived>
+QualType TreeTransform<Derived>::RebuildBlockPointerType(QualType PointeeType,
+                                                         SourceLocation Star) {
+  return SemaRef.BuildBlockPointerType(PointeeType, Qualifiers(), Star,
+                                       getDerived().getBaseEntity());
+}
+
+template<typename Derived>
+QualType
+TreeTransform<Derived>::RebuildReferenceType(QualType ReferentType,
+                                             bool WrittenAsLValue,
+                                             SourceLocation Sigil) {
+  return SemaRef.BuildReferenceType(ReferentType, WrittenAsLValue, Qualifiers(),
+                                    Sigil, getDerived().getBaseEntity());
+}
+
+template<typename Derived>
+QualType
+TreeTransform<Derived>::RebuildMemberPointerType(QualType PointeeType,
+                                                 QualType ClassType,
+                                                 SourceLocation Sigil) {
+  return SemaRef.BuildMemberPointerType(PointeeType, ClassType, Qualifiers(),
+                                        Sigil, getDerived().getBaseEntity());
+}
+
+template<typename Derived>
+QualType
+TreeTransform<Derived>::RebuildObjCObjectPointerType(QualType PointeeType,
+                                                     SourceLocation Sigil) {
+  return SemaRef.BuildPointerType(PointeeType, Qualifiers(), Sigil,
+                                  getDerived().getBaseEntity());
+}
+
+template<typename Derived>
+QualType
+TreeTransform<Derived>::RebuildArrayType(QualType ElementType,
+                                         ArrayType::ArraySizeModifier SizeMod,
+                                         const llvm::APInt *Size,
+                                         Expr *SizeExpr,
+                                         unsigned IndexTypeQuals,
+                                         SourceRange BracketsRange) {
+  if (SizeExpr || !Size)
+    return SemaRef.BuildArrayType(ElementType, SizeMod, SizeExpr,
+                                  IndexTypeQuals, BracketsRange,
+                                  getDerived().getBaseEntity());
+
+  QualType Types[] = {
+    SemaRef.Context.UnsignedCharTy, SemaRef.Context.UnsignedShortTy,
+    SemaRef.Context.UnsignedIntTy, SemaRef.Context.UnsignedLongTy,
+    SemaRef.Context.UnsignedLongLongTy, SemaRef.Context.UnsignedInt128Ty
+  };
+  const unsigned NumTypes = sizeof(Types) / sizeof(QualType);
+  QualType SizeType;
+  for (unsigned I = 0; I != NumTypes; ++I)
+    if (Size->getBitWidth() == SemaRef.Context.getIntWidth(Types[I])) {
+      SizeType = Types[I];
+      break;
+    }
+
+  IntegerLiteral ArraySize(*Size, SizeType, /*FIXME*/BracketsRange.getBegin());
+  return SemaRef.BuildArrayType(ElementType, SizeMod, &ArraySize,
+                                IndexTypeQuals, BracketsRange,
+                                getDerived().getBaseEntity());
+}
+
+template<typename Derived>
+QualType
+TreeTransform<Derived>::RebuildConstantArrayType(QualType ElementType,
+                                                 ArrayType::ArraySizeModifier SizeMod,
+                                                 const llvm::APInt &Size,
+                                                 unsigned IndexTypeQuals,
+                                                 SourceRange BracketsRange) {
+  return getDerived().RebuildArrayType(ElementType, SizeMod, &Size, 0,
+                                        IndexTypeQuals, BracketsRange);
+}
+
+template<typename Derived>
+QualType
+TreeTransform<Derived>::RebuildIncompleteArrayType(QualType ElementType,
+                                          ArrayType::ArraySizeModifier SizeMod,
+                                                 unsigned IndexTypeQuals,
+                                                   SourceRange BracketsRange) {
+  return getDerived().RebuildArrayType(ElementType, SizeMod, 0, 0,
+                                       IndexTypeQuals, BracketsRange);
+}
+
+template<typename Derived>
+QualType
+TreeTransform<Derived>::RebuildVariableArrayType(QualType ElementType,
+                                          ArrayType::ArraySizeModifier SizeMod,
+                                                 ExprArg SizeExpr,
+                                                 unsigned IndexTypeQuals,
+                                                 SourceRange BracketsRange) {
+  return getDerived().RebuildArrayType(ElementType, SizeMod, 0,
+                                       SizeExpr.takeAs<Expr>(),
+                                       IndexTypeQuals, BracketsRange);
+}
+
+template<typename Derived>
+QualType
+TreeTransform<Derived>::RebuildDependentSizedArrayType(QualType ElementType,
+                                          ArrayType::ArraySizeModifier SizeMod,
+                                                       ExprArg SizeExpr,
+                                                       unsigned IndexTypeQuals,
+                                                   SourceRange BracketsRange) {
+  return getDerived().RebuildArrayType(ElementType, SizeMod, 0,
+                                       SizeExpr.takeAs<Expr>(),
+                                       IndexTypeQuals, BracketsRange);
+}
+
+template<typename Derived>
+QualType TreeTransform<Derived>::RebuildVectorType(QualType ElementType,
+                                       unsigned NumElements,
+                                       bool IsAltiVec, bool IsPixel) {
+  // FIXME: semantic checking!
+  return SemaRef.Context.getVectorType(ElementType, NumElements,
+                                       IsAltiVec, IsPixel);
+}
+
+template<typename Derived>
+QualType TreeTransform<Derived>::RebuildExtVectorType(QualType ElementType,
+                                                      unsigned NumElements,
+                                                 SourceLocation AttributeLoc) {
+  llvm::APInt numElements(SemaRef.Context.getIntWidth(SemaRef.Context.IntTy),
+                          NumElements, true);
+  IntegerLiteral *VectorSize
+    = new (SemaRef.Context) IntegerLiteral(numElements, SemaRef.Context.IntTy,
+                                           AttributeLoc);
+  return SemaRef.BuildExtVectorType(ElementType, SemaRef.Owned(VectorSize),
+                                    AttributeLoc);
+}
+
+template<typename Derived>
+QualType
+TreeTransform<Derived>::RebuildDependentSizedExtVectorType(QualType ElementType,
+                                                           ExprArg SizeExpr,
+                                                  SourceLocation AttributeLoc) {
+  return SemaRef.BuildExtVectorType(ElementType, move(SizeExpr), AttributeLoc);
+}
+
+template<typename Derived>
+QualType TreeTransform<Derived>::RebuildFunctionProtoType(QualType T,
+                                                          QualType *ParamTypes,
+                                                        unsigned NumParamTypes,
+                                                          bool Variadic,
+                                                          unsigned Quals) {
+  return SemaRef.BuildFunctionType(T, ParamTypes, NumParamTypes, Variadic,
+                                   Quals,
+                                   getDerived().getBaseLocation(),
+                                   getDerived().getBaseEntity());
+}
+
+template<typename Derived>
+QualType TreeTransform<Derived>::RebuildFunctionNoProtoType(QualType T) {
+  return SemaRef.Context.getFunctionNoProtoType(T);
+}
+
+template<typename Derived>
+QualType TreeTransform<Derived>::RebuildUnresolvedUsingType(Decl *D) {
+  assert(D && "no decl found");
+  if (D->isInvalidDecl()) return QualType();
+
+  TypeDecl *Ty;
+  if (isa<UsingDecl>(D)) {
+    UsingDecl *Using = cast<UsingDecl>(D);
+    assert(Using->isTypeName() &&
+           "UnresolvedUsingTypenameDecl transformed to non-typename using");
+
+    // A valid resolved using typename decl points to exactly one type decl.
+    assert(++Using->shadow_begin() == Using->shadow_end());
+    Ty = cast<TypeDecl>((*Using->shadow_begin())->getTargetDecl());
+    
+  } else {
+    assert(isa<UnresolvedUsingTypenameDecl>(D) &&
+           "UnresolvedUsingTypenameDecl transformed to non-using decl");
+    Ty = cast<UnresolvedUsingTypenameDecl>(D);
+  }
+
+  return SemaRef.Context.getTypeDeclType(Ty);
+}
+
+template<typename Derived>
+QualType TreeTransform<Derived>::RebuildTypeOfExprType(ExprArg E) {
+  return SemaRef.BuildTypeofExprType(E.takeAs<Expr>());
+}
+
+template<typename Derived>
+QualType TreeTransform<Derived>::RebuildTypeOfType(QualType Underlying) {
+  return SemaRef.Context.getTypeOfType(Underlying);
+}
+
+template<typename Derived>
+QualType TreeTransform<Derived>::RebuildDecltypeType(ExprArg E) {
+  return SemaRef.BuildDecltypeType(E.takeAs<Expr>());
+}
+
+template<typename Derived>
+QualType TreeTransform<Derived>::RebuildTemplateSpecializationType(
+                                                      TemplateName Template,
+                                             SourceLocation TemplateNameLoc,
+                               const TemplateArgumentListInfo &TemplateArgs) {
+  return SemaRef.CheckTemplateIdType(Template, TemplateNameLoc, TemplateArgs);
+}
+
+template<typename Derived>
+NestedNameSpecifier *
+TreeTransform<Derived>::RebuildNestedNameSpecifier(NestedNameSpecifier *Prefix,
+                                                   SourceRange Range,
+                                                   IdentifierInfo &II,
+                                                   QualType ObjectType,
+                                                   NamedDecl *FirstQualifierInScope) {
+  CXXScopeSpec SS;
+  // FIXME: The source location information is all wrong.
+  SS.setRange(Range);
+  SS.setScopeRep(Prefix);
+  return static_cast<NestedNameSpecifier *>(
+                    SemaRef.BuildCXXNestedNameSpecifier(0, SS, Range.getEnd(),
+                                                        Range.getEnd(), II,
+                                                        ObjectType,
+                                                        FirstQualifierInScope,
+                                                        false, false));
+}
+
+template<typename Derived>
+NestedNameSpecifier *
+TreeTransform<Derived>::RebuildNestedNameSpecifier(NestedNameSpecifier *Prefix,
+                                                   SourceRange Range,
+                                                   NamespaceDecl *NS) {
+  return NestedNameSpecifier::Create(SemaRef.Context, Prefix, NS);
+}
+
+template<typename Derived>
+NestedNameSpecifier *
+TreeTransform<Derived>::RebuildNestedNameSpecifier(NestedNameSpecifier *Prefix,
+                                                   SourceRange Range,
+                                                   bool TemplateKW,
+                                                   QualType T) {
+  if (T->isDependentType() || T->isRecordType() ||
+      (SemaRef.getLangOptions().CPlusPlus0x && T->isEnumeralType())) {
+    assert(!T.hasLocalQualifiers() && "Can't get cv-qualifiers here");
+    return NestedNameSpecifier::Create(SemaRef.Context, Prefix, TemplateKW,
+                                       T.getTypePtr());
+  }
+
+  SemaRef.Diag(Range.getBegin(), diag::err_nested_name_spec_non_tag) << T;
+  return 0;
+}
+
+template<typename Derived>
+TemplateName
+TreeTransform<Derived>::RebuildTemplateName(NestedNameSpecifier *Qualifier,
+                                            bool TemplateKW,
+                                            TemplateDecl *Template) {
+  return SemaRef.Context.getQualifiedTemplateName(Qualifier, TemplateKW,
+                                                  Template);
+}
+
+template<typename Derived>
+TemplateName
+TreeTransform<Derived>::RebuildTemplateName(NestedNameSpecifier *Qualifier,
+                                            const IdentifierInfo &II,
+                                            QualType ObjectType) {
+  CXXScopeSpec SS;
+  SS.setRange(SourceRange(getDerived().getBaseLocation()));
+  SS.setScopeRep(Qualifier);
+  UnqualifiedId Name;
+  Name.setIdentifier(&II, /*FIXME:*/getDerived().getBaseLocation());
+  return getSema().ActOnDependentTemplateName(
+                                      /*FIXME:*/getDerived().getBaseLocation(),
+                                              SS,
+                                              Name,
+                                              ObjectType.getAsOpaquePtr(),
+                                              /*EnteringContext=*/false)
+           .template getAsVal<TemplateName>();
+}
+
+template<typename Derived>
+TemplateName
+TreeTransform<Derived>::RebuildTemplateName(NestedNameSpecifier *Qualifier,
+                                            OverloadedOperatorKind Operator,
+                                            QualType ObjectType) {
+  CXXScopeSpec SS;
+  SS.setRange(SourceRange(getDerived().getBaseLocation()));
+  SS.setScopeRep(Qualifier);
+  UnqualifiedId Name;
+  SourceLocation SymbolLocations[3]; // FIXME: Bogus location information.
+  Name.setOperatorFunctionId(/*FIXME:*/getDerived().getBaseLocation(),
+                             Operator, SymbolLocations);
+  return getSema().ActOnDependentTemplateName(
+                                       /*FIXME:*/getDerived().getBaseLocation(),
+                                              SS,
+                                              Name,
+                                              ObjectType.getAsOpaquePtr(),
+                                              /*EnteringContext=*/false)
+           .template getAsVal<TemplateName>();
+}
+  
+template<typename Derived>
+Sema::OwningExprResult
+TreeTransform<Derived>::RebuildCXXOperatorCallExpr(OverloadedOperatorKind Op,
+                                                   SourceLocation OpLoc,
+                                                   ExprArg Callee,
+                                                   ExprArg First,
+                                                   ExprArg Second) {
+  Expr *FirstExpr = (Expr *)First.get();
+  Expr *SecondExpr = (Expr *)Second.get();
+  Expr *CalleeExpr = ((Expr *)Callee.get())->IgnoreParenCasts();
+  bool isPostIncDec = SecondExpr && (Op == OO_PlusPlus || Op == OO_MinusMinus);
+
+  // Determine whether this should be a builtin operation.
+  if (Op == OO_Subscript) {
+    if (!FirstExpr->getType()->isOverloadableType() &&
+        !SecondExpr->getType()->isOverloadableType())
+      return getSema().CreateBuiltinArraySubscriptExpr(move(First),
+                                                 CalleeExpr->getLocStart(),
+                                                       move(Second), OpLoc);
+  } else if (Op == OO_Arrow) {
+    // -> is never a builtin operation.
+    return SemaRef.BuildOverloadedArrowExpr(0, move(First), OpLoc);
+  } else if (SecondExpr == 0 || isPostIncDec) {
+    if (!FirstExpr->getType()->isOverloadableType()) {
+      // The argument is not of overloadable type, so try to create a
+      // built-in unary operation.
+      UnaryOperator::Opcode Opc
+        = UnaryOperator::getOverloadedOpcode(Op, isPostIncDec);
+
+      return getSema().CreateBuiltinUnaryOp(OpLoc, Opc, move(First));
+    }
+  } else {
+    if (!FirstExpr->getType()->isOverloadableType() &&
+        !SecondExpr->getType()->isOverloadableType()) {
+      // Neither of the arguments is an overloadable type, so try to
+      // create a built-in binary operation.
+      BinaryOperator::Opcode Opc = BinaryOperator::getOverloadedOpcode(Op);
+      OwningExprResult Result
+        = SemaRef.CreateBuiltinBinOp(OpLoc, Opc, FirstExpr, SecondExpr);
+      if (Result.isInvalid())
+        return SemaRef.ExprError();
+
+      First.release();
+      Second.release();
+      return move(Result);
+    }
+  }
+
+  // Compute the transformed set of functions (and function templates) to be
+  // used during overload resolution.
+  UnresolvedSet<16> Functions;
+
+  if (UnresolvedLookupExpr *ULE = dyn_cast<UnresolvedLookupExpr>(CalleeExpr)) {
+    assert(ULE->requiresADL());
+
+    // FIXME: Do we have to check
+    // IsAcceptableNonMemberOperatorCandidate for each of these?
+    Functions.append(ULE->decls_begin(), ULE->decls_end());
+  } else {
+    Functions.addDecl(cast<DeclRefExpr>(CalleeExpr)->getDecl());
+  }
+
+  // Add any functions found via argument-dependent lookup.
+  Expr *Args[2] = { FirstExpr, SecondExpr };
+  unsigned NumArgs = 1 + (SecondExpr != 0);
+
+  // Create the overloaded operator invocation for unary operators.
+  if (NumArgs == 1 || isPostIncDec) {
+    UnaryOperator::Opcode Opc
+      = UnaryOperator::getOverloadedOpcode(Op, isPostIncDec);
+    return SemaRef.CreateOverloadedUnaryOp(OpLoc, Opc, Functions, move(First));
+  }
+
+  if (Op == OO_Subscript)
+    return SemaRef.CreateOverloadedArraySubscriptExpr(CalleeExpr->getLocStart(),
+                                                      OpLoc,
+                                                      move(First),
+                                                      move(Second));
+
+  // Create the overloaded operator invocation for binary operators.
+  BinaryOperator::Opcode Opc =
+    BinaryOperator::getOverloadedOpcode(Op);
+  OwningExprResult Result
+    = SemaRef.CreateOverloadedBinOp(OpLoc, Opc, Functions, Args[0], Args[1]);
+  if (Result.isInvalid())
+    return SemaRef.ExprError();
+
+  First.release();
+  Second.release();
+  return move(Result);
+}
+
+} // end namespace clang
+
+#endif // LLVM_CLANG_SEMA_TREETRANSFORM_H