Implement support for C++11 in-class initialization of non-static data members.



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@132878 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp
index 17b7c9d..9094aba 100644
--- a/lib/AST/ASTContext.cpp
+++ b/lib/AST/ASTContext.cpp
@@ -3536,7 +3536,8 @@
                                            SourceLocation(), 0,
                                            FieldTypes[i], /*TInfo=*/0,
                                            /*BitWidth=*/0,
-                                           /*Mutable=*/false);
+                                           /*Mutable=*/false,
+                                           /*HasInit=*/false);
       Field->setAccess(AS_public);
       CFConstantStringTypeDecl->addDecl(Field);
     }
@@ -3577,7 +3578,8 @@
                                            SourceLocation(), 0,
                                            FieldTypes[i], /*TInfo=*/0,
                                            /*BitWidth=*/0,
-                                           /*Mutable=*/false);
+                                           /*Mutable=*/false,
+                                           /*HasInit=*/false);
       Field->setAccess(AS_public);
       NSConstantStringTypeDecl->addDecl(Field);
     }
@@ -3616,7 +3618,8 @@
                                            SourceLocation(), 0,
                                            FieldTypes[i], /*TInfo=*/0,
                                            /*BitWidth=*/0,
-                                           /*Mutable=*/false);
+                                           /*Mutable=*/false,
+                                           /*HasInit=*/false);
       Field->setAccess(AS_public);
       ObjCFastEnumerationStateTypeDecl->addDecl(Field);
     }
@@ -3653,7 +3656,8 @@
                                          &Idents.get(FieldNames[i]),
                                          FieldTypes[i], /*TInfo=*/0,
                                          /*BitWidth=*/0,
-                                         /*Mutable=*/false);
+                                         /*Mutable=*/false,
+                                         /*HasInit=*/false);
     Field->setAccess(AS_public);
     T->addDecl(Field);
   }
@@ -3701,7 +3705,8 @@
                                          &Idents.get(FieldNames[i]),
                                          FieldTypes[i], /*TInfo=*/0,
                                          /*BitWidth=*/0,
-                                         /*Mutable=*/false);
+                                         /*Mutable=*/false,
+                                         /*HasInit=*/false);
     Field->setAccess(AS_public);
     T->addDecl(Field);
   }
@@ -3786,7 +3791,8 @@
                                          SourceLocation(),
                                          &Idents.get(FieldNames[i]),
                                          FieldTypes[i], /*TInfo=*/0,
-                                         /*BitWidth=*/0, /*Mutable=*/false);
+                                         /*BitWidth=*/0, /*Mutable=*/false,
+                                         /*HasInit=*/false);
     Field->setAccess(AS_public);
     T->addDecl(Field);
   }
diff --git a/lib/AST/ASTImporter.cpp b/lib/AST/ASTImporter.cpp
index fcca95c..100e604 100644
--- a/lib/AST/ASTImporter.cpp
+++ b/lib/AST/ASTImporter.cpp
@@ -2512,9 +2512,12 @@
   FieldDecl *ToField = FieldDecl::Create(Importer.getToContext(), DC,
                                          Importer.Import(D->getInnerLocStart()),
                                          Loc, Name.getAsIdentifierInfo(),
-                                         T, TInfo, BitWidth, D->isMutable());
+                                         T, TInfo, BitWidth, D->isMutable(),
+                                         D->hasInClassInitializer());
   ToField->setAccess(D->getAccess());
   ToField->setLexicalDeclContext(LexicalDC);
+  if (ToField->hasInClassInitializer())
+    ToField->setInClassInitializer(D->getInClassInitializer());
   Importer.Imported(D, ToField);
   LexicalDC->addDecl(ToField);
   return ToField;
diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp
index 1cad64e..12357c0 100644
--- a/lib/AST/Decl.cpp
+++ b/lib/AST/Decl.cpp
@@ -2077,9 +2077,10 @@
 FieldDecl *FieldDecl::Create(const ASTContext &C, DeclContext *DC,
                              SourceLocation StartLoc, SourceLocation IdLoc,
                              IdentifierInfo *Id, QualType T,
-                             TypeSourceInfo *TInfo, Expr *BW, bool Mutable) {
+                             TypeSourceInfo *TInfo, Expr *BW, bool Mutable,
+                             bool HasInit) {
   return new (C) FieldDecl(Decl::Field, DC, StartLoc, IdLoc, Id, T, TInfo,
-                           BW, Mutable);
+                           BW, Mutable, HasInit);
 }
 
 bool FieldDecl::isAnonymousStructOrUnion() const {
@@ -2124,10 +2125,17 @@
 
 SourceRange FieldDecl::getSourceRange() const {
   if (isBitField())
-    return SourceRange(getInnerLocStart(), BitWidth->getLocEnd());
+    return SourceRange(getInnerLocStart(), getBitWidth()->getLocEnd());
   return DeclaratorDecl::getSourceRange();
 }
 
+void FieldDecl::setInClassInitializer(Expr *Init) {
+  assert(!InitializerOrBitWidth.getPointer() &&
+         "bit width or initializer already set");
+  InitializerOrBitWidth.setPointer(Init);
+  InitializerOrBitWidth.setInt(0);
+}
+
 //===----------------------------------------------------------------------===//
 // TagDecl Implementation
 //===----------------------------------------------------------------------===//
diff --git a/lib/AST/DeclCXX.cpp b/lib/AST/DeclCXX.cpp
index 9e82a1a..08ac2a5 100644
--- a/lib/AST/DeclCXX.cpp
+++ b/lib/AST/DeclCXX.cpp
@@ -715,6 +715,22 @@
     if (!hasNonLiteralTypeFieldsOrBases() && !T->isLiteralType())
       data().HasNonLiteralTypeFieldsOrBases = true;
 
+    if (Field->hasInClassInitializer()) {
+      // C++0x [class]p5:
+      //   A default constructor is trivial if [...] no non-static data member
+      //   of its class has a brace-or-equal-initializer.
+      data().HasTrivialDefaultConstructor = false;
+
+      // C++0x [dcl.init.aggr]p1:
+      //   An aggregate is a [...] class with [...] no
+      //   brace-or-equal-initializers for non-static data members.
+      data().Aggregate = false;
+
+      // C++0x [class]p10:
+      //   A POD struct is [...] a trivial class.
+      data().PlainOldData = false;
+    }
+
     if (const RecordType *RecordTy = T->getAs<RecordType>()) {
       CXXRecordDecl* FieldRec = cast<CXXRecordDecl>(RecordTy->getDecl());
       if (FieldRec->getDefinition()) {
@@ -1345,11 +1361,21 @@
 SourceLocation CXXCtorInitializer::getSourceLocation() const {
   if (isAnyMemberInitializer() || isDelegatingInitializer())
     return getMemberLocation();
+
+  if (isInClassMemberInitializer())
+    return getAnyMember()->getLocation();
   
   return getBaseClassLoc().getLocalSourceRange().getBegin();
 }
 
 SourceRange CXXCtorInitializer::getSourceRange() const {
+  if (isInClassMemberInitializer()) {
+    FieldDecl *D = getAnyMember();
+    if (Expr *I = D->getInClassInitializer())
+      return I->getSourceRange();
+    return SourceRange();
+  }
+
   return SourceRange(getSourceLocation(), getRParenLoc());
 }
 
diff --git a/lib/AST/DeclPrinter.cpp b/lib/AST/DeclPrinter.cpp
index 49f2723..de1b610 100644
--- a/lib/AST/DeclPrinter.cpp
+++ b/lib/AST/DeclPrinter.cpp
@@ -450,62 +450,67 @@
     if (D->hasAttr<NoReturnAttr>())
       Proto += " __attribute((noreturn))";
     if (CXXConstructorDecl *CDecl = dyn_cast<CXXConstructorDecl>(D)) {
-      if (CDecl->getNumCtorInitializers() > 0) {
-        Proto += " : ";
-        Out << Proto;
-        Proto.clear();
-        for (CXXConstructorDecl::init_const_iterator B = CDecl->init_begin(),
-             E = CDecl->init_end();
-             B != E; ++B) {
-          CXXCtorInitializer * BMInitializer = (*B);
-          if (B != CDecl->init_begin())
-            Out << ", ";
-          if (BMInitializer->isAnyMemberInitializer()) {
-            FieldDecl *FD = BMInitializer->getAnyMember();
-            Out << FD;
-          } else {
-            Out << QualType(BMInitializer->getBaseClass(),
-                            0).getAsString(Policy);
-          }
+      bool HasInitializerList = false;
+      for (CXXConstructorDecl::init_const_iterator B = CDecl->init_begin(),
+           E = CDecl->init_end();
+           B != E; ++B) {
+        CXXCtorInitializer * BMInitializer = (*B);
+        if (BMInitializer->isInClassMemberInitializer())
+          continue;
+
+        if (!HasInitializerList) {
+          Proto += " : ";
+          Out << Proto;
+          Proto.clear();
+          HasInitializerList = true;
+        } else
+          Out << ", ";
+
+        if (BMInitializer->isAnyMemberInitializer()) {
+          FieldDecl *FD = BMInitializer->getAnyMember();
+          Out << FD;
+        } else {
+          Out << QualType(BMInitializer->getBaseClass(),
+                          0).getAsString(Policy);
+        }
+        
+        Out << "(";
+        if (!BMInitializer->getInit()) {
+          // Nothing to print
+        } else {
+          Expr *Init = BMInitializer->getInit();
+          if (ExprWithCleanups *Tmp = dyn_cast<ExprWithCleanups>(Init))
+            Init = Tmp->getSubExpr();
           
-          Out << "(";
-          if (!BMInitializer->getInit()) {
-            // Nothing to print
-          } else {
-            Expr *Init = BMInitializer->getInit();
-            if (ExprWithCleanups *Tmp = dyn_cast<ExprWithCleanups>(Init))
-              Init = Tmp->getSubExpr();
-            
-            Init = Init->IgnoreParens();
-            
-            Expr *SimpleInit = 0;
-            Expr **Args = 0;
-            unsigned NumArgs = 0;
-            if (ParenListExpr *ParenList = dyn_cast<ParenListExpr>(Init)) {
-              Args = ParenList->getExprs();
-              NumArgs = ParenList->getNumExprs();
-            } else if (CXXConstructExpr *Construct
-                                          = dyn_cast<CXXConstructExpr>(Init)) {
-              Args = Construct->getArgs();
-              NumArgs = Construct->getNumArgs();
-            } else
-              SimpleInit = Init;
-            
-            if (SimpleInit)
-              SimpleInit->printPretty(Out, Context, 0, Policy, Indentation);
-            else {
-              for (unsigned I = 0; I != NumArgs; ++I) {
-                if (isa<CXXDefaultArgExpr>(Args[I]))
-                  break;
-                
-                if (I)
-                  Out << ", ";
-                Args[I]->printPretty(Out, Context, 0, Policy, Indentation);
-              }
+          Init = Init->IgnoreParens();
+          
+          Expr *SimpleInit = 0;
+          Expr **Args = 0;
+          unsigned NumArgs = 0;
+          if (ParenListExpr *ParenList = dyn_cast<ParenListExpr>(Init)) {
+            Args = ParenList->getExprs();
+            NumArgs = ParenList->getNumExprs();
+          } else if (CXXConstructExpr *Construct
+                                        = dyn_cast<CXXConstructExpr>(Init)) {
+            Args = Construct->getArgs();
+            NumArgs = Construct->getNumArgs();
+          } else
+            SimpleInit = Init;
+          
+          if (SimpleInit)
+            SimpleInit->printPretty(Out, Context, 0, Policy, Indentation);
+          else {
+            for (unsigned I = 0; I != NumArgs; ++I) {
+              if (isa<CXXDefaultArgExpr>(Args[I]))
+                break;
+              
+              if (I)
+                Out << ", ";
+              Args[I]->printPretty(Out, Context, 0, Policy, Indentation);
             }
           }
-          Out << ")";
         }
+        Out << ")";
       }
     }
     else
@@ -553,6 +558,12 @@
     Out << " : ";
     D->getBitWidth()->printPretty(Out, Context, 0, Policy, Indentation);
   }
+
+  Expr *Init = D->getInClassInitializer();
+  if (!Policy.SuppressInitializers && Init) {
+    Out << " = ";
+    Init->printPretty(Out, Context, 0, Policy, Indentation);
+  }
 }
 
 void DeclPrinter::VisitLabelDecl(LabelDecl *D) {
diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp
index 012701d..9872139 100644
--- a/lib/AST/Expr.cpp
+++ b/lib/AST/Expr.cpp
@@ -22,6 +22,7 @@
 #include "clang/AST/StmtVisitor.h"
 #include "clang/Lex/LiteralSupport.h"
 #include "clang/Lex/Lexer.h"
+#include "clang/Sema/SemaDiagnostic.h"
 #include "clang/Basic/Builtins.h"
 #include "clang/Basic/SourceManager.h"
 #include "clang/Basic/TargetInfo.h"
@@ -1653,7 +1654,8 @@
   return R;
 }
 
-static Expr::CanThrowResult CanCalleeThrow(ASTContext &Ctx, const Decl *D,
+static Expr::CanThrowResult CanCalleeThrow(ASTContext &Ctx, const Expr *E,
+                                           const Decl *D,
                                            bool NullThrows = true) {
   if (!D)
     return NullThrows ? Expr::CT_Can : Expr::CT_Cannot;
@@ -1683,6 +1685,15 @@
   if (!FT)
     return Expr::CT_Can;
 
+  if (FT->getExceptionSpecType() == EST_Delayed) {
+    assert(isa<CXXConstructorDecl>(D) &&
+           "only constructor exception specs can be unknown");
+    Ctx.getDiagnostics().Report(E->getLocStart(),
+                                diag::err_exception_spec_unknown)
+      << E->getSourceRange();
+    return Expr::CT_Can;
+  }
+
   return FT->isNothrow(Ctx) ? Expr::CT_Cannot : Expr::CT_Can;
 }
 
@@ -1757,7 +1768,7 @@
     else if (isa<CXXPseudoDestructorExpr>(CE->getCallee()->IgnoreParens()))
       CT = CT_Cannot;
     else
-      CT = CanCalleeThrow(C, CE->getCalleeDecl());
+      CT = CanCalleeThrow(C, this, CE->getCalleeDecl());
     if (CT == CT_Can)
       return CT;
     return MergeCanThrow(CT, CanSubExprsThrow(C, this));
@@ -1765,7 +1776,7 @@
 
   case CXXConstructExprClass:
   case CXXTemporaryObjectExprClass: {
-    CanThrowResult CT = CanCalleeThrow(C,
+    CanThrowResult CT = CanCalleeThrow(C, this,
         cast<CXXConstructExpr>(this)->getConstructor());
     if (CT == CT_Can)
       return CT;
@@ -1778,8 +1789,8 @@
       CT = CT_Dependent;
     else
       CT = MergeCanThrow(
-        CanCalleeThrow(C, cast<CXXNewExpr>(this)->getOperatorNew()),
-        CanCalleeThrow(C, cast<CXXNewExpr>(this)->getConstructor(),
+        CanCalleeThrow(C, this, cast<CXXNewExpr>(this)->getOperatorNew()),
+        CanCalleeThrow(C, this, cast<CXXNewExpr>(this)->getConstructor(),
                        /*NullThrows*/false));
     if (CT == CT_Can)
       return CT;
@@ -1792,10 +1803,11 @@
     if (DTy.isNull() || DTy->isDependentType()) {
       CT = CT_Dependent;
     } else {
-      CT = CanCalleeThrow(C, cast<CXXDeleteExpr>(this)->getOperatorDelete());
+      CT = CanCalleeThrow(C, this,
+                          cast<CXXDeleteExpr>(this)->getOperatorDelete());
       if (const RecordType *RT = DTy->getAs<RecordType>()) {
         const CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
-        CT = MergeCanThrow(CT, CanCalleeThrow(C, RD->getDestructor()));
+        CT = MergeCanThrow(CT, CanCalleeThrow(C, this, RD->getDestructor()));
       }
       if (CT == CT_Can)
         return CT;
@@ -1805,7 +1817,7 @@
 
   case CXXBindTemporaryExprClass: {
     // The bound temporary has to be destroyed again, which might throw.
-    CanThrowResult CT = CanCalleeThrow(C,
+    CanThrowResult CT = CanCalleeThrow(C, this,
       cast<CXXBindTemporaryExpr>(this)->getTemporary()->getDestructor());
     if (CT == CT_Can)
       return CT;
diff --git a/lib/AST/Mangle.cpp b/lib/AST/Mangle.cpp
index 3a0b909..c3f3b11 100644
--- a/lib/AST/Mangle.cpp
+++ b/lib/AST/Mangle.cpp
@@ -48,6 +48,11 @@
   const DeclContext *ExpectedDC = BD->getDeclContext();
   while (isa<BlockDecl>(ExpectedDC) || isa<EnumDecl>(ExpectedDC))
     ExpectedDC = ExpectedDC->getParent();
+  // In-class initializers for non-static data members are lexically defined
+  // within the class, but are mangled as if they were specified as constructor
+  // member initializers.
+  if (isa<CXXRecordDecl>(ExpectedDC) && DC != ExpectedDC)
+    DC = DC->getParent();
   assert(DC == ExpectedDC && "Given decl context did not match expected!");
 #endif
 }
diff --git a/lib/CodeGen/CGBlocks.cpp b/lib/CodeGen/CGBlocks.cpp
index f11d528..e5da703 100644
--- a/lib/CodeGen/CGBlocks.cpp
+++ b/lib/CodeGen/CGBlocks.cpp
@@ -304,7 +304,11 @@
     const DeclContext *DC = block->getDeclContext();
     for (; isa<BlockDecl>(DC); DC = cast<BlockDecl>(DC)->getDeclContext())
       ;
-    QualType thisType = cast<CXXMethodDecl>(DC)->getThisType(C);
+    QualType thisType;
+    if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(DC))
+      thisType = C.getPointerType(C.getRecordType(RD));
+    else
+      thisType = cast<CXXMethodDecl>(DC)->getThisType(C);
 
     const llvm::Type *llvmType = CGM.getTypes().ConvertType(thisType);
     std::pair<CharUnits,CharUnits> tinfo
diff --git a/lib/CodeGen/CGClass.cpp b/lib/CodeGen/CGClass.cpp
index 0d25008..5725d80 100644
--- a/lib/CodeGen/CGClass.cpp
+++ b/lib/CodeGen/CGClass.cpp
@@ -520,6 +520,7 @@
                                   FunctionArgList &Args) {
   assert(MemberInit->isAnyMemberInitializer() &&
          "Must have member initializer!");
+  assert(MemberInit->getInit() && "Must have initializer!");
   
   // non-static data member initializers.
   FieldDecl *Field = MemberInit->getAnyMember();
diff --git a/lib/CodeGen/CGObjCMac.cpp b/lib/CodeGen/CGObjCMac.cpp
index 520d94e..8c3e9a3 100644
--- a/lib/CodeGen/CGObjCMac.cpp
+++ b/lib/CodeGen/CGObjCMac.cpp
@@ -4098,9 +4098,9 @@
                                       SourceLocation(), SourceLocation(),
                                       &Ctx.Idents.get("_objc_super"));
   RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), SourceLocation(), 0,
-                                Ctx.getObjCIdType(), 0, 0, false));
+                                Ctx.getObjCIdType(), 0, 0, false, false));
   RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), SourceLocation(), 0,
-                                Ctx.getObjCClassType(), 0, 0, false));
+                                Ctx.getObjCClassType(), 0, 0, false, false));
   RD->completeDefinition();
 
   SuperCTy = Ctx.getTagDeclType(RD);
@@ -4559,9 +4559,9 @@
                                       SourceLocation(), SourceLocation(),
                                       &Ctx.Idents.get("_message_ref_t"));
   RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), SourceLocation(), 0,
-                                Ctx.VoidPtrTy, 0, 0, false));
+                                Ctx.VoidPtrTy, 0, 0, false, false));
   RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), SourceLocation(), 0,
-                                Ctx.getObjCSelType(), 0, 0, false));
+                                Ctx.getObjCSelType(), 0, 0, false, false));
   RD->completeDefinition();
 
   MessageRefCTy = Ctx.getTagDeclType(RD);
diff --git a/lib/Parse/ParseCXXInlineMethods.cpp b/lib/Parse/ParseCXXInlineMethods.cpp
index dee0027..f5c6998 100644
--- a/lib/Parse/ParseCXXInlineMethods.cpp
+++ b/lib/Parse/ParseCXXInlineMethods.cpp
@@ -42,6 +42,7 @@
     FnD = Actions.ActOnCXXMemberDeclarator(getCurScope(), AS, D,
                                            move(TemplateParams), 0, 
                                            VS, Init.release(),
+                                           /*HasInit=*/false,
                                            /*IsDefinition*/true);
   }
 
@@ -166,8 +167,50 @@
   return FnD;
 }
 
+/// ParseCXXNonStaticMemberInitializer - We parsed and verified that the
+/// specified Declarator is a well formed C++ non-static data member
+/// declaration. Now lex its initializer and store its tokens for parsing
+/// after the class is complete.
+void Parser::ParseCXXNonStaticMemberInitializer(Decl *VarD) {
+  assert((Tok.is(tok::l_brace) || Tok.is(tok::equal)) &&
+         "Current token not a '{' or '='!");
+
+  LateParsedMemberInitializer *MI =
+    new LateParsedMemberInitializer(this, VarD);
+  getCurrentClass().LateParsedDeclarations.push_back(MI);
+  CachedTokens &Toks = MI->Toks;
+
+  tok::TokenKind kind = Tok.getKind();
+  if (kind == tok::equal) {
+    Toks.push_back(Tok);
+    ConsumeAnyToken();
+  }
+
+  if (kind == tok::l_brace) {
+    // Begin by storing the '{' token.
+    Toks.push_back(Tok);
+    ConsumeBrace();
+
+    // Consume everything up to (and including) the matching right brace.
+    ConsumeAndStoreUntil(tok::r_brace, Toks, /*StopAtSemi=*/true);
+  } else {
+    // Consume everything up to (but excluding) the comma or semicolon.
+    ConsumeAndStoreUntil(tok::comma, Toks, /*StopAtSemi=*/true,
+                         /*ConsumeFinalToken=*/false);
+  }
+
+  // Store an artificial EOF token to ensure that we don't run off the end of
+  // the initializer when we come to parse it.
+  Token Eof;
+  Eof.startToken();
+  Eof.setKind(tok::eof);
+  Eof.setLocation(Tok.getLocation());
+  Toks.push_back(Eof);
+}
+
 Parser::LateParsedDeclaration::~LateParsedDeclaration() {}
 void Parser::LateParsedDeclaration::ParseLexedMethodDeclarations() {}
+void Parser::LateParsedDeclaration::ParseLexedMemberInitializers() {}
 void Parser::LateParsedDeclaration::ParseLexedMethodDefs() {}
 
 Parser::LateParsedClass::LateParsedClass(Parser *P, ParsingClass *C)
@@ -181,6 +224,10 @@
   Self->ParseLexedMethodDeclarations(*Class);
 }
 
+void Parser::LateParsedClass::ParseLexedMemberInitializers() {
+  Self->ParseLexedMemberInitializers(*Class);
+}
+
 void Parser::LateParsedClass::ParseLexedMethodDefs() {
   Self->ParseLexedMethodDefs(*Class);
 }
@@ -193,6 +240,10 @@
   Self->ParseLexedMethodDef(*this);
 }
 
+void Parser::LateParsedMemberInitializer::ParseLexedMemberInitializers() {
+  Self->ParseLexedMemberInitializer(*this);
+}
+
 /// ParseLexedMethodDeclarations - We finished parsing the member
 /// specification of a top (non-nested) C++ class. Now go over the
 /// stack of method declarations with some parts for which parsing was
@@ -364,10 +415,72 @@
                                                         origLoc))
       while (Tok.getLocation() != origLoc && Tok.isNot(tok::eof))
         ConsumeAnyToken();
-
   }
 }
 
+/// ParseLexedMemberInitializers - We finished parsing the member specification
+/// of a top (non-nested) C++ class. Now go over the stack of lexed data member
+/// initializers that were collected during its parsing and parse them all.
+void Parser::ParseLexedMemberInitializers(ParsingClass &Class) {
+  bool HasTemplateScope = !Class.TopLevelClass && Class.TemplateScope;
+  ParseScope ClassTemplateScope(this, Scope::TemplateParamScope,
+                                HasTemplateScope);
+  if (HasTemplateScope)
+    Actions.ActOnReenterTemplateScope(getCurScope(), Class.TagOrTemplate);
+
+  // Set or update the scope flags to include Scope::ThisScope.
+  bool AlreadyHasClassScope = Class.TopLevelClass;
+  unsigned ScopeFlags = Scope::ClassScope|Scope::DeclScope|Scope::ThisScope;
+  ParseScope ClassScope(this, ScopeFlags, !AlreadyHasClassScope);
+  ParseScopeFlags ClassScopeFlags(this, ScopeFlags, AlreadyHasClassScope);
+
+  if (!AlreadyHasClassScope)
+    Actions.ActOnStartDelayedMemberDeclarations(getCurScope(),
+                                                Class.TagOrTemplate);
+
+  for (size_t i = 0; i < Class.LateParsedDeclarations.size(); ++i) {
+    Class.LateParsedDeclarations[i]->ParseLexedMemberInitializers();
+  }
+
+  if (!AlreadyHasClassScope)
+    Actions.ActOnFinishDelayedMemberDeclarations(getCurScope(),
+                                                 Class.TagOrTemplate);
+
+  Actions.ActOnFinishDelayedMemberInitializers(Class.TagOrTemplate);
+}
+
+void Parser::ParseLexedMemberInitializer(LateParsedMemberInitializer &MI) {
+  if (MI.Field->isInvalidDecl())
+    return;
+
+  // Append the current token at the end of the new token stream so that it
+  // doesn't get lost.
+  MI.Toks.push_back(Tok);
+  PP.EnterTokenStream(MI.Toks.data(), MI.Toks.size(), true, false);
+
+  // Consume the previously pushed token.
+  ConsumeAnyToken();
+
+  SourceLocation EqualLoc;
+  ExprResult Init = ParseCXXMemberInitializer(/*IsFunction=*/false, EqualLoc);
+
+  Actions.ActOnCXXInClassMemberInitializer(MI.Field, EqualLoc, Init.release());
+
+  // The next token should be our artificial terminating EOF token.
+  if (Tok.isNot(tok::eof)) {
+    SourceLocation EndLoc = PP.getLocForEndOfToken(PrevTokLocation);
+    if (!EndLoc.isValid())
+      EndLoc = Tok.getLocation();
+    // No fixit; we can't recover as if there were a semicolon here.
+    Diag(EndLoc, diag::err_expected_semi_decl_list);
+
+    // Consume tokens until we hit the artificial EOF.
+    while (Tok.isNot(tok::eof))
+      ConsumeAnyToken();
+  }
+  ConsumeAnyToken();
+}
+
 /// ConsumeAndStoreUntil - Consume and store the token at the passed token
 /// container until the token 'T' is reached (which gets
 /// consumed/stored too, if ConsumeFinalToken).
diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp
index dca7f90..51aa010 100644
--- a/lib/Parse/ParseDeclCXX.cpp
+++ b/lib/Parse/ParseDeclCXX.cpp
@@ -1553,6 +1553,7 @@
 ///       member-declarator:
 ///         declarator virt-specifier-seq[opt] pure-specifier[opt]
 ///         declarator constant-initializer[opt]
+/// [C++11] declarator brace-or-equal-initializer[opt]
 ///         identifier[opt] ':' constant-expression
 ///
 ///       virt-specifier-seq:
@@ -1731,10 +1732,14 @@
 
     bool IsDefinition = false;
     // function-definition:
-    if (Tok.is(tok::l_brace)) {
+    //
+    // In C++11, a non-function declarator followed by an open brace is a
+    // braced-init-list for an in-class member initialization, not an
+    // erroneous function definition.
+    if (Tok.is(tok::l_brace) && !getLang().CPlusPlus0x) {
       IsDefinition = true;
     } else if (DeclaratorInfo.isFunctionDeclarator()) {
-      if (Tok.is(tok::colon) || Tok.is(tok::kw_try)) {
+      if (Tok.is(tok::l_brace) || Tok.is(tok::colon) || Tok.is(tok::kw_try)) {
         IsDefinition = true;
       } else if (Tok.is(tok::equal)) {
         const Token &KW = NextToken();
@@ -1790,7 +1795,7 @@
   while (1) {
     // member-declarator:
     //   declarator pure-specifier[opt]
-    //   declarator constant-initializer[opt]
+    //   declarator brace-or-equal-initializer[opt]
     //   identifier[opt] ':' constant-expression
     if (Tok.is(tok::colon)) {
       ConsumeToken();
@@ -1799,38 +1804,6 @@
         SkipUntil(tok::comma, true, true);
     }
 
-    ParseOptionalCXX0XVirtSpecifierSeq(VS);
-
-    // pure-specifier:
-    //   '= 0'
-    //
-    // constant-initializer:
-    //   '=' constant-expression
-    //
-    // defaulted/deleted function-definition:
-    //   '=' 'default'                          [TODO]
-    //   '=' 'delete'
-    if (Tok.is(tok::equal)) {
-      ConsumeToken();
-      if (Tok.is(tok::kw_delete)) {
-        if (DeclaratorInfo.isFunctionDeclarator())
-          Diag(ConsumeToken(), diag::err_default_delete_in_multiple_declaration)
-            << 1 /* delete */;
-        else
-          Diag(ConsumeToken(), diag::err_deleted_non_function);
-      } else if (Tok.is(tok::kw_default)) {
-        if (DeclaratorInfo.isFunctionDeclarator())
-          Diag(Tok, diag::err_default_delete_in_multiple_declaration)
-            << 1 /* delete */;
-        else
-          Diag(ConsumeToken(), diag::err_default_special_members);
-      } else {
-        Init = ParseInitializer();
-        if (Init.isInvalid())
-          SkipUntil(tok::comma, true, true);
-      }
-    }
-
     // If a simple-asm-expr is present, parse it.
     if (Tok.is(tok::kw_asm)) {
       SourceLocation Loc;
@@ -1845,6 +1818,30 @@
     // If attributes exist after the declarator, parse them.
     MaybeParseGNUAttributes(DeclaratorInfo);
 
+    // FIXME: When g++ adds support for this, we'll need to check whether it
+    // goes before or after the GNU attributes and __asm__.
+    ParseOptionalCXX0XVirtSpecifierSeq(VS);
+
+    bool HasDeferredInitializer = false;
+    if (Tok.is(tok::equal) || Tok.is(tok::l_brace)) {
+      if (BitfieldSize.get()) {
+        Diag(Tok, diag::err_bitfield_member_init);
+        SkipUntil(tok::comma, true, true);
+      } else {
+        HasDeferredInitializer = !DeclaratorInfo.isFunctionDeclarator() &&
+          DeclaratorInfo.getDeclSpec().getStorageClassSpec()
+            != DeclSpec::SCS_static;
+
+        if (!HasDeferredInitializer) {
+          SourceLocation EqualLoc;
+          Init = ParseCXXMemberInitializer(
+            DeclaratorInfo.isFunctionDeclarator(), EqualLoc);
+          if (Init.isInvalid())
+            SkipUntil(tok::comma, true, true);
+        }
+      }
+    }
+
     // NOTE: If Sema is the Action module and declarator is an instance field,
     // this call will *not* return the created decl; It will return null.
     // See Sema::ActOnCXXMemberDeclarator for details.
@@ -1860,7 +1857,9 @@
                                                   DeclaratorInfo,
                                                   move(TemplateParams),
                                                   BitfieldSize.release(),
-                                                  VS, Init.release(), false);
+                                                  VS, Init.release(),
+                                                  HasDeferredInitializer,
+                                                  /*IsDefinition*/ false);
     }
     if (ThisDecl)
       DeclsInGroup.push_back(ThisDecl);
@@ -1873,6 +1872,24 @@
 
     DeclaratorInfo.complete(ThisDecl);
 
+    if (HasDeferredInitializer) {
+      if (!getLang().CPlusPlus0x)
+        Diag(Tok, diag::warn_nonstatic_member_init_accepted_as_extension);
+
+      if (DeclaratorInfo.isArrayOfUnknownBound()) {
+        // C++0x [dcl.array]p3: An array bound may also be omitted when the
+        // declarator is followed by an initializer. 
+        //
+        // A brace-or-equal-initializer for a member-declarator is not an
+        // initializer in the gramamr, so this is ill-formed.
+        Diag(Tok, diag::err_incomplete_array_member_init);
+        SkipUntil(tok::comma, true, true);
+        // Avoid later warnings about a class member of incomplete type.
+        ThisDecl->setInvalidDecl();
+      } else
+        ParseCXXNonStaticMemberInitializer(ThisDecl);
+    }
+
     // If we don't have a comma, it is either the end of the list (a ';')
     // or an error, bail out.
     if (Tok.isNot(tok::comma))
@@ -1906,6 +1923,66 @@
                                   DeclsInGroup.size());
 }
 
+/// ParseCXXMemberInitializer - Parse the brace-or-equal-initializer or
+/// pure-specifier. Also detect and reject any attempted defaulted/deleted
+/// function definition. The location of the '=', if any, will be placed in
+/// EqualLoc.
+///
+///   pure-specifier:
+///     '= 0'
+///  
+///   brace-or-equal-initializer:
+///     '=' initializer-expression
+///     braced-init-list                       [TODO]
+///  
+///   initializer-clause:
+///     assignment-expression
+///     braced-init-list                       [TODO]
+///  
+///   defaulted/deleted function-definition:                                                                                                                                                                                               
+///     '=' 'default'
+///     '=' 'delete'
+///
+/// Prior to C++0x, the assignment-expression in an initializer-clause must
+/// be a constant-expression.
+ExprResult Parser::ParseCXXMemberInitializer(bool IsFunction,
+                                             SourceLocation &EqualLoc) {
+  assert((Tok.is(tok::equal) || Tok.is(tok::l_brace))
+         && "Data member initializer not starting with '=' or '{'");
+
+  if (Tok.is(tok::equal)) {
+    EqualLoc = ConsumeToken();
+    if (Tok.is(tok::kw_delete)) {
+      // In principle, an initializer of '= delete p;' is legal, but it will
+      // never type-check. It's better to diagnose it as an ill-formed expression
+      // than as an ill-formed deleted non-function member.
+      // An initializer of '= delete p, foo' will never be parsed, because
+      // a top-level comma always ends the initializer expression.
+      const Token &Next = NextToken();
+      if (IsFunction || Next.is(tok::semi) || Next.is(tok::comma) ||
+           Next.is(tok::eof)) {
+        if (IsFunction)
+          Diag(ConsumeToken(), diag::err_default_delete_in_multiple_declaration)
+            << 1 /* delete */;
+        else
+          Diag(ConsumeToken(), diag::err_deleted_non_function);
+        return ExprResult();
+      }
+    } else if (Tok.is(tok::kw_default)) {
+      Diag(ConsumeToken(), diag::err_default_special_members);
+      if (IsFunction)
+        Diag(Tok, diag::err_default_delete_in_multiple_declaration)
+          << 0 /* default */;
+      else
+        Diag(ConsumeToken(), diag::err_default_special_members);
+      return ExprResult();
+    }
+
+    return ParseInitializer();
+  } else
+    return ExprError(Diag(Tok, diag::err_generalized_initializer_lists));
+}
+
 /// ParseCXXMemberSpecification - Parse the class definition.
 ///
 ///       member-specification:
@@ -2057,19 +2134,20 @@
                                               LBraceLoc, RBraceLoc,
                                               attrs.getList());
 
-  // C++ 9.2p2: Within the class member-specification, the class is regarded as
-  // complete within function bodies, default arguments,
-  // exception-specifications, and constructor ctor-initializers (including
-  // such things in nested classes).
+  // C++0x [class.mem]p2: Within the class member-specification, the class is
+  // regarded as complete within function bodies, default arguments, exception-
+  // specifications, and brace-or-equal-initializers for non-static data
+  // members (including such things in nested classes).
   //
-  // FIXME: Only function bodies and constructor ctor-initializers are
-  // parsed correctly, fix the rest.
+  // FIXME: Only function bodies and brace-or-equal-initializers are currently
+  // handled. Fix the others!
   if (TagDecl && NonNestedClass) {
     // We are not inside a nested class. This class and its nested classes
     // are complete and we can parse the delayed portions of method
     // declarations and the lexed inline method definitions.
     SourceLocation SavedPrevTokLocation = PrevTokLocation;
     ParseLexedMethodDeclarations(getCurrentClass());
+    ParseLexedMemberInitializers(getCurrentClass());
     ParseLexedMethodDefs(getCurrentClass());
     PrevTokLocation = SavedPrevTokLocation;
   }
diff --git a/lib/Parse/Parser.cpp b/lib/Parse/Parser.cpp
index f209723..f19472c 100644
--- a/lib/Parse/Parser.cpp
+++ b/lib/Parse/Parser.cpp
@@ -351,7 +351,23 @@
     ScopeCache[NumCachedScopes++] = OldScope;
 }
 
+/// Set the flags for the current scope to ScopeFlags. If ManageFlags is false,
+/// this object does nothing.
+Parser::ParseScopeFlags::ParseScopeFlags(Parser *Self, unsigned ScopeFlags,
+                                 bool ManageFlags)
+  : CurScope(ManageFlags ? Self->getCurScope() : 0) {
+  if (CurScope) {
+    OldFlags = CurScope->getFlags();
+    CurScope->setFlags(ScopeFlags);
+  }
+}
 
+/// Restore the flags for the current scope to what they were before this
+/// object overrode them.
+Parser::ParseScopeFlags::~ParseScopeFlags() {
+  if (CurScope)
+    CurScope->setFlags(OldFlags);
+}
 
 
 //===----------------------------------------------------------------------===//
diff --git a/lib/Rewrite/RewriteObjC.cpp b/lib/Rewrite/RewriteObjC.cpp
index d6e34ef..8cdb55a 100644
--- a/lib/Rewrite/RewriteObjC.cpp
+++ b/lib/Rewrite/RewriteObjC.cpp
@@ -2695,7 +2695,8 @@
                                                  SourceLocation(), 0,
                                                  FieldTypes[i], 0,
                                                  /*BitWidth=*/0,
-                                                 /*Mutable=*/false));
+                                                 /*Mutable=*/false,
+                                                 /*HasInit=*/false));
     }
 
     SuperStructDecl->completeDefinition();
@@ -2727,7 +2728,8 @@
                                                     SourceLocation(), 0,
                                                     FieldTypes[i], 0,
                                                     /*BitWidth=*/0,
-                                                    /*Mutable=*/true));
+                                                    /*Mutable=*/true,
+                                                    /*HasInit=*/false));
     }
 
     ConstantStringDecl->completeDefinition();
@@ -4709,7 +4711,8 @@
                                     SourceLocation(),
                                     &Context->Idents.get("FuncPtr"),
                                     Context->VoidPtrTy, 0,
-                                    /*BitWidth=*/0, /*Mutable=*/true);
+                                    /*BitWidth=*/0, /*Mutable=*/true,
+                                    /*HasInit=*/false);
   MemberExpr *ME = new (Context) MemberExpr(PE, true, FD, SourceLocation(),
                                             FD->getType(), VK_LValue,
                                             OK_Ordinary);
@@ -4763,7 +4766,8 @@
                                     SourceLocation(),
                                     &Context->Idents.get("__forwarding"), 
                                     Context->VoidPtrTy, 0,
-                                    /*BitWidth=*/0, /*Mutable=*/true);
+                                    /*BitWidth=*/0, /*Mutable=*/true,
+                                    /*HasInit=*/false);
   MemberExpr *ME = new (Context) MemberExpr(DeclRefExp, isArrow,
                                             FD, SourceLocation(),
                                             FD->getType(), VK_LValue,
@@ -4773,7 +4777,8 @@
   FD = FieldDecl::Create(*Context, 0, SourceLocation(), SourceLocation(),
                          &Context->Idents.get(Name), 
                          Context->VoidPtrTy, 0,
-                         /*BitWidth=*/0, /*Mutable=*/true);
+                         /*BitWidth=*/0, /*Mutable=*/true,
+                         /*HasInit=*/false);
   ME = new (Context) MemberExpr(ME, true, FD, SourceLocation(),
                                 DeclRefExp->getType(), VK_LValue, OK_Ordinary);
   
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index c2fee32..9446c0e 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -2610,7 +2610,8 @@
                              /*IdentifierInfo=*/0,
                              Context.getTypeDeclType(Record),
                              TInfo,
-                             /*BitWidth=*/0, /*Mutable=*/false);
+                             /*BitWidth=*/0, /*Mutable=*/false,
+                             /*HasInit=*/false);
     Anon->setAccess(AS);
     if (getLangOptions().CPlusPlus)
       FieldCollector->Add(cast<FieldDecl>(Anon));
@@ -2700,7 +2701,8 @@
                              /*IdentifierInfo=*/0,
                              Context.getTypeDeclType(Record),
                              TInfo,
-                             /*BitWidth=*/0, /*Mutable=*/false);
+                             /*BitWidth=*/0, /*Mutable=*/false,
+                             /*HasInit=*/false);
   Anon->setImplicit();
 
   // Add the anonymous struct object to the current context.
@@ -7512,14 +7514,13 @@
   return false;
 }
 
-/// ActOnField - Each field of a struct/union/class is passed into this in order
+/// ActOnField - Each field of a C struct/union is passed into this in order
 /// to create a FieldDecl object for it.
-Decl *Sema::ActOnField(Scope *S, Decl *TagD,
-                                 SourceLocation DeclStart,
-                                 Declarator &D, ExprTy *BitfieldWidth) {
+Decl *Sema::ActOnField(Scope *S, Decl *TagD, SourceLocation DeclStart,
+                       Declarator &D, ExprTy *BitfieldWidth) {
   FieldDecl *Res = HandleField(S, cast_or_null<RecordDecl>(TagD),
                                DeclStart, D, static_cast<Expr*>(BitfieldWidth),
-                               AS_public);
+                               /*HasInit=*/false, AS_public);
   return Res;
 }
 
@@ -7527,7 +7528,7 @@
 ///
 FieldDecl *Sema::HandleField(Scope *S, RecordDecl *Record,
                              SourceLocation DeclStart,
-                             Declarator &D, Expr *BitWidth,
+                             Declarator &D, Expr *BitWidth, bool HasInit,
                              AccessSpecifier AS) {
   IdentifierInfo *II = D.getIdentifier();
   SourceLocation Loc = DeclStart;
@@ -7576,8 +7577,8 @@
     = (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);
+    = CheckFieldDecl(II, T, TInfo, Record, Loc, Mutable, BitWidth, HasInit,
+                     TSSL, AS, PrevDecl, &D);
 
   if (NewFD->isInvalidDecl())
     Record->setInvalidDecl();
@@ -7606,7 +7607,7 @@
 FieldDecl *Sema::CheckFieldDecl(DeclarationName Name, QualType T,
                                 TypeSourceInfo *TInfo,
                                 RecordDecl *Record, SourceLocation Loc,
-                                bool Mutable, Expr *BitWidth,
+                                bool Mutable, Expr *BitWidth, bool HasInit,
                                 SourceLocation TSSL,
                                 AccessSpecifier AS, NamedDecl *PrevDecl,
                                 Declarator *D) {
@@ -7686,7 +7687,7 @@
   }
 
   FieldDecl *NewFD = FieldDecl::Create(Context, Record, TSSL, Loc, II, T, TInfo,
-                                       BitWidth, Mutable);
+                                       BitWidth, Mutable, HasInit);
   if (InvalidDecl)
     NewFD->setInvalidDecl();
 
@@ -8289,16 +8290,17 @@
 
     // Now that the record is complete, do any delayed exception spec checks
     // we were missing.
-    if (!DelayedDestructorExceptionSpecChecks.empty()) {
+    while (!DelayedDestructorExceptionSpecChecks.empty()) {
       const CXXDestructorDecl *Dtor =
               DelayedDestructorExceptionSpecChecks.back().first;
-      if (Dtor->getParent() == Record) {
-        assert(!Dtor->getParent()->isDependentType() &&
-            "Should not ever add destructors of templates into the list.");
-        CheckOverridingFunctionExceptionSpec(Dtor,
-            DelayedDestructorExceptionSpecChecks.back().second);
-        DelayedDestructorExceptionSpecChecks.pop_back();
-      }
+      if (Dtor->getParent() != Record)
+        break;
+
+      assert(!Dtor->getParent()->isDependentType() &&
+          "Should not ever add destructors of templates into the list.");
+      CheckOverridingFunctionExceptionSpec(Dtor,
+          DelayedDestructorExceptionSpecChecks.back().second);
+      DelayedDestructorExceptionSpecChecks.pop_back();
     }
 
   } else {
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index a4ba5fa..ce99efb 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -113,8 +113,8 @@
 
 void Sema::ImplicitExceptionSpecification::CalledDecl(CXXMethodDecl *Method) {
   assert(Context && "ImplicitExceptionSpecification without an ASTContext");
-  // If we have an MSAny spec already, don't bother.
-  if (!Method || ComputedEST == EST_MSAny)
+  // If we have an MSAny or unknown spec already, don't bother.
+  if (!Method || ComputedEST == EST_MSAny || ComputedEST == EST_Delayed)
     return;
 
   const FunctionProtoType *Proto
@@ -123,12 +123,15 @@
   ExceptionSpecificationType EST = Proto->getExceptionSpecType();
 
   // If this function can throw any exceptions, make a note of that.
-  if (EST == EST_MSAny || EST == EST_None) {
+  if (EST == EST_Delayed || EST == EST_MSAny || EST == EST_None) {
     ClearExceptions();
     ComputedEST = EST;
     return;
   }
 
+  // FIXME: If the call to this decl is using any of its default arguments, we
+  // need to search them for potentially-throwing calls.
+
   // If this function has a basic noexcept, it doesn't affect the outcome.
   if (EST == EST_BasicNoexcept)
     return;
@@ -175,6 +178,35 @@
       Exceptions.push_back(*E);
 }
 
+void Sema::ImplicitExceptionSpecification::CalledExpr(Expr *E) {
+  if (!E || ComputedEST == EST_MSAny || ComputedEST == EST_Delayed)
+    return;
+
+  // FIXME:
+  //
+  // C++0x [except.spec]p14:
+  //   [An] implicit exception-speciļ¬cation speciļ¬es the type-id T if and
+  // only if T is allowed by the exception-speciļ¬cation of a function directly
+  // invoked by f’s implicit deļ¬nition; f shall allow all exceptions if any
+  // function it directly invokes allows all exceptions, and f shall allow no
+  // exceptions if every function it directly invokes allows no exceptions.
+  //
+  // Note in particular that if an implicit exception-specification is generated
+  // for a function containing a throw-expression, that specification can still
+  // be noexcept(true).
+  //
+  // Note also that 'directly invoked' is not defined in the standard, and there
+  // is no indication that we should only consider potentially-evaluated calls.
+  //
+  // Ultimately we should implement the intent of the standard: the exception
+  // specification should be the set of exceptions which can be thrown by the
+  // implicit definition. For now, we assume that any non-nothrow expression can
+  // throw any exception.
+
+  if (E->CanThrow(*Context))
+    ComputedEST = EST_None;
+}
+
 bool
 Sema::SetParamDefaultArgument(ParmVarDecl *Param, Expr *Arg,
                               SourceLocation EqualLoc) {
@@ -1029,13 +1061,15 @@
 
 /// 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.
+/// bitfield width if there is one, 'InitExpr' specifies the initializer if
+/// one has been parsed, and 'HasDeferredInit' is true if an initializer is
+/// present but parsing it has been deferred.
 Decl *
 Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D,
                                MultiTemplateParamsArg TemplateParameterLists,
                                ExprTy *BW, const VirtSpecifiers &VS,
-                               ExprTy *InitExpr, bool IsDefinition) {
+                               ExprTy *InitExpr, bool HasDeferredInit,
+                               bool IsDefinition) {
   const DeclSpec &DS = D.getDeclSpec();
   DeclarationNameInfo NameInfo = GetNameForDeclarator(D);
   DeclarationName Name = NameInfo.getName();
@@ -1050,6 +1084,7 @@
 
   assert(isa<CXXRecordDecl>(CurContext));
   assert(!DS.isFriendSpecified());
+  assert(!Init || !HasDeferredInit);
 
   bool isFunc = false;
   if (D.isFunctionDeclarator())
@@ -1121,9 +1156,11 @@
     // FIXME: Check for template parameters!
     // FIXME: Check that the name is an identifier!
     Member = HandleField(S, cast<CXXRecordDecl>(CurContext), Loc, D, BitWidth,
-                         AS);
+                         HasDeferredInit, AS);
     assert(Member && "HandleField never returns null");
   } else {
+    assert(!HasDeferredInit);
+
     Member = HandleDeclarator(S, D, move(TemplateParameterLists), IsDefinition);
     if (!Member) {
       return 0;
@@ -1194,6 +1231,14 @@
   if (Init)
     AddInitializerToDecl(Member, Init, false,
                          DS.getTypeSpecType() == DeclSpec::TST_auto);
+  else if (DS.getTypeSpecType() == DeclSpec::TST_auto &&
+           DS.getStorageClassSpec() == DeclSpec::SCS_static) {
+    // C++0x [dcl.spec.auto]p4: 'auto' can only be used in the type of a static
+    // data member if a brace-or-equal-initializer is provided.
+    Diag(Loc, diag::err_auto_var_requires_init)
+      << Name << cast<ValueDecl>(Member)->getType();
+    Member->setInvalidDecl();
+  }
 
   FinalizeDeclaration(Member);
 
@@ -1202,6 +1247,47 @@
   return Member;
 }
 
+/// ActOnCXXInClassMemberInitializer - This is invoked after parsing an
+/// in-class initializer for a non-static C++ class member. Such parsing
+/// is deferred until the class is complete.
+void
+Sema::ActOnCXXInClassMemberInitializer(Decl *D, SourceLocation EqualLoc,
+                                       Expr *InitExpr) {
+  FieldDecl *FD = cast<FieldDecl>(D);
+
+  if (!InitExpr) {
+    FD->setInvalidDecl();
+    FD->removeInClassInitializer();
+    return;
+  }
+
+  ExprResult Init = InitExpr;
+  if (!FD->getType()->isDependentType() && !InitExpr->isTypeDependent()) {
+    // FIXME: if there is no EqualLoc, this is list-initialization.
+    Init = PerformCopyInitialization(
+      InitializedEntity::InitializeMember(FD), EqualLoc, InitExpr);
+    if (Init.isInvalid()) {
+      FD->setInvalidDecl();
+      return;
+    }
+
+    CheckImplicitConversions(Init.get(), EqualLoc);
+  }
+
+  // C++0x [class.base.init]p7:
+  //   The initialization of each base and member constitutes a
+  //   full-expression.
+  Init = MaybeCreateExprWithCleanups(Init);
+  if (Init.isInvalid()) {
+    FD->setInvalidDecl();
+    return;
+  }
+
+  InitExpr = Init.release();
+
+  FD->setInClassInitializer(InitExpr);
+}
+
 /// \brief Find the direct and/or virtual base specifiers that
 /// correspond to the given base type, for use in base initialization
 /// within a constructor.
@@ -2073,7 +2159,7 @@
 };
 }
 
-static bool CollectFieldInitializer(BaseAndFieldInfo &Info,
+static bool CollectFieldInitializer(Sema &SemaRef, BaseAndFieldInfo &Info,
                                     FieldDecl *Top, FieldDecl *Field) {
 
   // Overwhelmingly common case: we have a direct initializer for this field.
@@ -2082,6 +2168,18 @@
     return false;
   }
 
+  // C++0x [class.base.init]p8: if the entity is a non-static data member that
+  // has a brace-or-equal-initializer, the entity is initialized as specified
+  // in [dcl.init].
+  if (Field->hasInClassInitializer()) {
+    Info.AllToInit.push_back(
+      new (SemaRef.Context) CXXCtorInitializer(SemaRef.Context, Field,
+                                               SourceLocation(),
+                                               SourceLocation(), 0,
+                                               SourceLocation()));
+    return false;
+  }
+
   if (Info.IIK == IIK_Default && Field->isAnonymousStructOrUnion()) {
     const RecordType *FieldClassType = Field->getType()->getAs<RecordType>();
     assert(FieldClassType && "anonymous struct/union without record type");
@@ -2104,7 +2202,7 @@
           // field in the class is also initialized, so exit immediately.
           return false;
         } else if ((*FA)->isAnonymousStructOrUnion()) {
-          if (CollectFieldInitializer(Info, Top, *FA))
+          if (CollectFieldInitializer(SemaRef, Info, Top, *FA))
             return true;
         }
       }
@@ -2119,7 +2217,7 @@
       // necessary.
       for (RecordDecl::field_iterator FA = FieldClassDecl->field_begin(),
            EA = FieldClassDecl->field_end(); FA != EA; FA++) {
-        if (CollectFieldInitializer(Info, Top, *FA))
+        if (CollectFieldInitializer(SemaRef, Info, Top, *FA))
           return true;
       }
     }
@@ -2128,7 +2226,7 @@
   // Don't try to build an implicit initializer if there were semantic
   // errors in any of the initializers (and therefore we might be
   // missing some that the user actually wrote).
-  if (Info.AnyErrorsInInits)
+  if (Info.AnyErrorsInInits || Field->isInvalidDecl())
     return false;
 
   CXXCtorInitializer *Init = 0;
@@ -2260,7 +2358,7 @@
              "Incomplete array type is not valid");
       continue;
     }
-    if (CollectFieldInitializer(Info, *Field, *Field))
+    if (CollectFieldInitializer(*this, Info, *Field, *Field))
       HadError = true;
   }
 
@@ -2939,6 +3037,9 @@
     for (RecordDecl::field_iterator F = Record->field_begin(), 
                                  FEnd = Record->field_end();
          F != FEnd; ++F) {
+      if (F->hasInClassInitializer())
+        continue;
+
       if (F->getType()->isReferenceType() ||
           (F->getType().isConstQualified() && F->getType()->isScalarType())) {
         if (!Complained) {
@@ -3066,6 +3167,11 @@
   ImplicitExceptionSpecification Spec
     = ComputeDefaultedDefaultCtorExceptionSpec(CD->getParent());
   FunctionProtoType::ExtProtoInfo EPI = Spec.getEPI();
+  if (EPI.ExceptionSpecType == EST_Delayed) {
+    // Exception specification depends on some deferred part of the class. We'll
+    // try again when the class's definition has been fully processed.
+    return;
+  }
   const FunctionProtoType *CtorType = CD->getType()->getAs<FunctionProtoType>(),
                           *ExceptionType = Context.getFunctionType(
                          Context.VoidTy, 0, 0, EPI)->getAs<FunctionProtoType>();
@@ -3383,12 +3489,15 @@
   for (CXXRecordDecl::field_iterator FI = RD->field_begin(),
                                      FE = RD->field_end();
        FI != FE; ++FI) {
+    if (FI->isInvalidDecl())
+      continue;
+    
     QualType FieldType = Context.getBaseElementType(FI->getType());
     CXXRecordDecl *FieldRecord = FieldType->getAsCXXRecordDecl();
-    
+
     // -- any non-static data member with no brace-or-equal-initializer is of
     //    reference type
-    if (FieldType->isReferenceType())
+    if (FieldType->isReferenceType() && !FI->hasInClassInitializer())
       return true;
 
     // -- X is a union and all its variant members are of const-qualified type
@@ -3413,6 +3522,7 @@
       //    array thereof) with no brace-or-equal-initializer does not have a
       //    user-provided default constructor
       if (FieldType.isConstQualified() &&
+          !FI->hasInClassInitializer() &&
           !FieldRecord->hasUserProvidedDefaultConstructor())
         return true;
  
@@ -3445,18 +3555,21 @@
         continue;
       }
 
-      // -- any non-static data member ... has class type M (or array thereof)
-      //    and either M has no default constructor or overload resolution as
-      //    applied to M's default constructor results in an ambiguity or in a
-      //    function that is deleted or inaccessible from the defaulted default
-      //    constructor.
-      CXXConstructorDecl *FieldDefault = LookupDefaultConstructor(FieldRecord);
-      if (!FieldDefault || FieldDefault->isDeleted())
-        return true;
-      if (CheckConstructorAccess(Loc, FieldDefault, FieldDefault->getAccess(),
-                                 PDiag()) != AR_accessible)
-        return true;
-    } else if (!Union && FieldType.isConstQualified()) {
+      // -- any non-static data member with no brace-or-equal-initializer has
+      //    class type M (or array thereof) and either M has no default
+      //    constructor or overload resolution as applied to M's default
+      //    constructor results in an ambiguity or in a function that is deleted
+      //    or inaccessible from the defaulted default constructor.
+      if (!FI->hasInClassInitializer()) {
+        CXXConstructorDecl *FieldDefault = LookupDefaultConstructor(FieldRecord);
+        if (!FieldDefault || FieldDefault->isDeleted())
+          return true;
+        if (CheckConstructorAccess(Loc, FieldDefault, FieldDefault->getAccess(),
+                                   PDiag()) != AR_accessible)
+          return true;
+      }
+    } else if (!Union && FieldType.isConstQualified() &&
+               !FI->hasInClassInitializer()) {
       // -- any non-variant non-static data member of const-qualified type (or
       //    array thereof) with no brace-or-equal-initializer does not have a
       //    user-provided default constructor
@@ -5905,7 +6018,12 @@
   for (RecordDecl::field_iterator F = ClassDecl->field_begin(),
                                FEnd = ClassDecl->field_end();
        F != FEnd; ++F) {
-    if (const RecordType *RecordTy
+    if (F->hasInClassInitializer()) {
+      if (Expr *E = F->getInClassInitializer())
+        ExceptSpec.CalledExpr(E);
+      else if (!F->isInvalidDecl())
+        ExceptSpec.SetDelayed();
+    } else if (const RecordType *RecordTy
               = Context.getBaseElementType(F->getType())->getAs<RecordType>()) {
       CXXRecordDecl *FieldRecDecl = cast<CXXRecordDecl>(RecordTy->getDecl());
       CXXConstructorDecl *Constructor = LookupDefaultConstructor(FieldRecDecl);
@@ -6001,6 +6119,59 @@
   }
 }
 
+/// Get any existing defaulted default constructor for the given class. Do not
+/// implicitly define one if it does not exist.
+static CXXConstructorDecl *getDefaultedDefaultConstructorUnsafe(Sema &Self,
+                                                             CXXRecordDecl *D) {
+  ASTContext &Context = Self.Context;
+  QualType ClassType = Context.getTypeDeclType(D);
+  DeclarationName ConstructorName
+    = Context.DeclarationNames.getCXXConstructorName(
+                      Context.getCanonicalType(ClassType.getUnqualifiedType()));
+
+  DeclContext::lookup_const_iterator Con, ConEnd;
+  for (llvm::tie(Con, ConEnd) = D->lookup(ConstructorName);
+       Con != ConEnd; ++Con) {
+    // A function template cannot be defaulted.
+    if (isa<FunctionTemplateDecl>(*Con))
+      continue;
+
+    CXXConstructorDecl *Constructor = cast<CXXConstructorDecl>(*Con);
+    if (Constructor->isDefaultConstructor())
+      return Constructor->isDefaulted() ? Constructor : 0;
+  }
+  return 0;
+}
+
+void Sema::ActOnFinishDelayedMemberInitializers(Decl *D) {
+  if (!D) return;
+  AdjustDeclIfTemplate(D);
+
+  CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(D);
+  CXXConstructorDecl *CtorDecl
+    = getDefaultedDefaultConstructorUnsafe(*this, ClassDecl);
+
+  if (!CtorDecl) return;
+
+  // Compute the exception specification for the default constructor.
+  const FunctionProtoType *CtorTy =
+    CtorDecl->getType()->castAs<FunctionProtoType>();
+  if (CtorTy->getExceptionSpecType() == EST_Delayed) {
+    ImplicitExceptionSpecification Spec = 
+      ComputeDefaultedDefaultCtorExceptionSpec(ClassDecl);
+    FunctionProtoType::ExtProtoInfo EPI = Spec.getEPI();
+    assert(EPI.ExceptionSpecType != EST_Delayed);
+
+    CtorDecl->setType(Context.getFunctionType(Context.VoidTy, 0, 0, EPI));
+  }
+
+  // If the default constructor is explicitly defaulted, checking the exception
+  // specification is deferred until now.
+  if (!CtorDecl->isInvalidDecl() && CtorDecl->isExplicitlyDefaulted() &&
+      !ClassDecl->isDependentType())
+    CheckExplicitlyDefaultedDefaultConstructor(CtorDecl);
+}
+
 void Sema::DeclareInheritedConstructors(CXXRecordDecl *ClassDecl) {
   // We start with an initial pass over the base classes to collect those that
   // inherit constructors from. If there are none, we can forgo all further
@@ -6094,7 +6265,9 @@
         // Build up a function type for this particular constructor.
         // FIXME: The working paper does not consider that the exception spec
         // for the inheriting constructor might be larger than that of the
-        // source. This code doesn't yet, either.
+        // source. This code doesn't yet, either. When it does, this code will
+        // need to be delayed until after exception specifications and in-class
+        // member initializers are attached.
         const Type *NewCtorType;
         if (params == maxParams)
           NewCtorType = BaseCtorType;
diff --git a/lib/Sema/SemaExceptionSpec.cpp b/lib/Sema/SemaExceptionSpec.cpp
index 0f6108c..7bcec31 100644
--- a/lib/Sema/SemaExceptionSpec.cpp
+++ b/lib/Sema/SemaExceptionSpec.cpp
@@ -298,8 +298,6 @@
   //   - both are non-throwing, regardless of their form,
   //   - both have the form noexcept(constant-expression) and the constant-
   //     expressions are equivalent,
-  //   - one exception-specification is a noexcept-specification allowing all
-  //     exceptions and the other is of the form throw(type-id-list), or
   //   - both are dynamic-exception-specifications that have the same set of
   //     adjusted types.
   //
@@ -307,8 +305,6 @@
   //   of the form throw(), noexcept, or noexcept(constant-expression) where the
   //   constant-expression yields true.
   //
-  // CWG 1073 Proposed resolution: Strike the third bullet above.
-  //
   // C++0x [except.spec]p4: If any declaration of a function has an exception-
   //   specifier that is not a noexcept-specification allowing all exceptions,
   //   all declarations [...] of that function shall have a compatible
@@ -320,6 +316,9 @@
   ExceptionSpecificationType OldEST = Old->getExceptionSpecType();
   ExceptionSpecificationType NewEST = New->getExceptionSpecType();
 
+  assert(OldEST != EST_Delayed && NewEST != EST_Delayed &&
+         "Shouldn't see unknown exception specifications here");
+
   // Shortcut the case where both have no spec.
   if (OldEST == EST_None && NewEST == EST_None)
     return false;
@@ -506,6 +505,9 @@
 
   ExceptionSpecificationType SubEST = Subset->getExceptionSpecType();
 
+  assert(SuperEST != EST_Delayed && SubEST != EST_Delayed &&
+         "Shouldn't see unknown exception specifications here");
+
   // It does not. If the subset contains everything, we've failed.
   if (SubEST == EST_None || SubEST == EST_MSAny) {
     Diag(SubLoc, DiagID);
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index dafd56b..0549e94 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -1333,8 +1333,8 @@
     // 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".
-    CXXMethodDecl *method = tryCaptureCXXThis();
-    if (!method) {
+    QualType ThisTy = getAndCaptureCurrentThisType();
+    if (ThisTy.isNull()) {
       Diag(loc, diag::err_invalid_member_use_in_static_method)
         << indirectField->getDeclName();
       return ExprError();
@@ -1342,10 +1342,9 @@
 
     // Our base object expression is "this".
     baseObjectExpr =
-      new (Context) CXXThisExpr(loc, method->getThisType(Context),
-                                /*isImplicit=*/ true);
+      new (Context) CXXThisExpr(loc, ThisTy, /*isImplicit=*/ true);
     baseObjectIsPointer = true;
-    baseQuals = Qualifiers::fromCVRMask(method->getTypeQualifiers());
+    baseQuals = ThisTy->castAs<PointerType>()->getPointeeType().getQualifiers();
   }
 
   // Build the implicit member references to the field of the
@@ -1492,14 +1491,23 @@
 /// conservatively answer "yes", in which case some errors will simply
 /// not be caught until template-instantiation.
 static IMAKind ClassifyImplicitMemberAccess(Sema &SemaRef,
+                                            Scope *CurScope,
                                             const LookupResult &R) {
   assert(!R.empty() && (*R.begin())->isCXXClassMember());
 
   DeclContext *DC = SemaRef.getFunctionLevelDeclContext();
+
   bool isStaticContext =
     (!isa<CXXMethodDecl>(DC) ||
      cast<CXXMethodDecl>(DC)->isStatic());
 
+  // C++0x [expr.prim]p4:
+  //   Otherwise, if a member-declarator declares a non-static data member
+  // of a class X, the expression this is a prvalue of type "pointer to X"
+  // within the optional brace-or-equal-initializer.
+  if (CurScope->getFlags() & Scope::ThisScope)
+    isStaticContext = false;
+
   if (R.isUnresolvableResult())
     return isStaticContext ? IMA_Unresolved_StaticContext : IMA_Unresolved;
 
@@ -1547,8 +1555,11 @@
     return IMA_Error_StaticContext;
   }
 
-  CXXRecordDecl *
-        contextClass = cast<CXXMethodDecl>(DC)->getParent()->getCanonicalDecl();
+  CXXRecordDecl *contextClass;
+  if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(DC))
+    contextClass = MD->getParent()->getCanonicalDecl();
+  else
+    contextClass = cast<CXXRecordDecl>(DC);
 
   // [class.mfct.non-static]p3: 
   // ...is used in the body of a non-static member function of class X,
@@ -2026,7 +2037,7 @@
 Sema::BuildPossibleImplicitMemberExpr(const CXXScopeSpec &SS,
                                       LookupResult &R,
                                 const TemplateArgumentListInfo *TemplateArgs) {
-  switch (ClassifyImplicitMemberAccess(*this, R)) {
+  switch (ClassifyImplicitMemberAccess(*this, CurScope, R)) {
   case IMA_Instance:
     return BuildImplicitMemberExpr(SS, R, TemplateArgs, true);
 
@@ -2469,19 +2480,18 @@
   // If this is known to be an instance access, go ahead and build an
   // implicit 'this' expression now.
   // 'this' expression now.
-  CXXMethodDecl *method = tryCaptureCXXThis();
-  assert(method && "didn't correctly pre-flight capture of 'this'");
+  QualType ThisTy = getAndCaptureCurrentThisType();
+  assert(!ThisTy.isNull() && "didn't correctly pre-flight capture of 'this'");
 
-  QualType thisType = method->getThisType(Context);
   Expr *baseExpr = 0; // null signifies implicit access
   if (IsKnownInstance) {
     SourceLocation Loc = R.getNameLoc();
     if (SS.getRange().isValid())
       Loc = SS.getRange().getBegin();
-    baseExpr = new (Context) CXXThisExpr(loc, thisType, /*isImplicit=*/true);
+    baseExpr = new (Context) CXXThisExpr(loc, ThisTy, /*isImplicit=*/true);
   }
 
-  return BuildMemberReferenceExpr(baseExpr, thisType,
+  return BuildMemberReferenceExpr(baseExpr, ThisTy,
                                   /*OpLoc*/ SourceLocation(),
                                   /*IsArrow*/ true,
                                   SS,
diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp
index 50462ab..2f5a890 100644
--- a/lib/Sema/SemaExprCXX.cpp
+++ b/lib/Sema/SemaExprCXX.cpp
@@ -17,6 +17,7 @@
 #include "clang/Sema/Lookup.h"
 #include "clang/Sema/ParsedTemplate.h"
 #include "clang/Sema/ScopeInfo.h"
+#include "clang/Sema/Scope.h"
 #include "clang/Sema/TemplateDeduction.h"
 #include "clang/AST/ASTContext.h"
 #include "clang/AST/CXXInheritance.h"
@@ -575,42 +576,54 @@
   return Owned(E);
 }
 
-CXXMethodDecl *Sema::tryCaptureCXXThis() {
+QualType Sema::getAndCaptureCurrentThisType() {
   // Ignore block scopes: we can capture through them.
   // Ignore nested enum scopes: we'll diagnose non-constant expressions
   // where they're invalid, and other uses are legitimate.
   // Don't ignore nested class scopes: you can't use 'this' in a local class.
   DeclContext *DC = CurContext;
+  unsigned NumBlocks = 0;
   while (true) {
-    if (isa<BlockDecl>(DC)) DC = cast<BlockDecl>(DC)->getDeclContext();
-    else if (isa<EnumDecl>(DC)) DC = cast<EnumDecl>(DC)->getDeclContext();
+    if (isa<BlockDecl>(DC)) {
+      DC = cast<BlockDecl>(DC)->getDeclContext();
+      ++NumBlocks;
+    } else if (isa<EnumDecl>(DC))
+      DC = cast<EnumDecl>(DC)->getDeclContext();
     else break;
   }
 
-  // If we're not in an instance method, error out.
-  CXXMethodDecl *method = dyn_cast<CXXMethodDecl>(DC);
-  if (!method || !method->isInstance())
-    return 0;
+  QualType ThisTy;
+  if (CXXMethodDecl *method = dyn_cast<CXXMethodDecl>(DC)) {
+    if (method && method->isInstance())
+      ThisTy = method->getThisType(Context);
+  } else if (CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(DC)) {
+    // C++0x [expr.prim]p4:
+    //   Otherwise, if a member-declarator declares a non-static data member
+    // of a class X, the expression this is a prvalue of type "pointer to X"
+    // within the optional brace-or-equal-initializer.
+    Scope *S = getScopeForContext(DC);
+    if (!S || S->getFlags() & Scope::ThisScope)
+      ThisTy = Context.getPointerType(Context.getRecordType(RD));
+  }
 
-  // Mark that we're closing on 'this' in all the block scopes, if applicable.
-  for (unsigned idx = FunctionScopes.size() - 1;
-       isa<BlockScopeInfo>(FunctionScopes[idx]);
-       --idx)
-    cast<BlockScopeInfo>(FunctionScopes[idx])->CapturesCXXThis = true;
+  // Mark that we're closing on 'this' in all the block scopes we ignored.
+  if (!ThisTy.isNull())
+    for (unsigned idx = FunctionScopes.size() - 1;
+         NumBlocks; --idx, --NumBlocks)
+      cast<BlockScopeInfo>(FunctionScopes[idx])->CapturesCXXThis = true;
 
-  return method;
+  return ThisTy;
 }
 
-ExprResult Sema::ActOnCXXThis(SourceLocation loc) {
+ExprResult Sema::ActOnCXXThis(SourceLocation Loc) {
   /// 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.
 
-  CXXMethodDecl *method = tryCaptureCXXThis();
-  if (!method) return Diag(loc, diag::err_invalid_this_use);
+  QualType ThisTy = getAndCaptureCurrentThisType();
+  if (ThisTy.isNull()) return Diag(Loc, diag::err_invalid_this_use);
 
-  return Owned(new (Context) CXXThisExpr(loc, method->getThisType(Context),
-                                         /*isImplicit=*/false));
+  return Owned(new (Context) CXXThisExpr(Loc, ThisTy, /*isImplicit=*/false));
 }
 
 ExprResult
@@ -2663,7 +2676,6 @@
         return true;
 
       bool FoundAssign = false;
-      bool AllNoThrow = true;
       DeclarationName Name = C.DeclarationNames.getCXXOperatorName(OO_Equal);
       LookupResult Res(Self, DeclarationNameInfo(Name, KeyLoc),
                        Sema::LookupOrdinaryName);
@@ -2675,15 +2687,15 @@
             FoundAssign = true;
             const FunctionProtoType *CPT
                 = Operator->getType()->getAs<FunctionProtoType>();
-            if (!CPT->isNothrow(Self.Context)) {
-              AllNoThrow = false;
-              break;
-            }
+            if (CPT->getExceptionSpecType() == EST_Delayed)
+              return false;
+            if (!CPT->isNothrow(Self.Context))
+              return false;
           }
         }
       }
 
-      return FoundAssign && AllNoThrow;
+      return FoundAssign;
     }
     return false;
   case UTT_HasNothrowCopy:
@@ -2700,7 +2712,6 @@
         return true;
 
       bool FoundConstructor = false;
-      bool AllNoThrow = true;
       unsigned FoundTQs;
       DeclContext::lookup_const_iterator Con, ConEnd;
       for (llvm::tie(Con, ConEnd) = Self.LookupConstructors(RD);
@@ -2715,16 +2726,16 @@
           FoundConstructor = true;
           const FunctionProtoType *CPT
               = Constructor->getType()->getAs<FunctionProtoType>();
+          if (CPT->getExceptionSpecType() == EST_Delayed)
+            return false;
           // FIXME: check whether evaluating default arguments can throw.
           // For now, we'll be conservative and assume that they can throw.
-          if (!CPT->isNothrow(Self.Context) || CPT->getNumArgs() > 1) {
-            AllNoThrow = false;
-            break;
-          }
+          if (!CPT->isNothrow(Self.Context) || CPT->getNumArgs() > 1)
+            return false;
         }
       }
 
-      return FoundConstructor && AllNoThrow;
+      return FoundConstructor;
     }
     return false;
   case UTT_HasNothrowConstructor:
@@ -2750,6 +2761,8 @@
         if (Constructor->isDefaultConstructor()) {
           const FunctionProtoType *CPT
               = Constructor->getType()->getAs<FunctionProtoType>();
+          if (CPT->getExceptionSpecType() == EST_Delayed)
+            return false;
           // TODO: check whether evaluating default arguments can throw.
           // For now, we'll be conservative and assume that they can throw.
           return CPT->isNothrow(Self.Context) && CPT->getNumArgs() == 0;
diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp
index 444fb9a..3c19641 100644
--- a/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/lib/Sema/SemaTemplateInstantiate.cpp
@@ -13,6 +13,7 @@
 #include "clang/Sema/SemaInternal.h"
 #include "TreeTransform.h"
 #include "clang/Sema/DeclSpec.h"
+#include "clang/Sema/Initialization.h"
 #include "clang/Sema/Lookup.h"
 #include "clang/Sema/Template.h"
 #include "clang/Sema/TemplateDeduction.h"
@@ -1744,6 +1745,8 @@
 
   TemplateDeclInstantiator Instantiator(*this, Instantiation, TemplateArgs);
   llvm::SmallVector<Decl*, 4> Fields;
+  llvm::SmallVector<std::pair<FieldDecl*, FieldDecl*>, 4>
+    FieldsWithMemberInitializers;
   for (RecordDecl::decl_iterator Member = Pattern->decls_begin(),
          MemberEnd = Pattern->decls_end();
        Member != MemberEnd; ++Member) {
@@ -1766,9 +1769,13 @@
 
     Decl *NewMember = Instantiator.Visit(*Member);
     if (NewMember) {
-      if (FieldDecl *Field = dyn_cast<FieldDecl>(NewMember))
+      if (FieldDecl *Field = dyn_cast<FieldDecl>(NewMember)) {
         Fields.push_back(Field);
-      else if (NewMember->isInvalidDecl())
+        FieldDecl *OldField = cast<FieldDecl>(*Member);
+        if (OldField->getInClassInitializer())
+          FieldsWithMemberInitializers.push_back(std::make_pair(OldField,
+                                                                Field));
+      } else if (NewMember->isInvalidDecl())
         Invalid = true;
     } else {
       // FIXME: Eventually, a NULL return will mean that one of the
@@ -1782,6 +1789,43 @@
               Fields.data(), Fields.size(), SourceLocation(), SourceLocation(),
               0);
   CheckCompletedCXXClass(Instantiation);
+
+  // Attach any in-class member initializers now the class is complete.
+  for (unsigned I = 0, N = FieldsWithMemberInitializers.size(); I != N; ++I) {
+    FieldDecl *OldField = FieldsWithMemberInitializers[I].first;
+    FieldDecl *NewField = FieldsWithMemberInitializers[I].second;
+    Expr *OldInit = OldField->getInClassInitializer();
+    ExprResult NewInit = SubstExpr(OldInit, TemplateArgs);
+
+    // If the initialization is no longer dependent, check it now.
+    if ((OldField->getType()->isDependentType() || OldInit->isTypeDependent())
+        && !NewField->getType()->isDependentType()
+        && !NewInit.get()->isTypeDependent()) {
+      // FIXME: handle list-initialization
+      SourceLocation EqualLoc = NewField->getLocation();
+      NewInit = PerformCopyInitialization(
+        InitializedEntity::InitializeMember(NewField), EqualLoc,
+        NewInit.release());
+
+      if (!NewInit.isInvalid()) {
+        CheckImplicitConversions(NewInit.get(), EqualLoc);
+
+        // C++0x [class.base.init]p7:
+        //   The initialization of each base and member constitutes a
+        //   full-expression.
+        NewInit = MaybeCreateExprWithCleanups(NewInit);
+      }
+    }
+
+    if (NewInit.isInvalid())
+      NewField->setInvalidDecl();
+    else
+      NewField->setInClassInitializer(NewInit.release());
+  }
+
+  if (!FieldsWithMemberInitializers.empty())
+    ActOnFinishDelayedMemberInitializers(Instantiation);
+
   if (Instantiation->isInvalidDecl())
     Invalid = true;
   else {
diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp
index 22db4c8..e78aa29 100644
--- a/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -477,6 +477,7 @@
                                             D->getLocation(),
                                             D->isMutable(),
                                             BitWidth,
+                                            D->hasInClassInitializer(),
                                             D->getTypeSpecStartLoc(),
                                             D->getAccess(),
                                             0);
diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp
index e7f9885..5fd8afa 100644
--- a/lib/Sema/SemaType.cpp
+++ b/lib/Sema/SemaType.cpp
@@ -1593,6 +1593,8 @@
       Error = 0; // Function prototype
       break;
     case Declarator::MemberContext:
+      if (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_static)
+        break;
       switch (cast<TagDecl>(CurContext)->getTagKind()) {
       case TTK_Enum: assert(0 && "unhandled tag kind"); break;
       case TTK_Struct: Error = 1; /* Struct member */ break;
diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h
index 245499e..ff2e46a 100644
--- a/lib/Sema/TreeTransform.h
+++ b/lib/Sema/TreeTransform.h
@@ -6697,8 +6697,12 @@
 ExprResult
 TreeTransform<Derived>::TransformCXXThisExpr(CXXThisExpr *E) {
   DeclContext *DC = getSema().getFunctionLevelDeclContext();
-  CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(DC);
-  QualType T = MD->getThisType(getSema().Context);
+  QualType T;
+  if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(DC))
+    T = MD->getThisType(getSema().Context);
+  else
+    T = getSema().Context.getPointerType(
+      getSema().Context.getRecordType(cast<CXXRecordDecl>(DC)));
 
   if (!getDerived().AlwaysRebuild() && T == E->getType())
     return SemaRef.Owned(E);
diff --git a/lib/Serialization/ASTReaderDecl.cpp b/lib/Serialization/ASTReaderDecl.cpp
index 6e9d4d4..fab2069 100644
--- a/lib/Serialization/ASTReaderDecl.cpp
+++ b/lib/Serialization/ASTReaderDecl.cpp
@@ -677,8 +677,11 @@
 void ASTDeclReader::VisitFieldDecl(FieldDecl *FD) {
   VisitDeclaratorDecl(FD);
   FD->setMutable(Record[Idx++]);
-  if (Record[Idx++])
+  int BitWidthOrInitializer = Record[Idx++];
+  if (BitWidthOrInitializer == 1)
     FD->setBitWidth(Reader.ReadExpr(F));
+  else if (BitWidthOrInitializer == 2)
+    FD->setInClassInitializer(Reader.ReadExpr(F));
   if (!FD->getDeclName()) {
     FieldDecl *Tmpl = cast_or_null<FieldDecl>(Reader.GetDecl(Record[Idx++]));
     if (Tmpl)
@@ -1649,7 +1652,7 @@
     break;
   case DECL_FIELD:
     D = FieldDecl::Create(*Context, 0, SourceLocation(), SourceLocation(), 0,
-                          QualType(), 0, 0, false);
+                          QualType(), 0, 0, false, false);
     break;
   case DECL_INDIRECTFIELD:
     D = IndirectFieldDecl::Create(*Context, 0, SourceLocation(), 0, QualType(),
diff --git a/lib/Serialization/ASTWriterDecl.cpp b/lib/Serialization/ASTWriterDecl.cpp
index c6b159c..7c24088 100644
--- a/lib/Serialization/ASTWriterDecl.cpp
+++ b/lib/Serialization/ASTWriterDecl.cpp
@@ -599,9 +599,11 @@
 void ASTDeclWriter::VisitFieldDecl(FieldDecl *D) {
   VisitDeclaratorDecl(D);
   Record.push_back(D->isMutable());
-  Record.push_back(D->getBitWidth()? 1 : 0);
+  Record.push_back(D->getBitWidth()? 1 : D->hasInClassInitializer() ? 2 : 0);
   if (D->getBitWidth())
     Writer.AddStmt(D->getBitWidth());
+  else if (D->hasInClassInitializer())
+    Writer.AddStmt(D->getInClassInitializer());
   if (!D->getDeclName())
     Writer.AddDeclRef(Context.getInstantiatedFromUnnamedFieldDecl(D), Record);
 
@@ -612,6 +614,7 @@
       !D->isReferenced() &&
       D->getPCHLevel() == 0 &&
       !D->getBitWidth() &&
+      !D->hasInClassInitializer() &&
       !D->hasExtInfo() &&
       !ObjCIvarDecl::classofKind(D->getKind()) &&
       !ObjCAtDefsFieldDecl::classofKind(D->getKind()) &&