]> granicus.if.org Git - clang/commitdiff
Handle nested structs.
authorDevang Patel <dpatel@apple.com>
Tue, 23 Oct 2007 23:26:46 +0000 (23:26 +0000)
committerDevang Patel <dpatel@apple.com>
Tue, 23 Oct 2007 23:26:46 +0000 (23:26 +0000)
typdef struct A { int i; struct A *next; } A

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@43268 91177308-0d34-0410-b5e6-96231b3b80d8

CodeGen/CodeGenTypes.cpp
CodeGen/CodeGenTypes.h
test/CodeGen/struct.c

index 35ed348a7b2c7e6cc2cc93b785db9cd253246866..626ebf96a89fa7faf0442cb17f148d19fbb350ed 100644 (file)
@@ -167,13 +167,36 @@ const llvm::Type *CodeGenTypes::ConvertType(QualType T) {
       return ConvertType(cast<EnumDecl>(TD)->getIntegerType());
     } else if (TD->getKind() == Decl::Struct) {
       const RecordDecl *RD = cast<const RecordDecl>(TD);
+      
+      // If this is nested record and this RecordDecl is already under
+      // process then return associated OpaqueType for now.
+      llvm::DenseMap<const RecordDecl *, llvm::Type *>::iterator 
+       OpaqueI = RecordTypesToResolve.find(RD);
+      if (OpaqueI != RecordTypesToResolve.end())
+       return OpaqueI->second;
+
+      // Create new OpaqueType now for later use.
+      llvm::OpaqueType *OpaqueTy =  llvm::OpaqueType::get();
+      RecordTypesToResolve[RD] = OpaqueTy;
+
+      // Layout fields.
       RecordOrganizer *RO = new RecordOrganizer();
       for (unsigned i = 0, e = RD->getNumMembers(); i != e; ++i)
        RO->addField(RD->getMember(i));
       RO->layoutFields(*this);
+
+      // Get llvm::StructType.
       RecordLayoutInfo *RLI = new RecordLayoutInfo(RO);
       ResultType = RLI->getLLVMType();
       RecordLayouts[ResultType] = RLI;
+
+      // Refine any OpaqueType associated with this RecordDecl.
+      OpaqueTy->refineAbstractTypeTo(ResultType);
+      OpaqueI = RecordTypesToResolve.find(RD);
+      assert (OpaqueI != RecordTypesToResolve.end() 
+             && "Expected RecordDecl in RecordTypesToResolve");
+      RecordTypesToResolve.erase(OpaqueI);
+
       delete RO;
     } else if (TD->getKind() == Decl::Union) {
       const RecordDecl *RD = cast<const RecordDecl>(TD);
index 998175537b391471fb633a2615a47d6528f48594..f149fb801d1baa112cbe49b0d7f4fba75b23c525 100644 (file)
@@ -16,6 +16,7 @@
 
 #include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallPtrSet.h"
 #include <vector>
 
 namespace llvm {
@@ -29,7 +30,8 @@ namespace clang {
   class TargetInfo;
   class QualType;
   class FunctionTypeProto;
- class FieldDecl;
+  class FieldDecl;
+  class RecordDecl;
 
 namespace CodeGen {
   class CodeGenTypes;
@@ -98,6 +100,11 @@ class CodeGenTypes {
   /// field no. This info is populated by record organizer.
   llvm::DenseMap<const FieldDecl *, unsigned> FieldInfo;
 
+  /// RecordTypesToResolve - This keeps track of record types that are not 
+  /// yet incomplete. One llvm::OpaqueType is associated with each incomplete
+  /// record.
+  llvm::DenseMap<const RecordDecl *, llvm::Type *> RecordTypesToResolve;
+
 public:
   CodeGenTypes(ASTContext &Ctx, llvm::Module &M);
   ~CodeGenTypes();
index a3753d314a60ea9146303cca5be96d71b4b00753..cc6f0aaeeb16859666a3f5e9e2f1d085006a3d2f 100644 (file)
@@ -37,3 +37,21 @@ int fn3(F2 *c) {
   else
     return 0;
 }
+
+/* Nested structs */
+typedef struct NA {
+  int data;
+  struct NA *next;
+} NA;
+void f1() {  A a; }
+
+typedef struct NB {
+  int d1;
+  struct _B2 {
+    int d2;
+    struct NB *n2;
+  } B2;
+} NB;
+
+void f2() { NB b; }
+