From: Devang Patel Date: Fri, 21 Dec 2007 19:35:28 +0000 (+0000) Subject: Convert opaque type when struct definition is seen. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=3c40085b373d8e6e4523812e06f73a0cb9d5142c;p=clang Convert opaque type when struct definition is seen. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@45287 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/CodeGen/CodeGenTypes.cpp b/CodeGen/CodeGenTypes.cpp index 6fa0c2a746..97519c3428 100644 --- a/CodeGen/CodeGenTypes.cpp +++ b/CodeGen/CodeGenTypes.cpp @@ -114,12 +114,33 @@ CodeGenTypes::~CodeGenTypes() { CGRecordLayouts.clear(); } +/// isOpaqueTypeDefinition - Return true if LT is a llvm::OpaqueType +/// and T is tag definition. This helper routine does not check +/// relationship between T and LT. +static bool isOpaqueTypeDefinition(QualType T, llvm::Type *LT) { + + if (!isa(LT)) + return false; + + const clang::Type &Ty = *T.getCanonicalType(); + if (Ty.getTypeClass() == Type::Tagged) { + const TagType &TT = cast(Ty); + const TagDecl *TD = TT.getDecl(); + if (TD->isDefinition()) + return true; + } + + return false; +} + /// ConvertType - Convert the specified type to its LLVM form. const llvm::Type *CodeGenTypes::ConvertType(QualType T) { // See if type is already cached. llvm::DenseMap::iterator I = TypeHolderMap.find(T.getTypePtr()); - if (I != TypeHolderMap.end()) + // If type is found in map and this is not a definition for a opaque + // place holder type then use it. Otherwise convert type T. + if (I != TypeHolderMap.end() && !isOpaqueTypeDefinition(T, I->second.get())) return I->second.get(); const llvm::Type *ResultType = ConvertNewType(T); @@ -261,7 +282,9 @@ const llvm::Type *CodeGenTypes::ConvertNewType(QualType T) { const TagDecl *TD = TT.getDecl(); llvm::Type *&ResultType = TagDeclTypes[TD]; - if (ResultType) + // If corresponding llvm type is not a opaque struct type + // then use it. + if (ResultType && !isOpaqueTypeDefinition(T, ResultType)) return ResultType; if (!TD->isDefinition()) { @@ -278,14 +301,19 @@ const llvm::Type *CodeGenTypes::ConvertNewType(QualType T) { if (OpaqueI != RecordTypesToResolve.end()) return OpaqueI->second; - // Create new OpaqueType now for later use. - // FIXME: This creates a lot of opaque types, most of them are not - // needed. Reevaluate this when performance analyis finds tons of - // opaque types. - llvm::OpaqueType *OpaqueTy = llvm::OpaqueType::get(); + llvm::OpaqueType *OpaqueTy = NULL; + if (ResultType) + OpaqueTy = dyn_cast(ResultType); + if (!OpaqueTy) { + // Create new OpaqueType now for later use. + // FIXME: This creates a lot of opaque types, most of them are not + // needed. Reevaluate this when performance analyis finds tons of + // opaque types. + OpaqueTy = llvm::OpaqueType::get(); + TypeHolderMap.insert(std::make_pair(T.getTypePtr(), + llvm::PATypeHolder(OpaqueTy))); + } RecordTypesToResolve[RD] = OpaqueTy; - TypeHolderMap.insert(std::make_pair(T.getTypePtr(), - llvm::PATypeHolder(OpaqueTy))); // Layout fields. RecordOrganizer RO(*this); diff --git a/test/CodeGen/OpaqueStruct.c b/test/CodeGen/OpaqueStruct.c new file mode 100644 index 0000000000..ecf81fa830 --- /dev/null +++ b/test/CodeGen/OpaqueStruct.c @@ -0,0 +1,12 @@ +// RUN: clang %s -emit-llvm +typedef struct a b; + +b* x; + +struct a { + b* p; +}; + +void f() { + b* z = x->p; +}