r202320 - PR18962: Fix "Unable to find record layout information for type"

Reid Kleckner reid at kleckner.net
Wed Feb 26 16:03:39 PST 2014


Author: rnk
Date: Wed Feb 26 18:03:39 2014
New Revision: 202320

URL: http://llvm.org/viewvc/llvm-project?rev=202320&view=rev
Log:
PR18962: Fix "Unable to find record layout information for type"

Clang is using llvm::StructType::isOpaque() as a way of signaling if
we've finished record type conversion in
CodeGenTypes::isRecordLayoutComplete().  However, Clang was setting the
body of the type before it finished laying out the type as a base type.
Laying out the %class.C.base LLVM type attempts to convert more types,
eventually recursively attempting to layout 'C' again, at which point we
would say that layout was complete, even though we were still in the
middle of it.

By not setting the body, we correctly signal that layout is not
complete, and things work as expected.

At some point, it might be worth refactoring this to avoid looking at
the LLVM IR types under construction.

Added:
    cfe/trunk/test/CodeGenCXX/pr18962.cpp
Modified:
    cfe/trunk/lib/CodeGen/CGRecordLayoutBuilder.cpp

Modified: cfe/trunk/lib/CodeGen/CGRecordLayoutBuilder.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGRecordLayoutBuilder.cpp?rev=202320&r1=202319&r2=202320&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGRecordLayoutBuilder.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGRecordLayoutBuilder.cpp Wed Feb 26 18:03:39 2014
@@ -631,8 +631,6 @@ CGRecordLayout *CodeGenTypes::ComputeRec
 
   Builder.lower(false);
 
-  Ty->setBody(Builder.FieldTypes, Builder.Packed);
-
   // If we're in C++, compute the base subobject type.
   llvm::StructType *BaseTy = 0;
   if (isa<CXXRecordDecl>(D) && !D->isUnion() && !D->hasAttr<FinalAttr>()) {
@@ -646,6 +644,11 @@ CGRecordLayout *CodeGenTypes::ComputeRec
     }
   }
 
+  // Fill in the struct *after* computing the base type.  Filling in the body
+  // signifies that the type is no longer opaque and record layout is complete,
+  // but we may need to recursively layout D while laying D out as a base type.
+  Ty->setBody(Builder.FieldTypes, Builder.Packed);
+
   CGRecordLayout *RL =
     new CGRecordLayout(Ty, BaseTy, Builder.IsZeroInitializable,
                         Builder.IsZeroInitializableAsBase);

Added: cfe/trunk/test/CodeGenCXX/pr18962.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/pr18962.cpp?rev=202320&view=auto
==============================================================================
--- cfe/trunk/test/CodeGenCXX/pr18962.cpp (added)
+++ cfe/trunk/test/CodeGenCXX/pr18962.cpp Wed Feb 26 18:03:39 2014
@@ -0,0 +1,32 @@
+// RUN: %clang_cc1 -triple %itanium_abi_triple %s -emit-llvm -o - | FileCheck %s
+
+class A {
+  // append has to have the same prototype as fn1 to tickle the bug.
+  void (*append)(A *);
+};
+
+class B {};
+class D;
+
+// C has to be non-C++98 POD with available tail padding, making the LLVM base
+// type differ from the complete LLVM type.
+class C {
+  // This member creates a circular LLVM type reference to %class.D.
+  D *m_group;
+  B changeListeners;
+};
+class D : C {};
+
+void fn1(A *p1) {
+}
+
+void
+fn2(C *) {
+}
+
+// We end up using an opaque type for 'append' to avoid circular references.
+// CHECK: %class.A = type { {}* }
+// CHECK: %class.C = type { %class.D*, %class.B }
+// CHECK: %class.D = type { %class.C.base, [3 x i8] }
+// CHECK: %class.C.base = type <{ %class.D*, %class.B }>
+// CHECK: %class.B = type { i8 }





More information about the cfe-commits mailing list