From: Devang Patel Date: Tue, 23 Oct 2007 23:26:46 +0000 (+0000) Subject: Handle nested structs. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=b1e3989731b69e692f9fa2ad080406850c772b40;p=clang Handle nested structs. 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 --- diff --git a/CodeGen/CodeGenTypes.cpp b/CodeGen/CodeGenTypes.cpp index 35ed348a7b..626ebf96a8 100644 --- a/CodeGen/CodeGenTypes.cpp +++ b/CodeGen/CodeGenTypes.cpp @@ -167,13 +167,36 @@ const llvm::Type *CodeGenTypes::ConvertType(QualType T) { return ConvertType(cast(TD)->getIntegerType()); } else if (TD->getKind() == Decl::Struct) { const RecordDecl *RD = cast(TD); + + // If this is nested record and this RecordDecl is already under + // process then return associated OpaqueType for now. + llvm::DenseMap::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(TD); diff --git a/CodeGen/CodeGenTypes.h b/CodeGen/CodeGenTypes.h index 998175537b..f149fb801d 100644 --- a/CodeGen/CodeGenTypes.h +++ b/CodeGen/CodeGenTypes.h @@ -16,6 +16,7 @@ #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/SmallPtrSet.h" #include 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 FieldInfo; + /// RecordTypesToResolve - This keeps track of record types that are not + /// yet incomplete. One llvm::OpaqueType is associated with each incomplete + /// record. + llvm::DenseMap RecordTypesToResolve; + public: CodeGenTypes(ASTContext &Ctx, llvm::Module &M); ~CodeGenTypes(); diff --git a/test/CodeGen/struct.c b/test/CodeGen/struct.c index a3753d314a..cc6f0aaeeb 100644 --- a/test/CodeGen/struct.c +++ b/test/CodeGen/struct.c @@ -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; } +