[cfe-commits] r104025 - in /cfe/trunk: lib/CodeGen/CGExprConstant.cpp lib/CodeGen/CGRecordLayoutBuilder.cpp test/CodeGenCXX/pointers-to-data-members.cpp

Anders Carlsson andersca at mac.com
Tue May 18 09:51:41 PDT 2010


Author: andersca
Date: Tue May 18 11:51:41 2010
New Revision: 104025

URL: http://llvm.org/viewvc/llvm-project?rev=104025&view=rev
Log:
Correctly initialize bases with member pointers. This should fix PR6441 but that test case is a bit weird and I'd like to investigate further before closing that bug.

Modified:
    cfe/trunk/lib/CodeGen/CGExprConstant.cpp
    cfe/trunk/lib/CodeGen/CGRecordLayoutBuilder.cpp
    cfe/trunk/test/CodeGenCXX/pointers-to-data-members.cpp

Modified: cfe/trunk/lib/CodeGen/CGExprConstant.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprConstant.cpp?rev=104025&r1=104024&r2=104025&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGExprConstant.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExprConstant.cpp Tue May 18 11:51:41 2010
@@ -984,6 +984,79 @@
   return C;
 }
 
+static void
+FillInNullDataMemberPointers(CodeGenModule &CGM, QualType T,
+                             std::vector<llvm::Constant *> &Elements,
+                             uint64_t StartOffset) {
+  assert(StartOffset % 8 == 0 && "StartOffset not byte aligned!");
+
+  if (!CGM.getTypes().ContainsPointerToDataMember(T))
+    return;
+
+  if (const ConstantArrayType *CAT = 
+        CGM.getContext().getAsConstantArrayType(T)) {
+    QualType ElementTy = CAT->getElementType();
+    uint64_t ElementSize = CGM.getContext().getTypeSize(ElementTy);
+    
+    for (uint64_t I = 0, E = CAT->getSize().getZExtValue(); I != E; ++I) {
+      FillInNullDataMemberPointers(CGM, ElementTy, Elements,
+                                   StartOffset + I * ElementSize);
+    }
+  } else if (const RecordType *RT = T->getAs<RecordType>()) {
+    const CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
+    const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD);
+
+    // Go through all bases and fill in any null pointer to data members.
+    for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(),
+         E = RD->bases_end(); I != E; ++I) {
+      assert(!I->isVirtual() && "Should not see virtual bases here!");
+      
+      const CXXRecordDecl *BaseDecl = 
+      cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl());
+      
+      // Ignore empty bases.
+      if (BaseDecl->isEmpty())
+        continue;
+      
+      // Ignore bases that don't have any pointer to data members.
+      if (!CGM.getTypes().ContainsPointerToDataMember(BaseDecl))
+        continue;
+
+      uint64_t BaseOffset = Layout.getBaseClassOffset(BaseDecl);
+      FillInNullDataMemberPointers(CGM, I->getType(),
+                                   Elements, StartOffset + BaseOffset);
+    }
+    
+    // Visit all fields.
+    unsigned FieldNo = 0;
+    for (RecordDecl::field_iterator I = RD->field_begin(),
+         E = RD->field_end(); I != E; ++I, ++FieldNo) {
+      QualType FieldType = I->getType();
+      
+      if (!CGM.getTypes().ContainsPointerToDataMember(FieldType))
+        continue;
+
+      uint64_t FieldOffset = StartOffset + Layout.getFieldOffset(FieldNo);
+      FillInNullDataMemberPointers(CGM, FieldType, Elements, FieldOffset);
+    }
+  } else {
+    assert(T->isMemberPointerType() && "Should only see member pointers here!");
+    assert(!T->getAs<MemberPointerType>()->getPointeeType()->isFunctionType() &&
+           "Should only see pointers to data members here!");
+  
+    uint64_t StartIndex = StartOffset / 8;
+    uint64_t EndIndex = StartIndex + CGM.getContext().getTypeSize(T) / 8;
+
+    llvm::Constant *NegativeOne =
+      llvm::ConstantInt::get(llvm::Type::getInt8Ty(CGM.getLLVMContext()),
+                             -1ULL, /*isSigned=*/true);
+
+    // Fill in the null data member pointer.
+    for (uint64_t I = StartIndex; I != EndIndex; ++I)
+      Elements[I] = NegativeOne;
+  }
+}
+
 llvm::Constant *CodeGenModule::EmitNullConstant(QualType T) {
   if (!getTypes().ContainsPointerToDataMember(T))
     return llvm::Constant::getNullValue(getTypes().ConvertTypeForMem(T));
@@ -1005,21 +1078,60 @@
 
   if (const RecordType *RT = T->getAs<RecordType>()) {
     const CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
-    assert(!RD->getNumBases() && 
-           "FIXME: Handle zero-initializing structs with bases and "
-           "pointers to data members.");
     const llvm::StructType *STy =
       cast<llvm::StructType>(getTypes().ConvertTypeForMem(T));
     unsigned NumElements = STy->getNumElements();
     std::vector<llvm::Constant *> Elements(NumElements);
 
+    const CGRecordLayout &Layout = getTypes().getCGRecordLayout(RD);
+    
+    // Go through all bases and fill in any null pointer to data members.
+    for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(),
+         E = RD->bases_end(); I != E; ++I) {
+      assert(!I->isVirtual() && "Should not see virtual bases here!");
+
+      const CXXRecordDecl *BaseDecl = 
+        cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl());
+
+      // Ignore empty bases.
+      if (BaseDecl->isEmpty())
+        continue;
+
+      // Ignore bases that don't have any pointer to data members.
+      if (!getTypes().ContainsPointerToDataMember(BaseDecl))
+        continue;
+
+      // Currently, all bases are arrays of i8. Figure out how many elements
+      // this base array has.
+      unsigned BaseFieldNo = Layout.getNonVirtualBaseLLVMFieldNo(BaseDecl);
+      const llvm::ArrayType *BaseArrayTy =
+        cast<llvm::ArrayType>(STy->getElementType(BaseFieldNo));
+      
+      unsigned NumBaseElements = BaseArrayTy->getNumElements();
+      std::vector<llvm::Constant *> BaseElements(NumBaseElements);
+      
+      // Now fill in null data member pointers.
+      FillInNullDataMemberPointers(*this, I->getType(), BaseElements, 0);
+      
+      // Now go through all other elements and zero them out.
+      if (NumBaseElements) {
+        llvm::Constant *Zero =
+          llvm::ConstantInt::get(llvm::Type::getInt8Ty(getLLVMContext()), 0);
+        
+        for (unsigned I = 0; I != NumBaseElements; ++I) {
+          if (!BaseElements[I])
+            BaseElements[I] = Zero;
+        }
+      }
+      
+      Elements[BaseFieldNo] = llvm::ConstantArray::get(BaseArrayTy, 
+                                                       BaseElements);
+    }
+      
     for (RecordDecl::field_iterator I = RD->field_begin(),
          E = RD->field_end(); I != E; ++I) {
       const FieldDecl *FD = *I;
-      
-      const CGRecordLayout &RL =
-        getTypes().getCGRecordLayout(FD->getParent());
-      unsigned FieldNo = RL.getLLVMFieldNo(FD);
+      unsigned FieldNo = Layout.getLLVMFieldNo(FD);
       Elements[FieldNo] = EmitNullConstant(FD->getType());
     }
     
@@ -1032,6 +1144,7 @@
     return llvm::ConstantStruct::get(STy, Elements);
   }
 
+  assert(T->isMemberPointerType() && "Should only see member pointers here!");
   assert(!T->getAs<MemberPointerType>()->getPointeeType()->isFunctionType() &&
          "Should only see pointers to data members here!");
   

Modified: cfe/trunk/lib/CodeGen/CGRecordLayoutBuilder.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGRecordLayoutBuilder.cpp?rev=104025&r1=104024&r2=104025&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGRecordLayoutBuilder.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGRecordLayoutBuilder.cpp Tue May 18 11:51:41 2010
@@ -118,6 +118,7 @@
   /// CheckForPointerToDataMember - Check if the given type contains a pointer
   /// to data member.
   void CheckForPointerToDataMember(QualType T);
+  void CheckForPointerToDataMember(const CXXRecordDecl *RD);
 
 public:
   CGRecordLayoutBuilder(CodeGenTypes &Types)
@@ -456,6 +457,8 @@
     return;
   }
 
+  CheckForPointerToDataMember(BaseDecl);
+
   // FIXME: Actually use a better type than [sizeof(BaseDecl) x i8] when we can.
   AppendPadding(BaseOffset / 8, 1);
   
@@ -618,15 +621,24 @@
   } else if (const RecordType *RT = T->getAs<RecordType>()) {
     const CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
 
-    // FIXME: It would be better if there was a way to explicitly compute the
-    // record layout instead of converting to a type.
-    Types.ConvertTagDeclType(RD);
+    return CheckForPointerToDataMember(RD);
+  }
+}
 
-    const CGRecordLayout &Layout = Types.getCGRecordLayout(RD);
+void
+CGRecordLayoutBuilder::CheckForPointerToDataMember(const CXXRecordDecl *RD) {
+  // This record already contains a member pointer.
+  if (ContainsPointerToDataMember)
+    return;
 
-    if (Layout.containsPointerToDataMember())
-      ContainsPointerToDataMember = true;
-  }
+  // FIXME: It would be better if there was a way to explicitly compute the
+  // record layout instead of converting to a type.
+  Types.ConvertTagDeclType(RD);
+  
+  const CGRecordLayout &Layout = Types.getCGRecordLayout(RD);
+  
+  if (Layout.containsPointerToDataMember())
+    ContainsPointerToDataMember = true;
 }
 
 CGRecordLayout *CodeGenTypes::ComputeRecordLayout(const RecordDecl *D) {

Modified: cfe/trunk/test/CodeGenCXX/pointers-to-data-members.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/pointers-to-data-members.cpp?rev=104025&r1=104024&r2=104025&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/pointers-to-data-members.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/pointers-to-data-members.cpp Tue May 18 11:51:41 2010
@@ -35,6 +35,21 @@
       int A::*pa;
     } s;
   } ss;
+  
+  struct A {
+    int A::*a;
+    int b;
+  };
+
+  struct B {
+    A a[10];
+    char c;
+    int B::*b;
+  };
+
+  struct C : A, B { int j; };
+  // CHECK: @_ZN8ZeroInit1cE = global %"struct.ZeroInit::C" { [16 x i8] c"\FF\FF\FF\FF\FF\FF\FF\FF\00\00\00\00\00\00\00\00", [176 x i8] c"\FF\FF\FF\FF\FF\FF\FF\FF\00\00\00\00\00\00\00\00\FF\FF\FF\FF\FF\FF\FF\FF\00\00\00\00\00\00\00\00\FF\FF\FF\FF\FF\FF\FF\FF\00\00\00\00\00\00\00\00\FF\FF\FF\FF\FF\FF\FF\FF\00\00\00\00\00\00\00\00\FF\FF\FF\FF\FF\FF\FF\FF\00\00\00\00\00\00\00\00\FF\FF\FF\FF\FF\FF\FF\FF\00\00\00\00\00\00\00\00\FF\FF\FF\FF\FF\FF\FF\FF\00\00\00\00\00\00\00\00\FF\FF\FF\FF\FF\FF\FF\FF\00\00\00\00\00\00\00\00\FF\FF\FF\FF\FF\FF\FF\FF\00\00\00\00\00\00\00\00\FF\FF\FF\FF\FF\FF\FF\FF\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\FF\FF\FF\FF\FF\FF\FF\FF", i32 0, [4 x i8] zeroinitializer }
+  C c;
 }
 
 // PR5674
@@ -102,3 +117,4 @@
 A::A() : a() {}
 
 }
+





More information about the cfe-commits mailing list