diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td index bc2d8ceeeb6c..5bddef1b4ef2 100644 --- a/clang/include/clang/Basic/Attr.td +++ b/clang/include/clang/Basic/Attr.td @@ -1660,6 +1660,13 @@ def NoDebug : InheritableAttr { let Documentation = [NoDebugDocs]; } +def DebugTypeInfoAsNeeded : InheritableAttr { + let Spellings = [Clang<"debug_type_info_as_needed">]; + let Subjects = SubjectList<[CXXRecord]>; + let Documentation = [Undocumented]; + let SimpleHandler = 1; +} + def NoDuplicate : InheritableAttr { let Spellings = [Clang<"noduplicate">]; let Subjects = SubjectList<[Function]>; diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp index 48b9bf049f48..ef17983b446a 100644 --- a/clang/lib/CodeGen/CGDebugInfo.cpp +++ b/clang/lib/CodeGen/CGDebugInfo.cpp @@ -2344,6 +2344,10 @@ static bool shouldOmitDefinition(codegenoptions::DebugInfoKind DebugKind, if (!CXXDecl) return false; + // Don't omit definition if marked with attribute. + if (RD->hasAttr()) + return false; + // Only emit complete debug info for a dynamic class when its vtable is // emitted. However, Microsoft debuggers don't resolve type information // across DLL boundaries, so skip this optimization if the class or any of its diff --git a/clang/test/CodeGenCXX/debug-info-emit-as-needed-attribute.cpp b/clang/test/CodeGenCXX/debug-info-emit-as-needed-attribute.cpp new file mode 100644 index 000000000000..a2f0eae314c8 --- /dev/null +++ b/clang/test/CodeGenCXX/debug-info-emit-as-needed-attribute.cpp @@ -0,0 +1,22 @@ +// RUN: %clang_cc1 -DSETATTR=0 -emit-llvm -std=c++14 -debug-info-kind=constructor %s -o - | FileCheck %s --check-prefix=DEBUG +// RUN: %clang_cc1 -DSETATTR=1 -emit-llvm -std=c++14 -debug-info-kind=constructor %s -o - | FileCheck %s --check-prefix=WITHATTR + +#if SETATTR +#define DEBUGASNEEDED __attribute__((debug_type_info_as_needed)) +#else +#define DEBUGASNEEDED +#endif + +// Struct that isn't constructed, so its full type info should be omitted with +// -debug-info-kind=constructor. +struct DEBUGASNEEDED some_struct { + some_struct() {} +}; + +void func1(some_struct s) {} +// void func2() { func1(); } +// DEBUG: !DICompositeType({{.*}}name: "some_struct" +// DEBUG-SAME: flags: {{.*}}DIFlagFwdDecl +// WITHATTR: !DICompositeType({{.*}}name: "some_struct" +// WITHATTR-NOT: DIFlagFwdDecl +