[DebugInfo] Add an attribute to force type info to be emitted for types that are required to be complete.
This was motivated by the fact that constructor type homing (debug info optimization that we want to turn on by default) drops some libc++ types, so an attribute would allow us to override constructor homing and emit them anyway. I'm currently looking into the particular libc++ issue, but even if we do fix that, this issue might come up elsewhere and it might be nice to have this. As I've implemented it now, the attribute isn't specific to the constructor homing optimization and overrides all of the debug info optimizations. Open to discussion about naming, specifics on what the attribute should do, etc. Differential Revision: https://reviews.llvm.org/D97411
This commit is contained in:
parent
579b8fc2e9
commit
d7cd208f08
|
@ -1673,6 +1673,14 @@ def NoDebug : InheritableAttr {
|
|||
let Documentation = [NoDebugDocs];
|
||||
}
|
||||
|
||||
def StandaloneDebug : InheritableAttr {
|
||||
let Spellings = [Clang<"standalone_debug", /*allowInC =*/0>];
|
||||
let Subjects = SubjectList<[CXXRecord]>;
|
||||
let Documentation = [StandaloneDebugDocs];
|
||||
let SimpleHandler = 1;
|
||||
let LangOpts = [CPlusPlus];
|
||||
}
|
||||
|
||||
def NoDuplicate : InheritableAttr {
|
||||
let Spellings = [Clang<"noduplicate">];
|
||||
let Subjects = SubjectList<[Function]>;
|
||||
|
|
|
@ -1102,6 +1102,16 @@ data member, or for a typedef or using declaration.
|
|||
}];
|
||||
}
|
||||
|
||||
def StandaloneDebugDocs : Documentation {
|
||||
let Category = DocCatVariable;
|
||||
let Content = [{
|
||||
The ``standalone_debug`` attribute causes debug info to be emitted for a record
|
||||
type regardless of the debug info optimizations that are enabled with
|
||||
-fno-standalone-debug. This attribute only has an effect when debug info
|
||||
optimizations are enabled (e.g. with -fno-standalone-debug), and is C++-only.
|
||||
}];
|
||||
}
|
||||
|
||||
def NoDuplicateDocs : Documentation {
|
||||
let Category = DocCatFunction;
|
||||
let Content = [{
|
||||
|
|
|
@ -2385,7 +2385,8 @@ static bool shouldOmitDefinition(codegenoptions::DebugInfoKind DebugKind,
|
|||
if (DebugKind == codegenoptions::DebugLineTablesOnly)
|
||||
return true;
|
||||
|
||||
if (DebugKind > codegenoptions::LimitedDebugInfo)
|
||||
if (DebugKind > codegenoptions::LimitedDebugInfo ||
|
||||
RD->hasAttr<StandaloneDebugAttr>())
|
||||
return false;
|
||||
|
||||
if (!LangOpts.CPlusPlus)
|
||||
|
|
|
@ -0,0 +1,54 @@
|
|||
// RUN: %clang_cc1 -DSETATTR=0 -triple x86_64-unknown-linux-gnu -emit-llvm -debug-info-kind=constructor %s -o - | FileCheck %s --check-prefix=DEBUG
|
||||
// RUN: %clang_cc1 -DSETATTR=1 -triple x86_64-unknown-linux-gnu -emit-llvm -debug-info-kind=constructor %s -o - | FileCheck %s --check-prefix=WITHATTR
|
||||
// Use -debug-info-kind=constructor because it includes all the optimizations.
|
||||
|
||||
#if SETATTR
|
||||
#define STANDALONEDEBUGATTR __attribute__((standalone_debug))
|
||||
#else
|
||||
#define STANDALONEDEBUGATTR
|
||||
#endif
|
||||
|
||||
struct STANDALONEDEBUGATTR StructWithConstructor {
|
||||
StructWithConstructor() {}
|
||||
};
|
||||
void f(StructWithConstructor s) {}
|
||||
// DEBUG: !DICompositeType({{.*}}name: "StructWithConstructor"
|
||||
// DEBUG-SAME: flags: {{.*}}DIFlagFwdDecl
|
||||
// WITHATTR: !DICompositeType({{.*}}name: "StructWithConstructor"
|
||||
// WITHATTR-NOT: DIFlagFwdDecl
|
||||
|
||||
union STANDALONEDEBUGATTR UnionWithConstructor {
|
||||
UnionWithConstructor() {}
|
||||
};
|
||||
void f(UnionWithConstructor u) {}
|
||||
// DEBUG: !DICompositeType({{.*}}name: "UnionWithConstructor"
|
||||
// DEBUG-SAME: flags: {{.*}}DIFlagFwdDecl
|
||||
// WITHATTR: !DICompositeType({{.*}}name: "UnionWithConstructor"
|
||||
// WITHATTR-NOT: DIFlagFwdDecl
|
||||
|
||||
template <typename T> struct ExternTemplate {
|
||||
ExternTemplate() {}
|
||||
T x;
|
||||
};
|
||||
extern template struct STANDALONEDEBUGATTR ExternTemplate<int>;
|
||||
void f(ExternTemplate<int> s) {}
|
||||
// DEBUG: !DICompositeType({{.*}}name: "ExternTemplate<int>"
|
||||
// DEBUG-SAME: flags: {{.*}}DIFlagFwdDecl
|
||||
// WITHATTR: !DICompositeType({{.*}}name: "ExternTemplate<int>"
|
||||
// WITHATTR-NOT: DIFlagFwdDecl
|
||||
|
||||
struct STANDALONEDEBUGATTR CompleteTypeRequired {};
|
||||
void f(CompleteTypeRequired &s) {}
|
||||
// DEBUG: !DICompositeType({{.*}}name: "CompleteTypeRequired"
|
||||
// DEBUG-SAME: flags: {{.*}}DIFlagFwdDecl
|
||||
// WITHATTR: !DICompositeType({{.*}}name: "CompleteTypeRequired"
|
||||
// WITHATTR-NOT: DIFlagFwdDecl
|
||||
|
||||
struct STANDALONEDEBUGATTR Redecl;
|
||||
struct Redecl {};
|
||||
void f(Redecl &s) {}
|
||||
// DEBUG: !DICompositeType({{.*}}name: "Redecl"
|
||||
// DEBUG-SAME: flags: {{.*}}DIFlagFwdDecl
|
||||
// WITHATTR: !DICompositeType({{.*}}name: "Redecl"
|
||||
// WITHATTR-NOT: DIFlagFwdDecl
|
||||
|
|
@ -154,6 +154,7 @@
|
|||
// CHECK-NEXT: Section (SubjectMatchRule_function, SubjectMatchRule_variable_is_global, SubjectMatchRule_objc_method, SubjectMatchRule_objc_property)
|
||||
// CHECK-NEXT: SetTypestate (SubjectMatchRule_function_is_member)
|
||||
// CHECK-NEXT: SpeculativeLoadHardening (SubjectMatchRule_function, SubjectMatchRule_objc_method)
|
||||
// CHECK-NEXT: StandaloneDebug (SubjectMatchRule_record)
|
||||
// CHECK-NEXT: SwiftAsync (SubjectMatchRule_function, SubjectMatchRule_objc_method)
|
||||
// CHECK-NEXT: SwiftAsyncError (SubjectMatchRule_function, SubjectMatchRule_objc_method)
|
||||
// CHECK-NEXT: SwiftAsyncName (SubjectMatchRule_objc_method, SubjectMatchRule_function)
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
// RUN: %clang_cc1 %s -verify -fsyntax-only
|
||||
// RUN: %clang_cc1 %s -verify -fsyntax-only -x c
|
||||
|
||||
#ifdef __cplusplus
|
||||
int a __attribute__((standalone_debug)); // expected-warning {{'standalone_debug' attribute only applies to classes}}
|
||||
|
||||
void __attribute__((standalone_debug)) b(); // expected-warning {{'standalone_debug' attribute only applies to classes}}
|
||||
|
||||
struct __attribute__((standalone_debug(1))) c {}; // expected-error {{'standalone_debug' attribute takes no arguments}}
|
||||
|
||||
#else
|
||||
// Check that attribute only works in C++.
|
||||
struct __attribute__((standalone_debug)) a {}; // expected-warning {{'standalone_debug' attribute ignored}}
|
||||
#endif
|
Loading…
Reference in New Issue