[cfe-commits][patch] Strange LLVM IR result on recursive type

Hi all,

I found a strange result on clang-3.1 when recursive type was converted. A example is as following.
C language source code:
struct foo1 {
  struct foo2* a;
  struct foo3* b;
};
struct foo2 {
  void (*func1)(struct foo1*);
};
struct foo3 {
  void (*func1)(struct foo1*);
};
struct foo2 e;

Converted result to llvm IR:
%struct.foo2 = type { void (%struct.foo1*)* }
%struct.foo1 = type { %struct.foo2*, %struct.foo3* }
%struct.foo3 = type { {}* }
@e = common global %struct.foo2 zeroinitializer, align 4

struct.foo3 type has "{}*". The reason of strange result is that clang generates struct type for function type with parameter of cycled type as following.
File: clang/lib/CodeGen/CodeGenTypes.cpp
463 // While we're converting the argument types for a function, we don't want
464 // to recursively convert any pointed-to structs. Converting directly-used
465 // structs is ok though.
466 if (!RecordsBeingLaidOut.insert(Ty)) {
467 ResultType = llvm::StructType::get(getLLVMContext());
468
469 SkippedLayout = true;
470 break;
471 }

I think that cycle of types should be cut to translate cycled clang types into llvm IR so clang generates struct type as type holder. Is it right? What do you think about this?

I made a simple patch for clang-3.1 to fix this problem. Resolved result is as following.
Resolved result:
%struct.foo2 = type { void (%struct.foo1*)* }
%struct.foo1 = type { %struct.foo2*, %struct.foo3* }
%struct.foo3 = type { void (%struct.foo1*)* }
@e = common global %struct.foo2 zeroinitializer, align 4

Please review this patch.

Thanks,
Jin-Gu Kang

RecursiveType.patch (2.82 KB)