diff options
| -rw-r--r-- | clang/lib/CodeGen/CodeGenTypes.cpp | 54 | ||||
| -rw-r--r-- | clang/lib/CodeGen/CodeGenTypes.h | 8 | ||||
| -rw-r--r-- | clang/test/CodeGen/types.c | 13 | 
3 files changed, 61 insertions, 14 deletions
diff --git a/clang/lib/CodeGen/CodeGenTypes.cpp b/clang/lib/CodeGen/CodeGenTypes.cpp index 4e8d46c7dd5..d594cbc7355 100644 --- a/clang/lib/CodeGen/CodeGenTypes.cpp +++ b/clang/lib/CodeGen/CodeGenTypes.cpp @@ -92,6 +92,27 @@ CodeGenTypes::~CodeGenTypes() {  /// ConvertType - Convert the specified type to its LLVM form.  const llvm::Type *CodeGenTypes::ConvertType(QualType T) { +  llvm::PATypeHolder Result = ConvertTypeRecursive(T); + +  // Any pointers that were converted defered evaluation of their pointee type, +  // creating an opaque type instead.  This is in order to avoid problems with +  // circular types.  Loop through all these defered pointees, if any, and +  // resolve them now. +  while (!PointersToResolve.empty()) { +    std::pair<const PointerLikeType *, llvm::OpaqueType*> P = +      PointersToResolve.back(); +    PointersToResolve.pop_back(); +    // We can handle bare pointers here because we know that the only pointers +    // to the Opaque type are P.second and from other types.  Refining the +    // opqaue type away will invalidate P.second, but we don't mind :). +    const llvm::Type *NT = ConvertTypeRecursive(P.first->getPointeeType()); +    P.second->refineAbstractTypeTo(NT); +  } + +  return Result; +} + +const llvm::Type *CodeGenTypes::ConvertTypeRecursive(QualType T) {    // See if type is already cached.    llvm::DenseMap<Type *, llvm::PATypeHolder>::iterator      I = TypeCache.find(T.getCanonicalType().getTypePtr()); @@ -203,13 +224,16 @@ const llvm::Type *CodeGenTypes::ConvertNewType(QualType T) {    }    case Type::Complex: {      const llvm::Type *EltTy =  -      ConvertType(cast<ComplexType>(Ty).getElementType()); +      ConvertTypeRecursive(cast<ComplexType>(Ty).getElementType());      return llvm::StructType::get(EltTy, EltTy, NULL);    }    case Type::Reference:    case Type::Pointer: { -    QualType ETy = cast<PointerLikeType>(Ty).getPointeeType(); -    return llvm::PointerType::get(ConvertType(ETy), ETy.getAddressSpace());  +    const PointerLikeType &PTy = cast<PointerLikeType>(Ty); +    QualType ETy = PTy.getPointeeType(); +    llvm::OpaqueType *PointeeType = llvm::OpaqueType::get(); +    PointersToResolve.push_back(std::make_pair(&PTy, PointeeType)); +    return llvm::PointerType::get(PointeeType, ETy.getAddressSpace());    }    case Type::VariableArray: { @@ -218,24 +242,24 @@ const llvm::Type *CodeGenTypes::ConvertNewType(QualType T) {             "FIXME: We only handle trivial array types so far!");      // VLAs resolve to the innermost element type; this matches      // the return of alloca, and there isn't any obviously better choice. -    return ConvertType(A.getElementType()); +    return ConvertTypeRecursive(A.getElementType());    }    case Type::IncompleteArray: {      const IncompleteArrayType &A = cast<IncompleteArrayType>(Ty);      assert(A.getIndexTypeQualifier() == 0 &&             "FIXME: We only handle trivial array types so far!");      // int X[] -> [0 x int] -    return llvm::ArrayType::get(ConvertType(A.getElementType()), 0); +    return llvm::ArrayType::get(ConvertTypeRecursive(A.getElementType()), 0);    }    case Type::ConstantArray: {      const ConstantArrayType &A = cast<ConstantArrayType>(Ty); -    const llvm::Type *EltTy = ConvertType(A.getElementType()); +    const llvm::Type *EltTy = ConvertTypeRecursive(A.getElementType());      return llvm::ArrayType::get(EltTy, A.getSize().getZExtValue());    }    case Type::OCUVector:    case Type::Vector: {      const VectorType &VT = cast<VectorType>(Ty); -    return llvm::VectorType::get(ConvertType(VT.getElementType()), +    return llvm::VectorType::get(ConvertTypeRecursive(VT.getElementType()),                                   VT.getNumElements());    }    case Type::FunctionNoProto: @@ -246,7 +270,7 @@ const llvm::Type *CodeGenTypes::ConvertNewType(QualType T) {      if (FP.getResultType()->isVoidType())        ResultType = llvm::Type::VoidTy;    // Result of function uses llvm void.      else -      ResultType = ConvertType(FP.getResultType()); +      ResultType = ConvertTypeRecursive(FP.getResultType());      // FIXME: Convert argument types.      bool isVarArg; @@ -270,7 +294,8 @@ const llvm::Type *CodeGenTypes::ConvertNewType(QualType T) {    }    case Type::ASQual: -    return ConvertType(QualType(cast<ASQualType>(Ty).getBaseType(), 0)); +    return +      ConvertTypeRecursive(QualType(cast<ASQualType>(Ty).getBaseType(), 0));    case Type::ObjCInterface: {      // Warning: Use of this is strongly discouraged.  Late binding of instance @@ -324,7 +349,7 @@ const llvm::Type *CodeGenTypes::ConvertNewType(QualType T) {  void CodeGenTypes::DecodeArgumentTypes(const FunctionTypeProto &FTP,                                          std::vector<const llvm::Type*> &ArgTys) {    for (unsigned i = 0, e = FTP.getNumArgs(); i != e; ++i) { -    const llvm::Type *Ty = ConvertType(FTP.getArgType(i)); +    const llvm::Type *Ty = ConvertTypeRecursive(FTP.getArgType(i));      if (Ty->isFirstClassType())        ArgTys.push_back(Ty);      else @@ -355,7 +380,7 @@ const llvm::Type *CodeGenTypes::ConvertTagDeclType(const TagDecl *TD) {    if (TD->getKind() == Decl::Enum) {      // Don't bother storing enums in TagDeclTypes. -    return ConvertType(cast<EnumDecl>(TD)->getIntegerType()); +    return ConvertTypeRecursive(cast<EnumDecl>(TD)->getIntegerType());    }    // This decl could well be recursive.  In this case, insert an opaque @@ -484,7 +509,7 @@ void RecordOrganizer::layoutStructFields(const ASTRecordLayout &RL) {      if (FD->isBitField())         placeBitField(FD);      else { -      const llvm::Type *Ty = CGT.ConvertType(FD->getType()); +      const llvm::Type *Ty = CGT.ConvertTypeRecursive(FD->getType());        addLLVMField(Ty);        CGT.addFieldInfo(FD, llvmFieldNo - 1);        Cursor = llvmSize; @@ -562,7 +587,8 @@ void RecordOrganizer::layoutUnionFields() {    }    std::vector<const llvm::Type*> Fields; -  const llvm::Type *Ty = CGT.ConvertType(FieldDecls[PrimaryEltNo]->getType()); +  const llvm::Type *Ty = +    CGT.ConvertTypeRecursive(FieldDecls[PrimaryEltNo]->getType());    Fields.push_back(Ty);    STy = llvm::StructType::get(Fields);  } @@ -580,7 +606,7 @@ void RecordOrganizer::placeBitField(const FieldDecl *FD) {    assert (isBitField  && "Invalid BitField size expression");    uint64_t BitFieldSize =  FieldSize.getZExtValue(); -  const llvm::Type *Ty = CGT.ConvertType(FD->getType()); +  const llvm::Type *Ty = CGT.ConvertTypeRecursive(FD->getType());    uint64_t TySize = CGT.getTargetData().getABITypeSizeInBits(Ty);    unsigned Idx = Cursor / TySize; diff --git a/clang/lib/CodeGen/CodeGenTypes.h b/clang/lib/CodeGen/CodeGenTypes.h index f1a680c46f6..9bfd6bdb3a4 100644 --- a/clang/lib/CodeGen/CodeGenTypes.h +++ b/clang/lib/CodeGen/CodeGenTypes.h @@ -21,6 +21,7 @@  namespace llvm {    class Module;    class Type; +  class OpaqueType;    class PATypeHolder;    class TargetData;  } @@ -30,6 +31,8 @@ namespace clang {    class TagDecl;    class TargetInfo;    class QualType; +  class PointerType; +  class PointerLikeType;    class Type;    class FunctionTypeProto;    class FieldDecl; @@ -77,6 +80,10 @@ class CodeGenTypes {    llvm::Module& TheModule;    const llvm::TargetData& TheTargetData; + +  llvm::SmallVector<std::pair<const PointerLikeType *, +                              llvm::OpaqueType *>, 8>  PointersToResolve; +    llvm::DenseMap<const TagDecl*, llvm::PATypeHolder> TagDeclTypes;    /// CGRecordLayouts - This maps llvm struct type with corresponding  @@ -124,6 +131,7 @@ public:    /// ConvertType - Convert type T into a llvm::Type.      const llvm::Type *ConvertType(QualType T); +  const llvm::Type *ConvertTypeRecursive(QualType T);    /// ConvertTypeForMem - Convert type T into a llvm::Type.  This differs from    /// ConvertType in that it is used to convert to the memory representation for diff --git a/clang/test/CodeGen/types.c b/clang/test/CodeGen/types.c index 2bbcec106a7..c542a758b8d 100644 --- a/clang/test/CodeGen/types.c +++ b/clang/test/CodeGen/types.c @@ -19,3 +19,16 @@ struct MpegEncContext;  typedef struct MpegEncContext {int pb;} MpegEncContext;  static void test2(void) {MpegEncContext s; s.pb;} + +struct Village; + +struct List { +  struct Village *v; +}; + +struct Village { +  struct List returned; +}; + +void test3(struct List a) { +}  | 

