diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp --- a/clang/lib/CodeGen/CGDebugInfo.cpp +++ b/clang/lib/CodeGen/CGDebugInfo.cpp @@ -1031,6 +1031,10 @@ uint64_t Size = 0; uint32_t Align = 0; + const RecordDecl *D = RD->getDefinition(); + if (D && D->isCompleteDefinition()) + Size = CGM.getContext().getTypeSize(Ty); + llvm::DINode::DIFlags Flags = llvm::DINode::FlagFwdDecl; // Add flag to nontrivial forward declarations. To be consistent with MSVC, diff --git a/clang/test/CodeGenCXX/debug-info-class.cpp b/clang/test/CodeGenCXX/debug-info-class.cpp --- a/clang/test/CodeGenCXX/debug-info-class.cpp +++ b/clang/test/CodeGenCXX/debug-info-class.cpp @@ -136,7 +136,7 @@ // CHECK: [[C_DTOR]] = !DISubprogram(name: "~C" // CHECK: [[D:![0-9]+]] = !DICompositeType(tag: DW_TAG_structure_type, name: "D" -// CHECK-NOT: size: +// CHECK-SAME: size: // CHECK-SAME: DIFlagFwdDecl // CHECK-NOT: identifier: // CHECK-SAME: ){{$}} diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp --- a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp @@ -1013,8 +1013,10 @@ Tag == dwarf::DW_TAG_class_type || Tag == dwarf::DW_TAG_structure_type || Tag == dwarf::DW_TAG_union_type) { // Add size if non-zero (derived types might be zero-sized.) + // Ignore the size if it's a non-enum forward decl. // TODO: Do we care about size for enum forward declarations? - if (Size) + if (Size && + (!CTy->isForwardDecl() || Tag == dwarf::DW_TAG_enumeration_type)) addUInt(Buffer, dwarf::DW_AT_byte_size, None, Size); else if (!CTy->isForwardDecl()) // Add zero size if it is not a forward declaration. diff --git a/llvm/lib/Transforms/Scalar/SROA.cpp b/llvm/lib/Transforms/Scalar/SROA.cpp --- a/llvm/lib/Transforms/Scalar/SROA.cpp +++ b/llvm/lib/Transforms/Scalar/SROA.cpp @@ -4534,15 +4534,15 @@ // The alloca may be larger than the variable. auto VarSize = DbgDeclare->getVariable()->getSizeInBits(); - if (VarSize) { - if (Size > *VarSize) - Size = *VarSize; - if (Size == 0 || Start + Size > *VarSize) - continue; - } + assert(VarSize && + "Any variable with a location must have a type with a size"); + if (Size > *VarSize) + Size = *VarSize; + if (Size == 0 || Start + Size > *VarSize) + continue; // Avoid creating a fragment expression that covers the entire variable. - if (!VarSize || *VarSize != Size) { + if (*VarSize != Size) { if (auto E = DIExpression::createFragmentExpression(Expr, Start, Size)) FragmentExpr = *E; diff --git a/llvm/test/DebugInfo/X86/struct-fwd-decl.ll b/llvm/test/DebugInfo/X86/struct-fwd-decl.ll new file mode 100644 --- /dev/null +++ b/llvm/test/DebugInfo/X86/struct-fwd-decl.ll @@ -0,0 +1,21 @@ +; RUN: llc -O0 -mtriple=x86_64-unknown-linux %s -o %t -filetype=obj +; RUN: llvm-dwarfdump -debug-info %t | FileCheck %s +; Test that size is not emitted for class declarations in DWARF, even if it exists. + +@s = global i16 0, align 2, !dbg !0 + +!llvm.dbg.cu = !{!4} +!llvm.module.flags = !{!7} + +!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression()) +!1 = !DIGlobalVariable(name: "s", scope: null, file: !2, line: 2, type: !3, isLocal: false, isDefinition: true) +!2 = !DIFile(filename: "foo.cpp", directory: "/tmp") +!3 = !DICompositeType(tag: DW_TAG_structure_type, name: "S", file: !2, line: 1, size: 16, align: 16, flags: DIFlagFwdDecl) +!4 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !2, isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !5, retainedTypes: !5, globals: !6, imports: !5) +!5 = !{} +; CHECK: DW_TAG_structure_type +; CHECK-NEXT: DW_AT_name +; CHECK-NOT: DW_AT_byte_size +; CHECK-NEXT: DW_AT_declaration +!6 = !{!0} +!7 = !{i32 1, !"Debug Info Version", i32 3}