]> granicus.if.org Git - clang/commitdiff
Add VTT parameter to base ctors/dtors with virtual bases. (They aren't used yet).
authorAnders Carlsson <andersca@mac.com>
Wed, 25 Nov 2009 03:15:49 +0000 (03:15 +0000)
committerAnders Carlsson <andersca@mac.com>
Wed, 25 Nov 2009 03:15:49 +0000 (03:15 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@89835 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/CGCXX.cpp
lib/CodeGen/CGCall.cpp
lib/CodeGen/CodeGenFunction.cpp
lib/CodeGen/CodeGenFunction.h
lib/CodeGen/CodeGenTypes.h
test/CodeGenCXX/virtual-bases.cpp [new file with mode: 0644]

index e1b673933907d346fe96d9df71de4b8a50877445..71cdf95f48beff3590ca183125e672fa785be0cb 100644 (file)
@@ -765,7 +765,7 @@ CodeGenModule::GetAddrOfCXXConstructor(const CXXConstructorDecl *D,
                                        CXXCtorType Type) {
   const FunctionProtoType *FPT = D->getType()->getAs<FunctionProtoType>();
   const llvm::FunctionType *FTy =
-    getTypes().GetFunctionType(getTypes().getFunctionInfo(D), 
+    getTypes().GetFunctionType(getTypes().getFunctionInfo(D, Type), 
                                FPT->isVariadic());
 
   const char *Name = getMangledCXXCtorName(D, Type);
@@ -803,7 +803,7 @@ llvm::Function *
 CodeGenModule::GetAddrOfCXXDestructor(const CXXDestructorDecl *D,
                                       CXXDtorType Type) {
   const llvm::FunctionType *FTy =
-    getTypes().GetFunctionType(getTypes().getFunctionInfo(D), false);
+    getTypes().GetFunctionType(getTypes().getFunctionInfo(D, Type), false);
 
   const char *Name = getMangledCXXDtorName(D, Type);
   return cast<llvm::Function>(
index 16f4e7b533421cdd1e0071b2f48291c535e4eb57..decc73c6d458c4bb9fd86d442c6cde74e1488fac 100644 (file)
@@ -91,6 +91,42 @@ const CGFunctionInfo &CodeGenTypes::getFunctionInfo(const CXXMethodDecl *MD) {
                          getCallingConventionForDecl(MD));
 }
 
+const CGFunctionInfo &CodeGenTypes::getFunctionInfo(const CXXConstructorDecl *D, 
+                                                    CXXCtorType Type) {
+  llvm::SmallVector<QualType, 16> ArgTys;
+
+  // Add the 'this' pointer.
+  ArgTys.push_back(D->getThisType(Context));
+
+  // Check if we need to add a VTT parameter (which has type void **).
+  if (Type == Ctor_Base && D->getParent()->getNumVBases() != 0)
+    ArgTys.push_back(Context.getPointerType(Context.VoidPtrTy));
+  
+  const FunctionProtoType *FTP = D->getType()->getAs<FunctionProtoType>();
+  for (unsigned i = 0, e = FTP->getNumArgs(); i != e; ++i)
+    ArgTys.push_back(FTP->getArgType(i));
+  return getFunctionInfo(FTP->getResultType(), ArgTys,
+                         getCallingConventionForDecl(D));
+}
+
+const CGFunctionInfo &CodeGenTypes::getFunctionInfo(const CXXDestructorDecl *D,
+                                                    CXXDtorType Type) {
+  llvm::SmallVector<QualType, 16> ArgTys;
+  
+  // Add the 'this' pointer.
+  ArgTys.push_back(D->getThisType(Context));
+  
+  // Check if we need to add a VTT parameter (which has type void **).
+  if (Type == Dtor_Base && D->getParent()->getNumVBases() != 0)
+    ArgTys.push_back(Context.getPointerType(Context.VoidPtrTy));
+  
+  const FunctionProtoType *FTP = D->getType()->getAs<FunctionProtoType>();
+  for (unsigned i = 0, e = FTP->getNumArgs(); i != e; ++i)
+    ArgTys.push_back(FTP->getArgType(i));
+  return getFunctionInfo(FTP->getResultType(), ArgTys,
+                         getCallingConventionForDecl(D));
+}
+
 const CGFunctionInfo &CodeGenTypes::getFunctionInfo(const FunctionDecl *FD) {
   if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD))
     if (MD->isInstance())
index a4cbf449efcfbd84de81cf9790b07638723aa410..6e0a77ca1b0b36df5dcd1cd3566066244dcf1faf 100644 (file)
@@ -29,7 +29,7 @@ CodeGenFunction::CodeGenFunction(CodeGenModule &cgm)
     Builder(cgm.getModule().getContext()),
     DebugInfo(0), IndirectBranch(0),
     SwitchInsn(0), CaseRangeBlock(0), InvokeDest(0),
-    CXXThisDecl(0),
+    CXXThisDecl(0), CXXVTTDecl(0),
     ConditionalBranchLevel(0) {
   LLVMIntTy = ConvertType(getContext().IntTy);
   LLVMPointerWidth = Target.getPointerWidth(0);
@@ -217,6 +217,24 @@ void CodeGenFunction::StartFunction(GlobalDecl GD, QualType RetTy,
   }
 }
 
+static bool NeedsVTTParameter(GlobalDecl GD) {
+  const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl());
+  
+  // We don't have any virtual bases, just return early.
+  if (!MD->getParent()->getNumVBases())
+    return false;
+  
+  // Check if we have a base constructor.
+  if (isa<CXXConstructorDecl>(MD) && GD.getCtorType() == Ctor_Base)
+    return true;
+
+  // Check if we have a base destructor.
+  if (isa<CXXDestructorDecl>(MD) && GD.getDtorType() == Dtor_Base)
+    return true;
+  
+  return false;
+}
+
 void CodeGenFunction::GenerateCode(GlobalDecl GD,
                                    llvm::Function *Fn) {
   const FunctionDecl *FD = cast<FunctionDecl>(GD.getDecl());
@@ -236,6 +254,16 @@ void CodeGenFunction::GenerateCode(GlobalDecl GD,
                                               &getContext().Idents.get("this"),
                                               MD->getThisType(getContext()));
       Args.push_back(std::make_pair(CXXThisDecl, CXXThisDecl->getType()));
+      
+      // Check if we need a VTT parameter as well.
+      if (NeedsVTTParameter(GD)) {
+        // FIXME: The comment about using a fake decl above applies here too.
+        QualType T = getContext().getPointerType(getContext().VoidPtrTy);
+        CXXVTTDecl = 
+          ImplicitParamDecl::Create(getContext(), 0, SourceLocation(),
+                                    &getContext().Idents.get("vtt"), T);
+        Args.push_back(std::make_pair(CXXVTTDecl, CXXVTTDecl->getType()));
+      }
     }
   }
 
@@ -318,6 +346,10 @@ void CodeGenFunction::GenerateCode(GlobalDecl GD,
   // Destroy the 'this' declaration.
   if (CXXThisDecl)
     CXXThisDecl->Destroy(getContext());
+  
+  // Destroy the VTT declaration.
+  if (CXXVTTDecl)
+    CXXVTTDecl->Destroy(getContext());
 }
 
 /// ContainsLabel - Return true if the statement contains a label in it.  If
index 4fde0dd864fce6fb338a017ad1d32cecb24ed3ea..28e000a49208588c00bbd39387da6674aa1c41fc 100644 (file)
@@ -317,10 +317,15 @@ private:
   /// BlockScopes - Map of which "cleanup scope" scope basic blocks have.
   BlockScopeMap BlockScopes;
 
-  /// CXXThisDecl - When parsing an C++ function, this will hold the implicit
-  /// 'this' declaration.
+  /// CXXThisDecl - When generating code for a C++ member function,
+  /// this will hold the implicit 'this' declaration.
   ImplicitParamDecl *CXXThisDecl;
 
+  /// CXXVTTDecl - When generating code for a base object constructor or
+  /// base object destructor with virtual bases, this will hold the implicit
+  /// VTT parameter.
+  ImplicitParamDecl *CXXVTTDecl;
+  
   /// CXXLiveTemporaryInfo - Holds information about a live C++ temporary.
   struct CXXLiveTemporaryInfo {
     /// Temporary - The live temporary.
index d4adebecde109856b7f0a58c86e52b25ac30111c..55827aac4992c77484e706e0e65207edd6e8cdd7 100644 (file)
@@ -20,6 +20,7 @@
 #include <vector>
 
 #include "CGCall.h"
+#include "CGCXX.h"
 
 namespace llvm {
   class FunctionType;
@@ -34,6 +35,8 @@ namespace llvm {
 namespace clang {
   class ABIInfo;
   class ASTContext;
+  class CXXConstructorDecl;
+  class CXXDestructorDecl;
   class CXXMethodDecl;
   class FieldDecl;
   class FunctionProtoType;
@@ -198,7 +201,11 @@ public:
   const CGFunctionInfo &getFunctionInfo(const FunctionDecl *FD);
   const CGFunctionInfo &getFunctionInfo(const CXXMethodDecl *MD);
   const CGFunctionInfo &getFunctionInfo(const ObjCMethodDecl *MD);
-  
+  const CGFunctionInfo &getFunctionInfo(const CXXConstructorDecl *D,
+                                        CXXCtorType Type);
+  const CGFunctionInfo &getFunctionInfo(const CXXDestructorDecl *D,
+                                        CXXDtorType Type);
+
   // getFunctionInfo - Get the function info for a member function.
   const CGFunctionInfo &getFunctionInfo(const CXXRecordDecl *RD,
                                         const FunctionProtoType *FTP);
diff --git a/test/CodeGenCXX/virtual-bases.cpp b/test/CodeGenCXX/virtual-bases.cpp
new file mode 100644 (file)
index 0000000..4b069ea
--- /dev/null
@@ -0,0 +1,17 @@
+// RUN: clang-cc -emit-llvm %s -o - -triple=x86_64-apple-darwin10 | FileCheck %s
+
+struct A { 
+  A();
+};
+
+// CHECK: define void @_ZN1AC1Ev(%struct.A* %this)
+// CHECK: define void @_ZN1AC2Ev(%struct.A* %this)
+A::A() { }
+
+struct B : virtual A { 
+  B();
+};
+
+// CHECK: define void @_ZN1BC1Ev(%struct.B* %this)
+// CHECK: define void @_ZN1BC2Ev(%struct.B* %this, i8** %vtt)
+B::B() { }