Perform two more constructor/destructor code-size optimizations:

1) emit base destructors as aliases to their unique base class destructors
under some careful conditions.  This is enabled for the same targets that can
support complete-to-base aliases, i.e. not darwin.

2) Emit non-variadic complete constructors for classes with no virtual bases
as calls to the base constructor.  This is enabled on all targets and in
theory can trigger in situations that the alias optimization can't (mostly
involving virtual bases, mostly not yet supported).

These are bundled together because I didn't think it worthwhile to split them,
not because they really need to be.



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@96842 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/include/clang/AST/DeclCXX.h b/include/clang/AST/DeclCXX.h
index 0978c6d..264c895 100644
--- a/include/clang/AST/DeclCXX.h
+++ b/include/clang/AST/DeclCXX.h
@@ -710,7 +710,7 @@
   CXXConstructorDecl *getDefaultConstructor(ASTContext &Context);
 
   /// getDestructor - Returns the destructor decl for this class.
-  CXXDestructorDecl *getDestructor(ASTContext &Context);
+  CXXDestructorDecl *getDestructor(ASTContext &Context) const;
 
   /// isLocalClass - If the class is a local class [class.local], returns
   /// the enclosing function declaration.
diff --git a/lib/AST/DeclCXX.cpp b/lib/AST/DeclCXX.cpp
index b0569d6..8d2a379 100644
--- a/lib/AST/DeclCXX.cpp
+++ b/lib/AST/DeclCXX.cpp
@@ -543,14 +543,14 @@
   return 0;
 }
 
-CXXDestructorDecl *CXXRecordDecl::getDestructor(ASTContext &Context) {
+CXXDestructorDecl *CXXRecordDecl::getDestructor(ASTContext &Context) const {
   QualType ClassType = Context.getTypeDeclType(this);
 
   DeclarationName Name
     = Context.DeclarationNames.getCXXDestructorName(
                                           Context.getCanonicalType(ClassType));
 
-  DeclContext::lookup_iterator I, E;
+  DeclContext::lookup_const_iterator I, E;
   llvm::tie(I, E) = lookup(Name);
   assert(I != E && "Did not find a destructor!");
 
diff --git a/lib/CodeGen/CGCXX.cpp b/lib/CodeGen/CGCXX.cpp
index e84b681..01648ae 100644
--- a/lib/CodeGen/CGCXX.cpp
+++ b/lib/CodeGen/CGCXX.cpp
@@ -27,24 +27,88 @@
 using namespace clang;
 using namespace CodeGen;
 
+/// Determines whether the given function has a trivial body that does
+/// not require any specific codegen.
+static bool HasTrivialBody(const FunctionDecl *FD) {
+  Stmt *S = FD->getBody();
+  if (!S)
+    return true;
+  if (isa<CompoundStmt>(S) && cast<CompoundStmt>(S)->body_empty())
+    return true;
+  return false;
+}
+
+/// Try to emit a base destructor as an alias to its primary
+/// base-class destructor.
+bool CodeGenModule::TryEmitBaseDestructorAsAlias(const CXXDestructorDecl *D) {
+  if (!getCodeGenOpts().CXXCtorDtorAliases)
+    return true;
+
+  // If the destructor doesn't have a trivial body, we have to emit it
+  // separately.
+  if (!HasTrivialBody(D))
+    return true;
+
+  const CXXRecordDecl *Class = D->getParent();
+
+  // If we need to manipulate a VTT parameter, give up.
+  if (Class->getNumVBases()) {
+    // Extra Credit:  passing extra parameters is perfectly safe
+    // in many calling conventions, so only bail out if the ctor's
+    // calling convention is nonstandard.
+    return true;
+  }
+
+  // If any fields have a non-trivial destructor, we have to emit it
+  // separately.
+  for (CXXRecordDecl::field_iterator I = Class->field_begin(),
+         E = Class->field_end(); I != E; ++I)
+    if (const RecordType *RT = (*I)->getType()->getAs<RecordType>())
+      if (!cast<CXXRecordDecl>(RT->getDecl())->hasTrivialDestructor())
+        return true;
+
+  // Try to find a unique base class with a non-trivial destructor.
+  const CXXRecordDecl *UniqueBase = 0;
+  for (CXXRecordDecl::base_class_const_iterator I = Class->bases_begin(),
+         E = Class->bases_end(); I != E; ++I) {
+
+    // We're in the base destructor, so skip virtual bases.
+    if (I->isVirtual()) continue;
+
+    // Skip base classes with trivial destructors.
+    const CXXRecordDecl *Base
+      = cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl());
+    if (Base->hasTrivialDestructor()) continue;
+
+    // If we've already found a base class with a non-trivial
+    // destructor, give up.
+    if (UniqueBase) return true;
+    UniqueBase = Base;
+  }
+
+  // If we didn't find any bases with a non-trivial destructor, then
+  // the base destructor is actually effectively trivial, which can
+  // happen if it was needlessly user-defined or if there are virtual
+  // bases with non-trivial destructors.
+  if (!UniqueBase)
+    return true;
+
+  // If the base is at a non-zero offset, give up.
+  const ASTRecordLayout &ClassLayout = Context.getASTRecordLayout(Class);
+  if (ClassLayout.getBaseClassOffset(UniqueBase) != 0)
+    return true;
+
+  const CXXDestructorDecl *BaseD = UniqueBase->getDestructor(getContext());
+  return TryEmitDefinitionAsAlias(GlobalDecl(D, Dtor_Base),
+                                  GlobalDecl(BaseD, Dtor_Base));
+}
+
 /// Try to emit a definition as a global alias for another definition.
 bool CodeGenModule::TryEmitDefinitionAsAlias(GlobalDecl AliasDecl,
                                              GlobalDecl TargetDecl) {
   if (!getCodeGenOpts().CXXCtorDtorAliases)
     return true;
 
-  // Find the referrent.
-  llvm::GlobalValue *Ref = cast<llvm::GlobalValue>(GetAddrOfGlobal(TargetDecl));
-
-  // Look for an existing entry.
-  const char *MangledName = getMangledName(AliasDecl);
-  llvm::GlobalValue *&Entry = GlobalDeclMap[MangledName];
-  if (Entry) {
-    assert(Entry->isDeclaration() && "definition already exists for alias");
-    assert(Entry->getType() == Ref->getType() &&
-           "declaration exists with different type");
-  }
-
   // The alias will use the linkage of the referrent.  If we can't
   // support aliases with that linkage, fail.
   llvm::GlobalValue::LinkageTypes Linkage
@@ -72,11 +136,32 @@
     return true;
   }
 
+  // Derive the type for the alias.
+  const llvm::PointerType *AliasType
+    = getTypes().GetFunctionType(AliasDecl)->getPointerTo();
+
+  // Look for an existing entry.
+  const char *MangledName = getMangledName(AliasDecl);
+  llvm::GlobalValue *&Entry = GlobalDeclMap[MangledName];
+  if (Entry) {
+    assert(Entry->isDeclaration() && "definition already exists for alias");
+    assert(Entry->getType() == AliasType &&
+           "declaration exists with different type");
+  }
+
+  // Find the referrent.  Some aliases might require a bitcast, in
+  // which case the caller is responsible for ensuring the soundness
+  // of these semantics.
+  llvm::GlobalValue *Ref = cast<llvm::GlobalValue>(GetAddrOfGlobal(TargetDecl));
+  llvm::Constant *Aliasee = Ref;
+  if (Ref->getType() != AliasType)
+    Aliasee = llvm::ConstantExpr::getBitCast(Ref, AliasType);
+
   // Create the alias with no name.
   llvm::GlobalAlias *Alias = 
-    new llvm::GlobalAlias(Ref->getType(), Linkage, "", Ref, &getModule());
+    new llvm::GlobalAlias(AliasType, Linkage, "", Aliasee, &getModule());
 
-  // Switch any previous uses to the alias and continue.
+  // Switch any previous uses to the alias and kill the previous decl.
   if (Entry) {
     Entry->replaceAllUsesWith(Alias);
     Entry->eraseFromParent();
@@ -90,7 +175,6 @@
   return false;
 }
 
-
 void CodeGenModule::EmitCXXConstructors(const CXXConstructorDecl *D) {
   // The constructor used for constructing this as a complete class;
   // constucts the virtual bases, then calls the base constructor.
@@ -169,6 +253,13 @@
                                 GlobalDecl(D, Dtor_Base)))
     return;
 
+  // The base destructor is equivalent to the base destructor of its
+  // base class if there is exactly one non-virtual base class with a
+  // non-trivial destructor, there are no fields with a non-trivial
+  // destructor, and the body of the destructor is trivial.
+  if (Type == Dtor_Base && !TryEmitBaseDestructorAsAlias(D))
+    return;
+
   llvm::Function *Fn = cast<llvm::Function>(GetAddrOfCXXDestructor(D, Type));
 
   CodeGenFunction(*this).GenerateCode(GlobalDecl(D, Type), Fn);
diff --git a/lib/CodeGen/CGCall.cpp b/lib/CodeGen/CGCall.cpp
index b064c12..1cd8993 100644
--- a/lib/CodeGen/CGCall.cpp
+++ b/lib/CodeGen/CGCall.cpp
@@ -416,6 +416,18 @@
   return FI.getReturnInfo().isIndirect();
 }
 
+const llvm::FunctionType *CodeGenTypes::GetFunctionType(GlobalDecl GD) {
+  const CGFunctionInfo &FI = getFunctionInfo(GD);
+  
+  // For definition purposes, don't consider a K&R function variadic.
+  bool Variadic = false;
+  if (const FunctionProtoType *FPT =
+        cast<FunctionDecl>(GD.getDecl())->getType()->getAs<FunctionProtoType>())
+    Variadic = FPT->isVariadic();
+
+  return GetFunctionType(FI, Variadic);
+}
+
 const llvm::FunctionType *
 CodeGenTypes::GetFunctionType(const CGFunctionInfo &FI, bool IsVariadic) {
   std::vector<const llvm::Type*> ArgTys;
diff --git a/lib/CodeGen/CGClass.cpp b/lib/CodeGen/CGClass.cpp
index d30d218..99c6dfd 100644
--- a/lib/CodeGen/CGClass.cpp
+++ b/lib/CodeGen/CGClass.cpp
@@ -891,31 +891,80 @@
   }
 }
 
+/// Checks whether the given constructor is a valid subject for the
+/// complete-to-base constructor delegation optimization, i.e.
+/// emitting the complete constructor as a simple call to the base
+/// constructor.
+static bool IsConstructorDelegationValid(const CXXConstructorDecl *Ctor) {
+
+  // Currently we disable the optimization for classes with virtual
+  // bases because (1) the addresses of parameter variables need to be
+  // consistent across all initializers but (2) the delegate function
+  // call necessarily creates a second copy of the parameter variable.
+  //
+  // The limiting example (purely theoretical AFAIK):
+  //   struct A { A(int &c) { c++; } };
+  //   struct B : virtual A {
+  //     B(int count) : A(count) { printf("%d\n", count); }
+  //   };
+  // ...although even this example could in principle be emitted as a
+  // delegation since the address of the parameter doesn't escape.
+  if (Ctor->getParent()->getNumVBases()) {
+    // TODO: white-list trivial vbase initializers.  This case wouldn't
+    // be subject to the restrictions below.
+
+    // TODO: white-list cases where:
+    //  - there are no non-reference parameters to the constructor
+    //  - the initializers don't access any non-reference parameters
+    //  - the initializers don't take the address of non-reference
+    //    parameters
+    //  - etc.
+    // If we ever add any of the above cases, remember that:
+    //  - function-try-blocks will always blacklist this optimization
+    //  - we need to perform the constructor prologue and cleanup in
+    //    EmitConstructorBody.
+
+    return false;
+  }
+
+  // We also disable the optimization for variadic functions because
+  // it's impossible to "re-pass" varargs.
+  if (Ctor->getType()->getAs<FunctionProtoType>()->isVariadic())
+    return false;
+
+  return true;
+}
+
 /// EmitConstructorBody - Emits the body of the current constructor.
 void CodeGenFunction::EmitConstructorBody(FunctionArgList &Args) {
   const CXXConstructorDecl *Ctor = cast<CXXConstructorDecl>(CurGD.getDecl());
   CXXCtorType CtorType = CurGD.getCtorType();
 
+  // Before we go any further, try the complete->base constructor
+  // delegation optimization.
+  if (CtorType == Ctor_Complete && IsConstructorDelegationValid(Ctor)) {
+    EmitDelegateCXXConstructorCall(Ctor, Ctor_Base, Args);
+    return;
+  }
+
   Stmt *Body = Ctor->getBody();
 
-  // Some of the optimizations we want to do can't be done with
-  // function try blocks.
+  // Enter the function-try-block before the constructor prologue if
+  // applicable.
   CXXTryStmtInfo TryInfo;
-  bool isTryBody = (Body && isa<CXXTryStmt>(Body));
-  if (isTryBody)
+  bool IsTryBody = (Body && isa<CXXTryStmt>(Body));
+
+  if (IsTryBody)
     TryInfo = EnterCXXTryStmt(*cast<CXXTryStmt>(Body));
 
   unsigned CleanupStackSize = CleanupEntries.size();
 
-  // Emit the constructor prologue, i.e. the base and member initializers.
-
-  // TODO: for non-variadic complete-object constructors without a
-  // function try block for a body, we can get away with just emitting
-  // the vbase initializers, then calling the base constructor.
+  // Emit the constructor prologue, i.e. the base and member
+  // initializers.
   EmitCtorPrologue(Ctor, CtorType);
 
   // Emit the body of the statement.
-  if (isTryBody)
+  if (IsTryBody)
     EmitStmt(cast<CXXTryStmt>(Body)->getTryBlock());
   else if (Body)
     EmitStmt(Body);
@@ -933,7 +982,7 @@
   // constructed.
   EmitCleanupBlocks(CleanupStackSize);
 
-  if (isTryBody)
+  if (IsTryBody)
     ExitCXXTryStmt(*cast<CXXTryStmt>(Body), TryInfo);
 }
 
@@ -1406,6 +1455,71 @@
   EmitCXXMemberCall(D, Callee, ReturnValueSlot(), This, VTT, ArgBeg, ArgEnd);
 }
 
+void
+CodeGenFunction::EmitDelegateCXXConstructorCall(const CXXConstructorDecl *Ctor,
+                                                CXXCtorType CtorType,
+                                                const FunctionArgList &Args) {
+  CallArgList DelegateArgs;
+
+  FunctionArgList::const_iterator I = Args.begin(), E = Args.end();
+  assert(I != E && "no parameters to constructor");
+
+  // this
+  DelegateArgs.push_back(std::make_pair(RValue::get(LoadCXXThis()),
+                                        I->second));
+  ++I;
+
+  // vtt
+  if (llvm::Value *VTT = GetVTTParameter(*this, GlobalDecl(Ctor, CtorType))) {
+    QualType VoidPP = getContext().getPointerType(getContext().VoidPtrTy);
+    DelegateArgs.push_back(std::make_pair(RValue::get(VTT), VoidPP));
+
+    if (CGVtableInfo::needsVTTParameter(CurGD)) {
+      assert(I != E && "cannot skip vtt parameter, already done with args");
+      assert(I->second == VoidPP && "skipping parameter not of vtt type");
+      ++I;
+    }
+  }
+
+  // Explicit arguments.
+  for (; I != E; ++I) {
+    
+    const VarDecl *Param = I->first;
+    QualType ArgType = Param->getType(); // because we're passing it to itself
+
+    // StartFunction converted the ABI-lowered parameter(s) into a
+    // local alloca.  We need to turn that into an r-value suitable
+    // for EmitCall.
+    llvm::Value *Local = GetAddrOfLocalVar(Param);
+    RValue Arg;
+ 
+    // For the most part, we just need to load the alloca, except:
+    // 1) aggregate r-values are actually pointers to temporaries, and
+    // 2) references to aggregates are pointers directly to the aggregate.
+    // I don't know why references to non-aggregates are different here.
+    if (ArgType->isReferenceType()) {
+      const ReferenceType *RefType = ArgType->getAs<ReferenceType>();
+      if (hasAggregateLLVMType(RefType->getPointeeType()))
+        Arg = RValue::getAggregate(Local);
+      else
+        // Locals which are references to scalars are represented
+        // with allocas holding the pointer.
+        Arg = RValue::get(Builder.CreateLoad(Local));
+    } else {
+      if (hasAggregateLLVMType(ArgType))
+        Arg = RValue::getAggregate(Local);
+      else
+        Arg = RValue::get(EmitLoadOfScalar(Local, false, ArgType));
+    }
+
+    DelegateArgs.push_back(std::make_pair(Arg, ArgType));
+  }
+
+  EmitCall(CGM.getTypes().getFunctionInfo(Ctor, CtorType),
+           CGM.GetAddrOfCXXConstructor(Ctor, CtorType), 
+           ReturnValueSlot(), DelegateArgs, Ctor);
+}
+
 void CodeGenFunction::EmitCXXDestructorCall(const CXXDestructorDecl *DD,
                                             CXXDtorType Type,
                                             llvm::Value *This) {
diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h
index 1c5cd67..c4f0a9f 100644
--- a/lib/CodeGen/CodeGenFunction.h
+++ b/lib/CodeGen/CodeGenFunction.h
@@ -789,6 +789,9 @@
                                const CXXRecordDecl *BaseClassDecl,
                                QualType Ty);
 
+  void EmitDelegateCXXConstructorCall(const CXXConstructorDecl *Ctor,
+                                      CXXCtorType CtorType,
+                                      const FunctionArgList &Args);
   void EmitCXXConstructorCall(const CXXConstructorDecl *D, CXXCtorType Type,
                               llvm::Value *This,
                               CallExpr::const_arg_iterator ArgBeg,
diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp
index 41575e4..f819382 100644
--- a/lib/CodeGen/CodeGenModule.cpp
+++ b/lib/CodeGen/CodeGenModule.cpp
@@ -1195,28 +1195,8 @@
 
 
 void CodeGenModule::EmitGlobalFunctionDefinition(GlobalDecl GD) {
-  const llvm::FunctionType *Ty;
   const FunctionDecl *D = cast<FunctionDecl>(GD.getDecl());
-
-  if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(D)) {
-    bool isVariadic = D->getType()->getAs<FunctionProtoType>()->isVariadic();
-
-    Ty = getTypes().GetFunctionType(getTypes().getFunctionInfo(MD), isVariadic);
-  } else {
-    Ty = cast<llvm::FunctionType>(getTypes().ConvertType(D->getType()));
-
-    // As a special case, make sure that definitions of K&R function
-    // "type foo()" aren't declared as varargs (which forces the backend
-    // to do unnecessary work).
-    if (D->getType()->isFunctionNoProtoType()) {
-      assert(Ty->isVarArg() && "Didn't lower type as expected");
-      // Due to stret, the lowered function could have arguments.
-      // Just create the same type as was lowered by ConvertType
-      // but strip off the varargs bit.
-      std::vector<const llvm::Type*> Args(Ty->param_begin(), Ty->param_end());
-      Ty = llvm::FunctionType::get(Ty->getReturnType(), Args, false);
-    }
-  }
+  const llvm::FunctionType *Ty = getTypes().GetFunctionType(GD);
 
   // Get or create the prototype for the function.
   llvm::Constant *Entry = GetAddrOfFunction(GD, Ty);
diff --git a/lib/CodeGen/CodeGenModule.h b/lib/CodeGen/CodeGenModule.h
index a5e1d9f..ac83326 100644
--- a/lib/CodeGen/CodeGenModule.h
+++ b/lib/CodeGen/CodeGenModule.h
@@ -485,6 +485,7 @@
   // C++ related functions.
 
   bool TryEmitDefinitionAsAlias(GlobalDecl Alias, GlobalDecl Target);
+  bool TryEmitBaseDestructorAsAlias(const CXXDestructorDecl *D);
 
   void EmitNamespace(const NamespaceDecl *D);
   void EmitLinkageSpec(const LinkageSpecDecl *D);
diff --git a/lib/CodeGen/CodeGenTypes.h b/lib/CodeGen/CodeGenTypes.h
index 87ba0bc..7ce96f4 100644
--- a/lib/CodeGen/CodeGenTypes.h
+++ b/lib/CodeGen/CodeGenTypes.h
@@ -168,6 +168,8 @@
   const llvm::FunctionType *GetFunctionType(const CGFunctionInfo &Info,
                                             bool IsVariadic);
 
+  const llvm::FunctionType *GetFunctionType(GlobalDecl GD);
+
 
   /// GetFunctionTypeForVtable - Get the LLVM function type for use in a vtable,
   /// given a CXXMethodDecl. If the method to has an incomplete return type, 
diff --git a/test/CodeGenCXX/constructors.cpp b/test/CodeGenCXX/constructors.cpp
new file mode 100644
index 0000000..2c95c91
--- /dev/null
+++ b/test/CodeGenCXX/constructors.cpp
@@ -0,0 +1,94 @@
+// RUN: %clang_cc1 -triple x86_64-apple-darwin10 %s -emit-llvm -o - | FileCheck %s
+
+struct Member { int x; Member(); Member(int); Member(const Member &); };
+struct VBase { int x; VBase(); VBase(int); VBase(const VBase &); };
+
+struct ValueClass {
+  ValueClass(int x, int y) : x(x), y(y) {}
+  int x;
+  int y;
+}; // subject to ABI trickery
+
+
+
+/* Test basic functionality. */
+class A {
+  A(struct Undeclared &);
+  A(ValueClass);
+  Member mem;
+};
+
+A::A(struct Undeclared &ref) : mem(0) {}
+
+// Check that delegation works.
+// CHECK: define void @_ZN1AC1ER10Undeclared(
+// CHECK: call void @_ZN1AC2ER10Undeclared(
+
+// CHECK: define void @_ZN1AC2ER10Undeclared(
+// CHECK: call void @_ZN6MemberC1Ei(
+
+A::A(ValueClass v) : mem(v.y - v.x) {}
+
+// CHECK: define void @_ZN1AC1E10ValueClass(
+// CHECK: call void @_ZN1AC2E10ValueClass(
+
+// CHECK: define void @_ZN1AC2E10ValueClass(
+// CHECK: call void @_ZN6MemberC1Ei(
+
+
+/* Test that things work for inheritance. */
+struct B : A {
+  B(struct Undeclared &);
+  Member mem;
+};
+
+B::B(struct Undeclared &ref) : A(ref), mem(1) {}
+
+// CHECK: define void @_ZN1BC1ER10Undeclared(
+// CHECK: call void @_ZN1BC2ER10Undeclared(
+
+// CHECK: define void @_ZN1BC2ER10Undeclared(
+// CHECK: call void @_ZN1AC2ER10Undeclared(
+// CHECK: call void @_ZN6MemberC1Ei(
+
+
+
+/* Test that the delegation optimization is disabled for classes with
+   virtual bases (for now).  This is necessary because a vbase
+   initializer could access one of the parameter variables by
+   reference.  That's a solvable problem, but let's not solve it right
+   now. */
+struct C : virtual A {
+  C(int);
+  Member mem;
+};
+C::C(int x) : A(ValueClass(x, x+1)), mem(x * x) {}
+
+// CHECK: define void @_ZN1CC1Ei(
+// CHECK: call void @_ZN10ValueClassC1Eii(
+// CHECK: call void @_ZN1AC2E10ValueClass(
+// CHECK: call void @_ZN6MemberC1Ei(
+
+// CHECK: define void @_ZN1CC2Ei(
+// CHECK: call void @_ZN6MemberC1Ei(
+
+
+
+/* Test that the delegation optimization is disabled for varargs
+   constructors. */
+struct D : A {
+  D(int, ...);
+  Member mem;
+};
+
+D::D(int x, ...) : A(ValueClass(x, x+1)), mem(x*x) {}
+
+// CHECK: define void @_ZN1DC1Eiz(
+// CHECK: call void @_ZN10ValueClassC1Eii(
+// CHECK: call void @_ZN1AC2E10ValueClass(
+// CHECK: call void @_ZN6MemberC1Ei(
+
+// CHECK: define void @_ZN1DC2Eiz(
+// CHECK: call void @_ZN10ValueClassC1Eii(
+// CHECK: call void @_ZN1AC2E10ValueClass(
+// CHECK: call void @_ZN6MemberC1Ei(
diff --git a/test/CodeGenCXX/default-arguments.cpp b/test/CodeGenCXX/default-arguments.cpp
index 282e5d0..2ed1567 100644
--- a/test/CodeGenCXX/default-arguments.cpp
+++ b/test/CodeGenCXX/default-arguments.cpp
@@ -43,11 +43,7 @@
 };
 
 // CHECK: define void @_ZN1CC1Ev(
-// CHECK: call void @_ZN2A1C1Ev(
-// CHECK: call void @_ZN2A2C1Ev(
-// CHECK: call void @_ZN1BC1ERK2A1RK2A2(
-// CHECK: call void @_ZN2A2D1Ev
-// CHECK: call void @_ZN2A1D1Ev
+// CHECK: call void @_ZN1CC2Ev(
 
 // CHECK: define void @_ZN1CC2Ev(
 // CHECK: call void @_ZN2A1C1Ev(
diff --git a/test/CodeGenCXX/destructors.cpp b/test/CodeGenCXX/destructors.cpp
index f06661a..accd1b3 100644
--- a/test/CodeGenCXX/destructors.cpp
+++ b/test/CodeGenCXX/destructors.cpp
@@ -1,4 +1,11 @@
 // RUN: %clang_cc1 %s -emit-llvm -o - -mconstructor-aliases | FileCheck %s
+
+// CHECK: @_ZN5test01AD1Ev = alias {{.*}} @_ZN5test01AD2Ev
+// CHECK: @_ZN5test11MD2Ev = alias {{.*}} @_ZN5test11AD2Ev
+// CHECK: @_ZN5test11ND2Ev = alias {{.*}} @_ZN5test11AD2Ev
+// CHECK: @_ZN5test11OD2Ev = alias {{.*}} @_ZN5test11AD2Ev
+// CHECK: @_ZN5test11SD2Ev = alias bitcast {{.*}} @_ZN5test11AD2Ev
+
 struct A {
   int a;
   
@@ -60,7 +67,7 @@
   // The function-try-block won't suppress -mconstructor-aliases here.
   A::~A() try { } catch (int i) {}
 
-// CHECK: @_ZN5test01AD1Ev = alias {{.*}} @_ZN5test01AD2Ev
+// complete destructor alias tested above
 
 // CHECK: define void @_ZN5test01AD2Ev
 // CHECK: invoke void @_ZN5test06MemberD1Ev
@@ -89,3 +96,40 @@
 // CHECK: invoke void @_ZN5test04BaseD2Ev
 // CHECK:   unwind label [[BASE_UNWIND:%[a-zA-Z0-9.]+]]
 }
+
+// Test base-class aliasing.
+namespace test1 {
+  struct A { ~A(); char ***m; }; // non-trivial destructor
+  struct B { ~B(); }; // non-trivial destructor
+  struct Empty { }; // trivial destructor, empty
+  struct NonEmpty { int x; }; // trivial destructor, non-empty
+
+  struct M : A { ~M(); };
+  M::~M() {} // alias tested above
+
+  struct N : A, Empty { ~N(); };
+  N::~N() {} // alias tested above
+
+  struct O : Empty, A { ~O(); };
+  O::~O() {} // alias tested above
+
+  struct P : NonEmpty, A { ~P(); };
+  P::~P() {} // CHECK: define void @_ZN5test11PD2Ev
+
+  struct Q : A, B { ~Q(); };
+  Q::~Q() {} // CHECK: define void @_ZN5test11QD2Ev
+
+  struct R : A { ~R(); };
+  R::~R() { A a; } // CHECK: define void @_ZN5test11RD2Ev
+
+  struct S : A { ~S(); int x; };
+  S::~S() {} // alias tested above
+
+  struct T : A { ~T(); B x; };
+  T::~T() {} // CHECK: define void @_ZN5test11TD2Ev
+
+  // The VTT parameter prevents this.  We could still make this work
+  // for calling conventions that are safe against extra parameters.
+  struct U : A, virtual B { ~U(); };
+  U::~U() {} // CHECK: define void @_ZN5test11UD2Ev
+}
diff --git a/test/CodeGenCXX/virtual-destructor-calls.cpp b/test/CodeGenCXX/virtual-destructor-calls.cpp
index 91fd598..c5b9262 100644
--- a/test/CodeGenCXX/virtual-destructor-calls.cpp
+++ b/test/CodeGenCXX/virtual-destructor-calls.cpp
@@ -1,16 +1,25 @@
 // RUN: %clang_cc1 -emit-llvm %s -o - -triple=x86_64-apple-darwin10 -mconstructor-aliases | FileCheck %s
 
+struct Member {
+  ~Member();
+};
+
 struct A {
   virtual ~A();
 };
 
 struct B : A {
+  Member m;
   virtual ~B();
 };
 
 // Complete dtor: just an alias because there are no virtual bases.
 // CHECK: @_ZN1BD1Ev = alias {{.*}} @_ZN1BD2Ev
 
+// (aliases from C)
+// CHECK: @_ZN1CD1Ev = alias {{.*}} @_ZN1CD2Ev
+// CHECK: @_ZN1CD2Ev = alias bitcast {{.*}} @_ZN1BD2Ev
+
 // Deleting dtor: defers to the complete dtor.
 // CHECK: define void @_ZN1BD0Ev
 // CHECK: call void @_ZN1BD1Ev
@@ -18,6 +27,22 @@
 
 // Base dtor: actually calls A's base dtor.
 // CHECK: define void @_ZN1BD2Ev
+// CHECK: call void @_ZN6MemberD1Ev
 // CHECK: call void @_ZN1AD2Ev
 
 B::~B() { }
+
+struct C : B {
+  ~C();
+};
+
+C::~C() { }
+
+// Complete dtor: just an alias (checked above).
+
+// Deleting dtor: defers to the complete dtor.
+// CHECK: define void @_ZN1CD0Ev
+// CHECK: call void @_ZN1CD1Ev
+// CHECK: call void @_ZdlPv
+
+// Base dtor: just an alias to B's base dtor.
diff --git a/test/CodeGenCXX/vtable-pointer-initialization.cpp b/test/CodeGenCXX/vtable-pointer-initialization.cpp
index ebe5315..75620ab 100644
--- a/test/CodeGenCXX/vtable-pointer-initialization.cpp
+++ b/test/CodeGenCXX/vtable-pointer-initialization.cpp
@@ -42,13 +42,16 @@
 void f() { B b; }
 
 // CHECK: define linkonce_odr void @_ZN1BC1Ev(
-// CHECK: call void @_ZN4BaseC2Ev(
-// CHECK: store i8** getelementptr inbounds ([3 x i8*]* @_ZTV1B, i64 0, i64 2)
-// CHECK: call void @_ZN5FieldC1Ev
-// CHECK: ret void
+// CHECK: call void @_ZN1BC2Ev(
 
 // CHECK: define linkonce_odr void @_ZN1BD1Ev(
 // CHECK: store i8** getelementptr inbounds ([3 x i8*]* @_ZTV1B, i64 0, i64 2)
 // CHECK: call void @_ZN5FieldD1Ev(
 // CHECK: call void @_ZN4BaseD2Ev(
 // CHECK: ret void
+
+// CHECK: define linkonce_odr void @_ZN1BC2Ev(
+// CHECK: call void @_ZN4BaseC2Ev(
+// CHECK: store i8** getelementptr inbounds ([3 x i8*]* @_ZTV1B, i64 0, i64 2)
+// CHECK: call void @_ZN5FieldC1Ev
+// CHECK: ret void