return false;
}
+/// Does a type definition exist in an imported clang module?
+static bool isDefinedInClangModule(const RecordDecl *RD) {
+ // Only definitions that where imported from an AST file come from a module.
+ if (!RD || !RD->isFromASTFile())
+ return false;
+ // Anonymous entities cannot be addressed. Treat them as not from module.
+ if (!RD->isExternallyVisible() && RD->getName().empty())
+ return false;
+ if (auto *CXXDecl = dyn_cast<CXXRecordDecl>(RD)) {
+ if (!CXXDecl->isCompleteDefinition())
+ return false;
+ auto TemplateKind = CXXDecl->getTemplateSpecializationKind();
+ if (TemplateKind != TSK_Undeclared) {
+ // This is a template, check the origin of the first member.
+ if (CXXDecl->field_begin() == CXXDecl->field_end())
+ return TemplateKind == TSK_ExplicitInstantiationDeclaration;
+ if (!CXXDecl->field_begin()->isFromASTFile())
+ return false;
+ }
+ }
+ return true;
+}
+
void CGDebugInfo::completeClassData(const RecordDecl *RD) {
if (auto *CXXRD = dyn_cast<CXXRecordDecl>(RD))
if (CXXRD->isDynamicClass() &&
llvm::GlobalValue::AvailableExternallyLinkage &&
!isClassOrMethodDLLImport(CXXRD))
return;
+
+ if (DebugTypeExtRefs && isDefinedInClangModule(RD->getDefinition()))
+ return;
+
completeClass(RD);
}
return false;
}
-/// Does a type definition exist in an imported clang module?
-static bool isDefinedInClangModule(const RecordDecl *RD) {
- // Only definitions that where imported from an AST file come from a module.
- if (!RD || !RD->isFromASTFile())
- return false;
- // Anonymous entities cannot be addressed. Treat them as not from module.
- if (!RD->isExternallyVisible() && RD->getName().empty())
- return false;
- if (auto *CXXDecl = dyn_cast<CXXRecordDecl>(RD)) {
- if (!CXXDecl->isCompleteDefinition())
- return false;
- auto TemplateKind = CXXDecl->getTemplateSpecializationKind();
- if (TemplateKind != TSK_Undeclared) {
- // This is a template, check the origin of the first member.
- if (CXXDecl->field_begin() == CXXDecl->field_end())
- return TemplateKind == TSK_ExplicitInstantiationDeclaration;
- if (!CXXDecl->field_begin()->isFromASTFile())
- return false;
- }
- }
- return true;
-}
-
static bool shouldOmitDefinition(codegenoptions::DebugInfoKind DebugKind,
bool DebugTypeExtRefs, const RecordDecl *RD,
const LangOptions &LangOpts) {
void foo() {
anon.i = GlobalStruct.i = GlobalUnion.i = GlobalEnum;
+ A a;
+ Virtual virt;
}
// CHECK: ![[CPP:.*]] = !DIFile(filename: {{.*}}ExtDebugInfo.cpp"
// CHECK-SAME: dwoId:
// CHECK-PCH: !DICompileUnit({{.*}}splitDebugFilename:
// CHECK-PCH: dwoId: 18446744073709551614
+
+// CHECK: !DICompositeType(tag: DW_TAG_class_type, name: "A",
+// CHECK-SAME: DIFlagFwdDecl, identifier: "_ZTS1A")
+
+// There is a full definition of the type available in the module.
+// CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "Virtual",
+// CHECK-SAME: DIFlagFwdDecl, identifier: "_ZTS7Virtual")
// CHECK-SAME: flags: DIFlagFwdDecl
// CHECK-SAME: identifier: "_ZTSN8DebugCXX8TemplateIfNS_6traitsIfEEEE")
-// CHECK: !DICompositeType(tag: DW_TAG_class_type, name: "FwdVirtual"
+// CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "Virtual"
// CHECK-SAME: elements:
-// CHECK-SAME: identifier: "_ZTS10FwdVirtual")
-// CHECK: !DIDerivedType(tag: DW_TAG_member, name: "_vptr$FwdVirtual"
+// CHECK-SAME: identifier: "_ZTS7Virtual")
+// CHECK: !DIDerivedType(tag: DW_TAG_member, name: "_vptr$Virtual"
// CHECK: !DICompositeType(tag: DW_TAG_union_type,
// CHECK-NOT: name:
// CHECK-SAME: name: "InAnonymousNamespace",
// CHECK-SAME: elements: !{{[0-9]+}})
+// CHECK: ![[A:.*]] = {{.*}}!DICompositeType(tag: DW_TAG_class_type, name: "A",
+// CHECK-SAME: elements:
+// CHECK-SAME: vtableHolder: ![[A]],
+// CHECK-SAME: identifier: "_ZTS1A")
+
// CHECK: ![[DERIVED:.*]] = {{.*}}!DICompositeType(tag: DW_TAG_class_type, name: "Derived",
// CHECK-SAME: identifier: "_ZTS7Derived")
// CHECK: !DICompositeType(tag: DW_TAG_class_type, name: "B", scope: ![[DERIVED]],