From 53992adde3eda3ccf9da63bc7e45673f043de18f Mon Sep 17 00:00:00 2001
From: rdivacky <rdivacky@FreeBSD.org>
Date: Thu, 27 May 2010 15:17:06 +0000
Subject: Update clang to r104832.

---
 lib/Sema/SemaDeclCXX.cpp | 605 +++++++++++++++++++++++++++++++----------------
 1 file changed, 397 insertions(+), 208 deletions(-)

(limited to 'lib/Sema/SemaDeclCXX.cpp')

diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index b9c7d79..148d146 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -461,7 +461,7 @@ Sema::CheckBaseSpecifier(CXXRecordDecl *Class,
 
   if (BaseType->isDependentType())
     return new (Context) CXXBaseSpecifier(SpecifierRange, Virtual,
-                                Class->getTagKind() == RecordDecl::TK_class,
+                                Class->getTagKind() == TTK_Class,
                                 Access, BaseType);
 
   // Base specifiers must be record types.
@@ -504,9 +504,8 @@ Sema::CheckBaseSpecifier(CXXRecordDecl *Class,
   SetClassDeclAttributesFromBase(Class, CXXBaseDecl, Virtual);
   
   // Create the base specifier.
-  // FIXME: Allocate via ASTContext?
   return new (Context) CXXBaseSpecifier(SpecifierRange, Virtual,
-                              Class->getTagKind() == RecordDecl::TK_class,
+                              Class->getTagKind() == TTK_Class,
                               Access, BaseType);
 }
 
@@ -623,7 +622,13 @@ bool Sema::AttachBaseSpecifiers(CXXRecordDecl *Class, CXXBaseSpecifier **Bases,
     QualType NewBaseType
       = Context.getCanonicalType(Bases[idx]->getType());
     NewBaseType = NewBaseType.getLocalUnqualifiedType();
-
+    if (!Class->hasObjectMember()) {
+      if (const RecordType *FDTTy = 
+            NewBaseType.getTypePtr()->getAs<RecordType>())
+        if (FDTTy->getDecl()->hasObjectMember())
+          Class->setHasObjectMember(true);
+    }
+    
     if (KnownBaseTypes[NewBaseType]) {
       // C++ [class.mi]p3:
       //   A class shall not be specified as a direct base class of a
@@ -736,6 +741,18 @@ void Sema::BuildBasePathArray(const CXXBasePaths &Paths,
     BasePathArray.push_back(Path[I].Base);
 }
 
+/// \brief Determine whether the given base path includes a virtual
+/// base class.
+bool Sema::BasePathInvolvesVirtualBase(const CXXBaseSpecifierArray &BasePath) {
+  for (CXXBaseSpecifierArray::iterator B = BasePath.begin(), 
+                                    BEnd = BasePath.end();
+       B != BEnd; ++B)
+    if ((*B)->isVirtual())
+      return true;
+
+  return false;
+}
+
 /// 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
@@ -1125,7 +1142,8 @@ Sema::ActOnMemInitializer(DeclPtrTy ConstructorD,
           // specialization, we take it as a type name.
           BaseType = CheckTypenameType(ETK_None,
                                        (NestedNameSpecifier *)SS.getScopeRep(),
-                                       *MemberOrBase, SS.getRange());
+                                       *MemberOrBase, SourceLocation(),
+                                       SS.getRange(), IdLoc);
           if (BaseType.isNull())
             return true;
 
@@ -1192,7 +1210,7 @@ Sema::ActOnMemInitializer(DeclPtrTy ConstructorD,
           static_cast<NestedNameSpecifier*>(SS.getScopeRep());
 
         // FIXME: preserve source range information
-        BaseType = Context.getQualifiedNameType(Qualifier, BaseType);
+        BaseType = Context.getElaboratedType(ETK_None, Qualifier, BaseType);
       }
     }
   }
@@ -1357,7 +1375,7 @@ Sema::BuildBaseInitializer(QualType BaseType, TypeSourceInfo *BaseTInfo,
   for (unsigned i = 0; i < NumArgs; i++)
     HasDependentArg |= Args[i]->isTypeDependent();
 
-  SourceLocation BaseLoc = BaseTInfo->getTypeLoc().getSourceRange().getBegin();
+  SourceLocation BaseLoc = BaseTInfo->getTypeLoc().getLocalSourceRange().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.
@@ -1381,7 +1399,7 @@ Sema::BuildBaseInitializer(QualType BaseType, TypeSourceInfo *BaseTInfo,
   
   if (!BaseType->isRecordType())
     return Diag(BaseLoc, diag::err_base_init_does_not_name_class)
-             << BaseType << BaseTInfo->getTypeLoc().getSourceRange();
+             << BaseType << BaseTInfo->getTypeLoc().getLocalSourceRange();
 
   // C++ [class.base.init]p2:
   //   [...] Unless the mem-initializer-id names a nonstatic data
@@ -1402,7 +1420,7 @@ Sema::BuildBaseInitializer(QualType BaseType, TypeSourceInfo *BaseTInfo,
   //   class, the mem-initializer is ill-formed.
   if (DirectBaseSpec && VirtualBaseSpec)
     return Diag(BaseLoc, diag::err_base_init_direct_and_virtual)
-      << BaseType << BaseTInfo->getTypeLoc().getSourceRange();
+      << BaseType << BaseTInfo->getTypeLoc().getLocalSourceRange();
   // 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
@@ -1410,7 +1428,7 @@ Sema::BuildBaseInitializer(QualType BaseType, TypeSourceInfo *BaseTInfo,
   if (!DirectBaseSpec && !VirtualBaseSpec)
     return Diag(BaseLoc, diag::err_not_direct_base_or_virtual)
       << BaseType << Context.getTypeDeclType(ClassDecl)
-      << BaseTInfo->getTypeLoc().getSourceRange();
+      << BaseTInfo->getTypeLoc().getLocalSourceRange();
 
   CXXBaseSpecifier *BaseSpec
     = const_cast<CXXBaseSpecifier *>(DirectBaseSpec);
@@ -1550,42 +1568,107 @@ BuildImplicitMemberInitializer(Sema &SemaRef, CXXConstructorDecl *Constructor,
                                ImplicitInitializerKind ImplicitInitKind,
                                FieldDecl *Field,
                                CXXBaseOrMemberInitializer *&CXXMemberInit) {
+  if (Field->isInvalidDecl())
+    return true;
+
   if (ImplicitInitKind == IIK_Copy) {
-    // FIXME: We should not return early here, but will do so until 
-    // we know how to handle copy initialization of arrays.
-    CXXMemberInit = 0;
-    return false;
-    
+    SourceLocation Loc = Constructor->getLocation();
     ParmVarDecl *Param = Constructor->getParamDecl(0);
     QualType ParamType = Param->getType().getNonReferenceType();
     
     Expr *MemberExprBase = 
       DeclRefExpr::Create(SemaRef.Context, 0, SourceRange(), Param, 
-                          SourceLocation(), ParamType, 0);
+                          Loc, ParamType, 0);
+
+    // Build a reference to this field within the parameter.
+    CXXScopeSpec SS;
+    LookupResult MemberLookup(SemaRef, Field->getDeclName(), Loc,
+                              Sema::LookupMemberName);
+    MemberLookup.addDecl(Field, AS_public);
+    MemberLookup.resolveKind();
+    Sema::OwningExprResult CopyCtorArg 
+      = SemaRef.BuildMemberReferenceExpr(SemaRef.Owned(MemberExprBase),
+                                         ParamType, Loc,
+                                         /*IsArrow=*/false,
+                                         SS,
+                                         /*FirstQualifierInScope=*/0,
+                                         MemberLookup,
+                                         /*TemplateArgs=*/0);    
+    if (CopyCtorArg.isInvalid())
+      return true;
     
+    // When the field we are copying is an array, create index variables for 
+    // each dimension of the array. We use these index variables to subscript
+    // the source array, and other clients (e.g., CodeGen) will perform the
+    // necessary iteration with these index variables.
+    llvm::SmallVector<VarDecl *, 4> IndexVariables;
+    QualType BaseType = Field->getType();
+    QualType SizeType = SemaRef.Context.getSizeType();
+    while (const ConstantArrayType *Array
+                          = SemaRef.Context.getAsConstantArrayType(BaseType)) {
+      // Create the iteration variable for this array index.
+      IdentifierInfo *IterationVarName = 0;
+      {
+        llvm::SmallString<8> Str;
+        llvm::raw_svector_ostream OS(Str);
+        OS << "__i" << IndexVariables.size();
+        IterationVarName = &SemaRef.Context.Idents.get(OS.str());
+      }
+      VarDecl *IterationVar
+        = VarDecl::Create(SemaRef.Context, SemaRef.CurContext, Loc,
+                          IterationVarName, SizeType,
+                        SemaRef.Context.getTrivialTypeSourceInfo(SizeType, Loc),
+                          VarDecl::None, VarDecl::None);
+      IndexVariables.push_back(IterationVar);
+      
+      // Create a reference to the iteration variable.
+      Sema::OwningExprResult IterationVarRef
+        = SemaRef.BuildDeclRefExpr(IterationVar, SizeType, Loc);
+      assert(!IterationVarRef.isInvalid() &&
+             "Reference to invented variable cannot fail!");
+      
+      // Subscript the array with this iteration variable.
+      CopyCtorArg = SemaRef.CreateBuiltinArraySubscriptExpr(move(CopyCtorArg),
+                                                            Loc,
+                                                          move(IterationVarRef),
+                                                            Loc);
+      if (CopyCtorArg.isInvalid())
+        return true;
+      
+      BaseType = Array->getElementType();
+    }
     
-    Expr *CopyCtorArg = 
-      MemberExpr::Create(SemaRef.Context, MemberExprBase, /*IsArrow=*/false, 
-                         0, SourceRange(), Field, 
-                         DeclAccessPair::make(Field, Field->getAccess()),
-                         SourceLocation(), 0, 
-                         Field->getType().getNonReferenceType());
+    // Construct the entity that we will be initializing. For an array, this
+    // will be first element in the array, which may require several levels
+    // of array-subscript entities. 
+    llvm::SmallVector<InitializedEntity, 4> Entities;
+    Entities.reserve(1 + IndexVariables.size());
+    Entities.push_back(InitializedEntity::InitializeMember(Field));
+    for (unsigned I = 0, N = IndexVariables.size(); I != N; ++I)
+      Entities.push_back(InitializedEntity::InitializeElement(SemaRef.Context,
+                                                              0,
+                                                              Entities.back()));
     
-    InitializedEntity InitEntity = InitializedEntity::InitializeMember(Field);
+    // Direct-initialize to use the copy constructor.
     InitializationKind InitKind =
-      InitializationKind::CreateDirect(Constructor->getLocation(), 
-                                       SourceLocation(), SourceLocation());
+      InitializationKind::CreateDirect(Loc, SourceLocation(), SourceLocation());
     
-    InitializationSequence InitSeq(SemaRef, InitEntity, InitKind,
-                                   &CopyCtorArg, 1);
+    Expr *CopyCtorArgE = CopyCtorArg.takeAs<Expr>();
+    InitializationSequence InitSeq(SemaRef, Entities.back(), InitKind,
+                                   &CopyCtorArgE, 1);
     
-    Sema::OwningExprResult MemberInit =
-      InitSeq.Perform(SemaRef, InitEntity, InitKind, 
-                      Sema::MultiExprArg(SemaRef, (void**)&CopyCtorArg, 1), 0);
+    Sema::OwningExprResult MemberInit
+      = InitSeq.Perform(SemaRef, Entities.back(), InitKind, 
+                        Sema::MultiExprArg(SemaRef, (void**)&CopyCtorArgE, 1));
+    MemberInit = SemaRef.MaybeCreateCXXExprWithTemporaries(move(MemberInit));
     if (MemberInit.isInvalid())
       return true;
-    
-    CXXMemberInit = 0;
+
+    CXXMemberInit
+      = CXXBaseOrMemberInitializer::Create(SemaRef.Context, Field, Loc, Loc,
+                                           MemberInit.takeAs<Expr>(), Loc,
+                                           IndexVariables.data(),
+                                           IndexVariables.size());
     return false;
   }
 
@@ -1640,6 +1723,81 @@ BuildImplicitMemberInitializer(Sema &SemaRef, CXXConstructorDecl *Constructor,
   CXXMemberInit = 0;
   return false;
 }
+
+namespace {
+struct BaseAndFieldInfo {
+  Sema &S;
+  CXXConstructorDecl *Ctor;
+  bool AnyErrorsInInits;
+  ImplicitInitializerKind IIK;
+  llvm::DenseMap<const void *, CXXBaseOrMemberInitializer*> AllBaseFields;
+  llvm::SmallVector<CXXBaseOrMemberInitializer*, 8> AllToInit;
+
+  BaseAndFieldInfo(Sema &S, CXXConstructorDecl *Ctor, bool ErrorsInInits)
+    : S(S), Ctor(Ctor), AnyErrorsInInits(ErrorsInInits) {
+    // FIXME: Handle implicit move constructors.
+    if (Ctor->isImplicit() && Ctor->isCopyConstructor())
+      IIK = IIK_Copy;
+    else
+      IIK = IIK_Default;
+  }
+};
+}
+
+static bool CollectFieldInitializer(BaseAndFieldInfo &Info,
+                                    FieldDecl *Top, FieldDecl *Field) {
+
+  // Overwhelmingly common case:  we have a direct initializer for this field.
+  if (CXXBaseOrMemberInitializer *Init = Info.AllBaseFields.lookup(Field)) {
+    Info.AllToInit.push_back(Init);
+
+    if (Field != Top) {
+      Init->setMember(Top);
+      Init->setAnonUnionMember(Field);
+    }
+    return false;
+  }
+
+  if (Info.IIK == IIK_Default && Field->isAnonymousStructOrUnion()) {
+    const RecordType *FieldClassType = Field->getType()->getAs<RecordType>();
+    assert(FieldClassType && "anonymous struct/union without record type");
+
+    // Walk through the members, tying in any initializers for fields
+    // we find.  The earlier semantic checks should prevent redundant
+    // initialization of union members, given the requirement that
+    // union members never have non-trivial default constructors.
+
+    // TODO: in C++0x, it might be legal to have union members with
+    // non-trivial default constructors in unions.  Revise this
+    // implementation then with the appropriate semantics.
+    CXXRecordDecl *FieldClassDecl
+      = cast<CXXRecordDecl>(FieldClassType->getDecl());
+    for (RecordDecl::field_iterator FA = FieldClassDecl->field_begin(),
+           EA = FieldClassDecl->field_end(); FA != EA; FA++)
+      if (CollectFieldInitializer(Info, Top, *FA))
+        return true;
+  }
+
+  // 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)
+    return false;
+
+  CXXBaseOrMemberInitializer *Init = 0;
+  if (BuildImplicitMemberInitializer(Info.S, Info.Ctor, Info.IIK, Field, Init))
+    return true;
+    
+  // If the member doesn't need to be initialized, Init will still be null.
+  if (!Init) return false;
+
+  Info.AllToInit.push_back(Init);
+  if (Top != Field) {
+    Init->setMember(Top);
+    Init->setAnonUnionMember(Field);
+  }
+  return false;
+}
                                
 bool
 Sema::SetBaseOrMemberInitializers(CXXConstructorDecl *Constructor,
@@ -1661,11 +1819,7 @@ Sema::SetBaseOrMemberInitializers(CXXConstructorDecl *Constructor,
     return false;
   }
 
-  ImplicitInitializerKind ImplicitInitKind = IIK_Default;
-  
-  // FIXME: Handle implicit move constructors.
-  if (Constructor->isImplicit() && Constructor->isCopyConstructor())
-    ImplicitInitKind = IIK_Copy;
+  BaseAndFieldInfo Info(*this, Constructor, AnyErrors);
 
   // We need to build the initializer AST according to order of construction
   // and not what user specified in the Initializers list.
@@ -1673,17 +1827,15 @@ Sema::SetBaseOrMemberInitializers(CXXConstructorDecl *Constructor,
   if (!ClassDecl)
     return true;
   
-  llvm::SmallVector<CXXBaseOrMemberInitializer*, 32> AllToInit;
-  llvm::DenseMap<const void *, CXXBaseOrMemberInitializer*> AllBaseFields;
   bool HadError = false;
 
   for (unsigned i = 0; i < NumInitializers; i++) {
     CXXBaseOrMemberInitializer *Member = Initializers[i];
     
     if (Member->isBaseInitializer())
-      AllBaseFields[Member->getBaseClass()->getAs<RecordType>()] = Member;
+      Info.AllBaseFields[Member->getBaseClass()->getAs<RecordType>()] = Member;
     else
-      AllBaseFields[Member->getMember()] = Member;
+      Info.AllBaseFields[Member->getMember()] = Member;
   }
 
   // Keep track of the direct virtual bases.
@@ -1699,22 +1851,23 @@ Sema::SetBaseOrMemberInitializers(CXXConstructorDecl *Constructor,
        E = ClassDecl->vbases_end(); VBase != E; ++VBase) {
 
     if (CXXBaseOrMemberInitializer *Value
-        = AllBaseFields.lookup(VBase->getType()->getAs<RecordType>())) {
-      AllToInit.push_back(Value);
+        = Info.AllBaseFields.lookup(VBase->getType()->getAs<RecordType>())) {
+      Info.AllToInit.push_back(Value);
     } else if (!AnyErrors) {
       bool IsInheritedVirtualBase = !DirectVBases.count(VBase);
       CXXBaseOrMemberInitializer *CXXBaseInit;
-      if (BuildImplicitBaseInitializer(*this, Constructor, ImplicitInitKind,
+      if (BuildImplicitBaseInitializer(*this, Constructor, Info.IIK,
                                        VBase, IsInheritedVirtualBase, 
                                        CXXBaseInit)) {
         HadError = true;
         continue;
       }
 
-      AllToInit.push_back(CXXBaseInit);
+      Info.AllToInit.push_back(CXXBaseInit);
     }
   }
 
+  // Non-virtual bases.
   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.
@@ -1722,70 +1875,39 @@ Sema::SetBaseOrMemberInitializers(CXXConstructorDecl *Constructor,
       continue;
 
     if (CXXBaseOrMemberInitializer *Value
-          = AllBaseFields.lookup(Base->getType()->getAs<RecordType>())) {
-      AllToInit.push_back(Value);
+          = Info.AllBaseFields.lookup(Base->getType()->getAs<RecordType>())) {
+      Info.AllToInit.push_back(Value);
     } else if (!AnyErrors) {
       CXXBaseOrMemberInitializer *CXXBaseInit;
-      if (BuildImplicitBaseInitializer(*this, Constructor, ImplicitInitKind,
+      if (BuildImplicitBaseInitializer(*this, Constructor, Info.IIK,
                                        Base, /*IsInheritedVirtualBase=*/false,
                                        CXXBaseInit)) {
         HadError = true;
         continue;
       }
 
-      AllToInit.push_back(CXXBaseInit);
+      Info.AllToInit.push_back(CXXBaseInit);
     }
   }
 
-  // non-static data members.
+  // Fields.
   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);
+    if ((*Field)->getType()->isIncompleteArrayType()) {
+      assert(ClassDecl->hasFlexibleArrayMember() &&
+             "Incomplete array type is not valid");
       continue;
     }
-
-    if (AnyErrors)
-      continue;
-    
-    CXXBaseOrMemberInitializer *Member;
-    if (BuildImplicitMemberInitializer(*this, Constructor, ImplicitInitKind,
-                                       *Field, Member)) {
+    if (CollectFieldInitializer(Info, *Field, *Field))
       HadError = true;
-      continue;
-    }
-    
-    // If the member doesn't need to be initialized, it will be null.
-    if (Member)
-      AllToInit.push_back(Member);
   }
 
-  NumInitializers = AllToInit.size();
+  NumInitializers = Info.AllToInit.size();
   if (NumInitializers > 0) {
     Constructor->setNumBaseOrMemberInitializers(NumInitializers);
     CXXBaseOrMemberInitializer **baseOrMemberInitializers =
       new (Context) CXXBaseOrMemberInitializer*[NumInitializers];
-    memcpy(baseOrMemberInitializers, AllToInit.data(),
+    memcpy(baseOrMemberInitializers, Info.AllToInit.data(),
            NumInitializers * sizeof(CXXBaseOrMemberInitializer*));
     Constructor->setBaseOrMemberInitializers(baseOrMemberInitializers);
 
@@ -1900,9 +2022,7 @@ DiagnoseBaseOrMemInitializerOrder(Sema &SemaRef,
     // If we didn't find this initializer, it must be because we
     // scanned past it on a previous iteration.  That can only
     // happen if we're out of order;  emit a warning.
-    if (IdealIndex == NumIdealInits) {
-      assert(PrevInit && "initializer not found in initializer list");
-
+    if (IdealIndex == NumIdealInits && PrevInit) {
       Sema::SemaDiagnosticBuilder D =
         SemaRef.Diag(PrevInit->getSourceLocation(),
                      diag::warn_initializer_out_of_order);
@@ -2028,6 +2148,9 @@ void Sema::ActOnMemInitializers(DeclPtrTy ConstructorDecl,
   for (unsigned i = 0; i < NumMemInits; i++) {
     CXXBaseOrMemberInitializer *Init = MemInits[i];
 
+    // Set the source order index.
+    Init->setSourceOrder(i);
+
     if (Init->isMemberInitializer()) {
       FieldDecl *Field = Init->getMember();
       if (CheckRedundantInit(*this, Init, Members[Field]) ||
@@ -2064,7 +2187,8 @@ Sema::MarkBaseAndMemberDestructorsReferenced(SourceLocation Location,
   for (CXXRecordDecl::field_iterator I = ClassDecl->field_begin(),
        E = ClassDecl->field_end(); I != E; ++I) {
     FieldDecl *Field = *I;
-    
+    if (Field->isInvalidDecl())
+      continue;
     QualType FieldType = Context.getBaseElementType(Field->getType());
     
     const RecordType* RT = FieldType->getAs<RecordType>();
@@ -2403,6 +2527,9 @@ void Sema::CheckCompletedCXXClass(Scope *S, CXXRecordDecl *Record) {
       }
     }
   }
+
+  if (Record->isDynamicClass())
+    DynamicClasses.push_back(Record);
 }
 
 void Sema::ActOnFinishCXXMemberSpecification(Scope* S, SourceLocation RLoc,
@@ -2530,7 +2657,7 @@ void Sema::AddImplicitlyDeclaredMembersToClass(Scope *S,
                                    Context.getFunctionType(Context.VoidTy,
                                                            &ArgType, 1,
                                                            false, 0,
-                                                           /*FIXME:*/false,
+                                               /*FIXME: hasExceptionSpec*/false,
                                                            false, 0, 0,
                                                        FunctionType::ExtInfo()),
                                    /*TInfo=*/0,
@@ -2623,7 +2750,7 @@ void Sema::AddImplicitlyDeclaredMembersToClass(Scope *S,
       CXXMethodDecl::Create(Context, ClassDecl, ClassDecl->getLocation(), Name,
                             Context.getFunctionType(RetType, &ArgType, 1,
                                                     false, 0,
-                                                    /*FIXME:*/false,
+                                              /*FIXME: hasExceptionSpec*/false,
                                                     false, 0, 0,
                                                     FunctionType::ExtInfo()),
                             /*TInfo=*/0, /*isStatic=*/false,
@@ -2659,7 +2786,7 @@ void Sema::AddImplicitlyDeclaredMembersToClass(Scope *S,
     //   inline public member of its class.
     QualType Ty = Context.getFunctionType(Context.VoidTy,
                                           0, 0, false, 0,
-                                          /*FIXME:*/false,
+                                          /*FIXME: hasExceptionSpec*/false,
                                           false, 0, 0, FunctionType::ExtInfo());
 
     DeclarationName Name
@@ -3817,8 +3944,9 @@ bool Sema::CheckUsingDeclRedeclaration(SourceLocation UsingLoc,
   //   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())
+  //
+  // That's in non-member contexts.
+  if (!CurContext->getLookupContext()->isRecord())
     return false;
 
   NestedNameSpecifier *Qual
@@ -4082,12 +4210,15 @@ void Sema::DefineImplicitDefaultConstructor(SourceLocation CurrentLocation,
   assert(ClassDecl && "DefineImplicitDefaultConstructor - invalid constructor");
 
   ImplicitlyDefinedFunctionScope Scope(*this, Constructor);
-  if (SetBaseOrMemberInitializers(Constructor, 0, 0, /*AnyErrors=*/false)) {
+  ErrorTrap Trap(*this);
+  if (SetBaseOrMemberInitializers(Constructor, 0, 0, /*AnyErrors=*/false) ||
+      Trap.hasErrorOccurred()) {
     Diag(CurrentLocation, diag::note_member_synthesized_at) 
       << CXXConstructor << Context.getTagDeclType(ClassDecl);
     Constructor->setInvalidDecl();
   } else {
     Constructor->setUsed();
+    MarkVTableUsed(CurrentLocation, ClassDecl);
   }
 }
 
@@ -4098,14 +4229,16 @@ void Sema::DefineImplicitDestructor(SourceLocation CurrentLocation,
   CXXRecordDecl *ClassDecl = Destructor->getParent();
   assert(ClassDecl && "DefineImplicitDestructor - invalid destructor");
 
+  if (Destructor->isInvalidDecl())
+    return;
+
   ImplicitlyDefinedFunctionScope Scope(*this, Destructor);
 
+  ErrorTrap Trap(*this);
   MarkBaseAndMemberDestructorsReferenced(Destructor->getLocation(),
                                          Destructor->getParent());
 
-  // FIXME: If CheckDestructor fails, we should emit a note about where the
-  // implicit destructor was needed.
-  if (CheckDestructor(Destructor)) {
+  if (CheckDestructor(Destructor) || Trap.hasErrorOccurred()) {
     Diag(CurrentLocation, diag::note_member_synthesized_at) 
       << CXXDestructor << Context.getTagDeclType(ClassDecl);
 
@@ -4114,6 +4247,7 @@ void Sema::DefineImplicitDestructor(SourceLocation CurrentLocation,
   }
 
   Destructor->setUsed();
+  MarkVTableUsed(CurrentLocation, ClassDecl);
 }
 
 /// \brief Builds a statement that copies the given entity from \p From to
@@ -4332,6 +4466,7 @@ void Sema::DefineImplicitCopyAssignment(SourceLocation CurrentLocation,
   CopyAssignOperator->setUsed();
 
   ImplicitlyDefinedFunctionScope Scope(*this, CopyAssignOperator);
+  ErrorTrap Trap(*this);
 
   // C++0x [class.copy]p30:
   //   The implicitly-defined or explicitly-defaulted copy assignment operator
@@ -4407,8 +4542,10 @@ void Sema::DefineImplicitCopyAssignment(SourceLocation CurrentLocation,
                                                   move(To), Owned(From),
                                                 /*CopyingBaseSubobject=*/true);
     if (Copy.isInvalid()) {
-      Invalid = true;
-      continue;
+      Diag(CurrentLocation, diag::note_member_synthesized_at) 
+        << CXXCopyAssignment << Context.getTagDeclType(ClassDecl);
+      CopyAssignOperator->setInvalidDecl();
+      return;
     }
     
     // Success! Record the copy.
@@ -4427,7 +4564,8 @@ void Sema::DefineImplicitCopyAssignment(SourceLocation CurrentLocation,
       Diag(ClassDecl->getLocation(), diag::err_uninitialized_member_for_assign)
         << Context.getTagDeclType(ClassDecl) << 0 << Field->getDeclName();
       Diag(Field->getLocation(), diag::note_declared_at);
-      Diag(Loc, diag::note_first_required_here);
+      Diag(CurrentLocation, diag::note_member_synthesized_at) 
+        << CXXCopyAssignment << Context.getTagDeclType(ClassDecl);
       Invalid = true;
       continue;
     }
@@ -4438,12 +4576,18 @@ void Sema::DefineImplicitCopyAssignment(SourceLocation CurrentLocation,
       Diag(ClassDecl->getLocation(), diag::err_uninitialized_member_for_assign)
         << Context.getTagDeclType(ClassDecl) << 1 << Field->getDeclName();
       Diag(Field->getLocation(), diag::note_declared_at);
-      Diag(Loc, diag::note_first_required_here);
+      Diag(CurrentLocation, diag::note_member_synthesized_at) 
+        << CXXCopyAssignment << Context.getTagDeclType(ClassDecl);
       Invalid = true;      
       continue;
     }
     
     QualType FieldType = Field->getType().getNonReferenceType();
+    if (FieldType->isIncompleteArrayType()) {
+      assert(ClassDecl->hasFlexibleArrayMember() && 
+             "Incomplete array type is not valid");
+      continue;
+    }
     
     // Build references to the field in the object we're copying from and to.
     CXXScopeSpec SS; // Intentionally empty
@@ -4528,8 +4672,10 @@ void Sema::DefineImplicitCopyAssignment(SourceLocation CurrentLocation,
                                                   move(To), move(From),
                                               /*CopyingBaseSubobject=*/false);
     if (Copy.isInvalid()) {
-      Invalid = true;
-      continue;
+      Diag(CurrentLocation, diag::note_member_synthesized_at) 
+        << CXXCopyAssignment << Context.getTagDeclType(ClassDecl);
+      CopyAssignOperator->setInvalidDecl();
+      return;
     }
     
     // Success! Record the copy.
@@ -4546,6 +4692,12 @@ void Sema::DefineImplicitCopyAssignment(SourceLocation CurrentLocation,
       Invalid = true;
     else {
       Statements.push_back(Return.takeAs<Stmt>());
+
+      if (Trap.hasErrorOccurred()) {
+        Diag(CurrentLocation, diag::note_member_synthesized_at) 
+          << CXXCopyAssignment << Context.getTagDeclType(ClassDecl);
+        Invalid = true;
+      }
     }
   }
 
@@ -4572,37 +4724,22 @@ void Sema::DefineImplicitCopyConstructor(SourceLocation CurrentLocation,
   assert(ClassDecl && "DefineImplicitCopyConstructor - invalid constructor");
 
   ImplicitlyDefinedFunctionScope Scope(*this, CopyConstructor);
+  ErrorTrap Trap(*this);
 
-  if (SetBaseOrMemberInitializers(CopyConstructor, 0, 0, /*AnyErrors=*/false)) {
+  if (SetBaseOrMemberInitializers(CopyConstructor, 0, 0, /*AnyErrors=*/false) ||
+      Trap.hasErrorOccurred()) {
     Diag(CurrentLocation, diag::note_member_synthesized_at) 
-    << CXXCopyConstructor << Context.getTagDeclType(ClassDecl);
+      << CXXCopyConstructor << Context.getTagDeclType(ClassDecl);
     CopyConstructor->setInvalidDecl();
-  } else {
-    CopyConstructor->setUsed();
-  }
-
-  // FIXME: Once SetBaseOrMemberInitializers can handle copy initialization of
-  // fields, this code below should be removed.
-  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)) {
-        CheckDirectMemberAccess(Field->getLocation(),
-                                FieldCopyCtor,
-                                PDiag(diag::err_access_copy_field)
-                                  << Field->getDeclName() << Field->getType());
-
-        MarkDeclarationReferenced(CurrentLocation, FieldCopyCtor);
-      }
-    }
+  }  else {
+    CopyConstructor->setBody(ActOnCompoundStmt(CopyConstructor->getLocation(),
+                                               CopyConstructor->getLocation(),
+                                               MultiStmtArg(*this, 0, 0), 
+                                               /*isStmtExpr=*/false)
+                                                              .takeAs<Stmt>());
   }
+  
+  CopyConstructor->setUsed();
 }
 
 Sema::OwningExprResult
@@ -4672,7 +4809,7 @@ bool Sema::InitializeVarWithConstructor(VarDecl *VD,
 void Sema::FinalizeVarWithDestructor(VarDecl *VD, const RecordType *Record) {
   CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(Record->getDecl());
   if (!ClassDecl->isInvalidDecl() && !VD->isInvalidDecl() &&
-      !ClassDecl->hasTrivialDestructor()) {
+      !ClassDecl->hasTrivialDestructor() && !ClassDecl->isDependentContext()) {
     CXXDestructorDecl *Destructor = ClassDecl->getDestructor(Context);
     MarkDeclarationReferenced(VD->getLocation(), Destructor);
     CheckDestructorAccess(VD->getLocation(), Destructor,
@@ -5419,7 +5556,7 @@ FriendDecl *Sema::CheckFriendTypeDecl(SourceLocation FriendLoc,
   assert(TSInfo && "NULL TypeSourceInfo for friend type declaration");
   
   QualType T = TSInfo->getType();
-  SourceRange TypeRange = TSInfo->getTypeLoc().getSourceRange();
+  SourceRange TypeRange = TSInfo->getTypeLoc().getLocalSourceRange();
   
   if (!getLangOptions().CPlusPlus0x) {
     // C++03 [class.friend]p2:
@@ -5948,90 +6085,125 @@ Sema::ActOnCXXConditionDeclaration(Scope *S, Declarator &D) {
   return Dcl;
 }
 
-static bool needsVTable(CXXMethodDecl *MD, ASTContext &Context) {
-  // Ignore dependent types.
-  if (MD->isDependentContext())
-    return false;
-
-  // Ignore declarations that are not definitions.
-  if (!MD->isThisDeclarationADefinition())
-    return false;
-
-  CXXRecordDecl *RD = MD->getParent();
-
-  // Ignore classes without a vtable.
-  if (!RD->isDynamicClass())
-    return false;
-
-  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.
-    break;
+void Sema::MarkVTableUsed(SourceLocation Loc, CXXRecordDecl *Class,
+                          bool DefinitionRequired) {
+  // Ignore any vtable uses in unevaluated operands or for classes that do
+  // not have a vtable.
+  if (!Class->isDynamicClass() || Class->isDependentContext() ||
+      CurContext->isDependentContext() ||
+      ExprEvalContexts.back().Context == Unevaluated)
+    return;
 
-  case TSK_ImplicitInstantiation:
-    // This is a constructor of a class template; mark all of the virtual
-    // members as referenced to ensure that they get instantiatied.
-    if (isa<CXXConstructorDecl>(MD) || isa<CXXDestructorDecl>(MD))
-      return true;
-    break;
+  // Try to insert this class into the map.
+  Class = cast<CXXRecordDecl>(Class->getCanonicalDecl());
+  std::pair<llvm::DenseMap<CXXRecordDecl *, bool>::iterator, bool>
+    Pos = VTablesUsed.insert(std::make_pair(Class, DefinitionRequired));
+  if (!Pos.second) {
+    // If we already had an entry, check to see if we are promoting this vtable
+    // to required a definition. If so, we need to reappend to the VTableUses
+    // list, since we may have already processed the first entry.
+    if (DefinitionRequired && !Pos.first->second) {
+      Pos.first->second = true;
+    } else {
+      // Otherwise, we can early exit.
+      return;
+    }
+  }
 
-  case TSK_ExplicitInstantiationDeclaration:
-    return false;
+  // Local classes need to have their virtual members marked
+  // immediately. For all other classes, we mark their virtual members
+  // at the end of the translation unit.
+  if (Class->isLocalClass())
+    MarkVirtualMembersReferenced(Loc, Class);
+  else
+    VTableUses.push_back(std::make_pair(Class, Loc));
+}
 
-  case TSK_ExplicitInstantiationDefinition:
-    // This is method of a explicit instantiation; mark all of the virtual
-    // members as referenced to ensure that they get instantiatied.
-    return true;
+bool Sema::DefineUsedVTables() {
+  // If any dynamic classes have their key function defined within
+  // this translation unit, then those vtables are considered "used" and must
+  // be emitted.
+  for (unsigned I = 0, N = DynamicClasses.size(); I != N; ++I) {
+    if (const CXXMethodDecl *KeyFunction
+                             = Context.getKeyFunction(DynamicClasses[I])) {
+      const FunctionDecl *Definition = 0;
+      if (KeyFunction->getBody(Definition))
+        MarkVTableUsed(Definition->getLocation(), DynamicClasses[I], true);
+    }
   }
 
-  // Consider only out-of-line definitions of member functions. When we see
-  // an inline definition, it's too early to compute the key function.
-  if (!MD->isOutOfLine())
+  if (VTableUses.empty())
     return false;
+  
+  // Note: The VTableUses vector could grow as a result of marking
+  // the members of a class as "used", so we check the size each
+  // time through the loop and prefer indices (with are stable) to
+  // iterators (which are not).
+  for (unsigned I = 0; I != VTableUses.size(); ++I) {
+    CXXRecordDecl *Class = VTableUses[I].first->getDefinition();
+    if (!Class)
+      continue;
 
-  const CXXMethodDecl *KeyFunction = Context.getKeyFunction(RD);
-
-  // If there is no key function, we will need a copy of the vtable.
-  if (!KeyFunction)
-    return true;
-
-  // If this is the key function, we need to mark virtual members.
-  if (KeyFunction->getCanonicalDecl() == MD->getCanonicalDecl())
-    return true;
-
-  return false;
-}
-
-void Sema::MaybeMarkVirtualMembersReferenced(SourceLocation Loc,
-                                             CXXMethodDecl *MD) {
-  CXXRecordDecl *RD = MD->getParent();
+    SourceLocation Loc = VTableUses[I].second;
+
+    // If this class has a key function, but that key function is
+    // defined in another translation unit, we don't need to emit the
+    // vtable even though we're using it.
+    const CXXMethodDecl *KeyFunction = Context.getKeyFunction(Class);
+    if (KeyFunction && !KeyFunction->getBody()) {
+      switch (KeyFunction->getTemplateSpecializationKind()) {
+      case TSK_Undeclared:
+      case TSK_ExplicitSpecialization:
+      case TSK_ExplicitInstantiationDeclaration:
+        // The key function is in another translation unit.
+        continue;
 
-  // We will need to mark all of the virtual members as referenced to build the
-  // vtable.
-  if (!needsVTable(MD, Context))
-    return;
+      case TSK_ExplicitInstantiationDefinition:
+      case TSK_ImplicitInstantiation:
+        // We will be instantiating the key function.
+        break;
+      }
+    } else if (!KeyFunction) {
+      // If we have a class with no key function that is the subject
+      // of an explicit instantiation declaration, suppress the
+      // vtable; it will live with the explicit instantiation
+      // definition.
+      bool IsExplicitInstantiationDeclaration
+        = Class->getTemplateSpecializationKind()
+                                      == TSK_ExplicitInstantiationDeclaration;
+      for (TagDecl::redecl_iterator R = Class->redecls_begin(),
+                                 REnd = Class->redecls_end();
+           R != REnd; ++R) {
+        TemplateSpecializationKind TSK
+          = cast<CXXRecordDecl>(*R)->getTemplateSpecializationKind();
+        if (TSK == TSK_ExplicitInstantiationDeclaration)
+          IsExplicitInstantiationDeclaration = true;
+        else if (TSK == TSK_ExplicitInstantiationDefinition) {
+          IsExplicitInstantiationDeclaration = false;
+          break;
+        }
+      }
 
-  TemplateSpecializationKind kind = RD->getTemplateSpecializationKind();
-  if (kind == TSK_ImplicitInstantiation)
-    ClassesWithUnmarkedVirtualMembers.push_back(std::make_pair(RD, Loc));
-  else
-    MarkVirtualMembersReferenced(Loc, RD);
-}
+      if (IsExplicitInstantiationDeclaration)
+        continue;
+    }
 
-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);
+    // Mark all of the virtual members of this class as referenced, so
+    // that we can build a vtable. Then, tell the AST consumer that a
+    // vtable for this class is required.
+    MarkVirtualMembersReferenced(Loc, Class);
+    CXXRecordDecl *Canonical = cast<CXXRecordDecl>(Class->getCanonicalDecl());
+    Consumer.HandleVTable(Class, VTablesUsed[Canonical]);
+
+    // Optionally warn if we're emitting a weak vtable.
+    if (Class->getLinkage() == ExternalLinkage &&
+        Class->getTemplateSpecializationKind() != TSK_ImplicitInstantiation) {
+      if (!KeyFunction || (KeyFunction->getBody() && KeyFunction->isInlined()))
+        Diag(Class->getLocation(), diag::warn_weak_vtable) << Class;
+    }
   }
-  
+  VTableUses.clear();
+
   return true;
 }
 
@@ -6076,6 +6248,9 @@ void Sema::SetIvarInitializers(ObjCImplementationDecl *ObjCImplementation) {
     llvm::SmallVector<CXXBaseOrMemberInitializer*, 32> AllToInit;
     for (unsigned i = 0; i < ivars.size(); i++) {
       FieldDecl *Field = ivars[i];
+      if (Field->isInvalidDecl())
+        continue;
+      
       CXXBaseOrMemberInitializer *Member;
       InitializedEntity InitEntity = InitializedEntity::InitializeMember(Field);
       InitializationKind InitKind = 
@@ -6098,6 +6273,20 @@ void Sema::SetIvarInitializers(ObjCImplementationDecl *ObjCImplementation) {
                                                  MemberInit.takeAs<Expr>(),
                                                  SourceLocation());
       AllToInit.push_back(Member);
+      
+      // Be sure that the destructor is accessible and is marked as referenced.
+      if (const RecordType *RecordTy
+                  = Context.getBaseElementType(Field->getType())
+                                                        ->getAs<RecordType>()) {
+                    CXXRecordDecl *RD = cast<CXXRecordDecl>(RecordTy->getDecl());
+        if (CXXDestructorDecl *Destructor
+              = const_cast<CXXDestructorDecl*>(RD->getDestructor(Context))) {
+          MarkDeclarationReferenced(Field->getLocation(), Destructor);
+          CheckDestructorAccess(Field->getLocation(), Destructor,
+                            PDiag(diag::err_access_dtor_ivar)
+                              << Context.getBaseElementType(Field->getType()));
+        }
+      }      
     }
     ObjCImplementation->setIvarInitializers(Context, 
                                             AllToInit.data(), AllToInit.size());
-- 
cgit v1.1