Index: llvm/tools/clang/lib/CodeGen/CGDebugInfo.h =================================================================== --- llvm/tools/clang/lib/CodeGen/CGDebugInfo.h +++ llvm/tools/clang/lib/CodeGen/CGDebugInfo.h @@ -286,6 +286,9 @@ /// \brief - Emit C++ using declaration. void EmitUsingDecl(const UsingDecl &UD); + /// EmitExplicitCastType - Emit the type explicitly casted to. + void EmitExplicitCastType(QualType Ty); + /// \brief - Emit C++ namespace alias. llvm::DIImportedEntity EmitNamespaceAlias(const NamespaceAliasDecl &NA); Index: llvm/tools/clang/lib/CodeGen/CGDebugInfo.cpp =================================================================== --- llvm/tools/clang/lib/CodeGen/CGDebugInfo.cpp +++ llvm/tools/clang/lib/CodeGen/CGDebugInfo.cpp @@ -3347,3 +3347,9 @@ DBuilder.finalize(); } + +void CGDebugInfo::EmitExplicitCastType(QualType Ty) { + llvm::DIType DieTy = getOrCreateType(Ty, getOrCreateMainFile()); + // Don't ignore in case of explicit cast where it is referenced indirectly. + DBuilder.retainType(DieTy); +} Index: llvm/tools/clang/lib/CodeGen/CGExprScalar.cpp =================================================================== --- llvm/tools/clang/lib/CodeGen/CGExprScalar.cpp +++ llvm/tools/clang/lib/CodeGen/CGExprScalar.cpp @@ -274,6 +274,13 @@ Value *VisitExplicitCastExpr(ExplicitCastExpr *E) { if (E->getType()->isVariablyModifiedType()) CGF.EmitVariablyModifiedType(E->getType()); + + CGDebugInfo *DI = CGF.getDebugInfo(); + if (DI && + CGF.CGM.getCodeGenOpts().getDebugInfo() >= + CodeGenOptions::LimitedDebugInfo) + DI->EmitExplicitCastType(E->getType()); + return VisitCastExpr(E); } Value *VisitCastExpr(CastExpr *E); Index: llvm/tools/clang/test/CodeGen/Debug-info-explicitcast.c =================================================================== --- llvm/tools/clang/test/CodeGen/Debug-info-explicitcast.c +++ llvm/tools/clang/test/CodeGen/Debug-info-explicitcast.c @@ -0,0 +1,50 @@ +// RUN: %clang_cc1 -emit-llvm -g %s -o - | FileCheck %s + +typedef struct S { int i; } *T; +#define M(p) ((T)(p)) + +void foo(void *p) { M(p)->i++; } +// CHECK: metadata !{i32 {{.*}}, metadata !{{.*}}, null, metadata !"T", i32 3, i64 0, i64 0, i64 0, i32 0, metadata !{{.*}}} ; [ DW_TAG_typedef ] [T] [line 3, size 0, align 0, offset 0] [from ] +// CHECK: metadata !{i32 {{.*}}, metadata !{{.*}}, null, metadata !"S", i32 3, i64 32, i64 32, i32 0, i32 0, null, metadata !{{.*}}, i32 0, null, null, null} ; [ DW_TAG_structure_type ] [S] [line 3, size 32, align 32, offset 0] [def] [from ] +// CHECK: metadata !{i32 {{.*}}, metadata !{{.*}}, metadata !{{.*}}, metadata !"i", i32 3, i64 32, i64 32, i64 0, i32 0, metadata !{{.*}}} ; [ DW_TAG_member ] [i] [line 3, size 32, align 32, offset 0] [from int] + +typedef struct S1 { int i; } T1; +void foo1(T1 *p) { p->i++; } + +struct S2 { + int i; +}; +void foo2(void *p) { ((struct S2 *)p)->i++; } + +struct S3 { + int i; +}; +void foo3(struct S3 *p) { p->i++; } + +union U4 { + int i; + char c; +}; +void foo4(void *p) { ((union U4 *)p)->i++; } + +typedef union U5 { + int i; + char c; +} T5; + +void foo5(void *p) { ((T5 *)p)->i++; } + +// CHECK: metadata !{i32 {{.*}}, metadata !{{.*}}, null, metadata !"S2", i32 14, i64 32, i64 32, i32 0, i32 0, null, metadata !{{.*}}, i32 0, null, null, null} ; [ DW_TAG_structure_type ] [S2] [line 14, size 32, align 32, offset 0] [def] [from ] +// CHECK: metadata !{i32 {{.*}}, metadata !{{.*}}, metadata !{{.*}}, metadata !"i", i32 15, i64 32, i64 32, i64 0, i32 0, metadata !{{.*}}} ; [ DW_TAG_member ] [i] [line 15, size 32, align 32, offset 0] [from int] +// CHECK: metadata !{i32 {{.*}}, metadata !{{.*}}, null, metadata !"U4", i32 24, i64 32, i64 32, i64 0, i32 0, null, metadata !{{.*}}, i32 0, null, null, null} ; [ DW_TAG_union_type ] [U4] [line 24, size 32, align 32, offset 0] [def] [from ] +// CHECK: metadata !{i32 {{.*}}, metadata !{{.*}}, metadata !{{.*}}, metadata !"i", i32 25, i64 32, i64 32, i64 0, i32 0, metadata !{{.*}}} ; [ DW_TAG_member ] [i] [line 25, size 32, align 32, offset 0] [from int] +// CHECK: metadata !{i32 {{.*}}, metadata !{{.*}}, metadata !{{.*}}, metadata !"c", i32 26, i64 8, i64 8, i64 0, i32 0, metadata !{{.*}}} ; [ DW_TAG_member ] [c] [line 26, size 8, align 8, offset 0] [from char] +// CHECK: metadata !{i32 {{.*}}, metadata !{{.*}}, null, metadata !"T5", i32 33, i64 0, i64 0, i64 0, i32 0, metadata !{{.*}}} ; [ DW_TAG_typedef ] [T5] [line 33, size 0, align 0, offset 0] [from U5] +// CHECK: metadata !{i32 {{.*}}, metadata !{{.*}}, null, metadata !"U5", i32 30, i64 32, i64 32, i64 0, i32 0, null, metadata !{{.*}}, i32 0, null, null, null} ; [ DW_TAG_union_type ] [U5] [line 30, size 32, align 32, offset 0] [def] [from ] +// CHECK: metadata !{i32 {{.*}}, metadata !{{.*}}, metadata !{{.*}}, metadata !"i", i32 31, i64 32, i64 32, i64 0, i32 0, metadata !{{.*}}} ; [ DW_TAG_member ] [i] [line 31, size 32, align 32, offset 0] [from int] +// CHECK: metadata !{i32 {{.*}}, metadata !{{.*}}, metadata !{{.*}}, metadata !"c", i32 32, i64 8, i64 8, i64 0, i32 0, metadata !{{.*}}} ; [ DW_TAG_member ] [c] [line 32, size 8, align 8, offset 0] [from char] +// CHECK: metadata !{i32 {{.*}}, metadata !{{.*}}, null, metadata !"T1", i32 11, i64 0, i64 0, i64 0, i32 0, metadata !{{.*}}} ; [ DW_TAG_typedef ] [T1] [line 11, size 0, align 0, offset 0] [from S1] +// CHECK: metadata !{i32 {{.*}}, metadata !{{.*}}, null, metadata !"S1", i32 11, i64 32, i64 32, i32 0, i32 0, null, metadata !{{.*}}, i32 0, null, null, null} ; [ DW_TAG_structure_type ] [S1] [line 11, size 32, align 32, offset 0] [def] [from ] +// CHECK: metadata !{i32 {{.*}}, metadata !{{.*}}, metadata !{{.*}}, metadata !"i", i32 11, i64 32, i64 32, i64 0, i32 0, metadata !{{.*}}} ; [ DW_TAG_member ] [i] [line 11, size 32, align 32, offset 0] [from int] +// CHECK: metadata !{i32 {{.*}}, metadata !{{.*}}, null, metadata !"S3", i32 19, i64 32, i64 32, i32 0, i32 0, null, metadata !{{.*}}, i32 0, null, null, null} ; [ DW_TAG_structure_type ] [S3] [line 19, size 32, align 32, offset 0] [def] [from ] +// CHECK: metadata !{i32 {{.*}}, metadata !{{.*}}, metadata !{{.*}}, metadata !"i", i32 20, i64 32, i64 32, i64 0, i32 0, metadata !{{.*}}} ; [ DW_TAG_member ] [i] [line 20, size 32, align 32, offset 0] [from int]