TypeCache[TyPtr] = Res;
}
+static bool hasExplicitMemberDefinition(CXXRecordDecl::method_iterator I,
+ CXXRecordDecl::method_iterator End) {
+ for (; I != End; ++I)
+ if (FunctionDecl *Tmpl = I->getInstantiatedFromMemberFunction())
+ if (!Tmpl->isImplicit() && Tmpl->hasBody())
+ return true;
+ return false;
+}
+
+static bool shouldOmitDefinition(CodeGenOptions::DebugInfoKind DebugKind,
+ const RecordDecl *RD,
+ const LangOptions &LangOpts) {
+ if (DebugKind > CodeGenOptions::LimitedDebugInfo)
+ return false;
+
+ if (!LangOpts.CPlusPlus)
+ return false;
+
+ if (!RD->isCompleteDefinitionRequired())
+ return true;
+
+ const CXXRecordDecl *CXXDecl = dyn_cast<CXXRecordDecl>(RD);
+
+ if (!CXXDecl)
+ return false;
+
+ if (CXXDecl->hasDefinition() && CXXDecl->isDynamicClass())
+ return true;
+
+ TemplateSpecializationKind Spec = TSK_Undeclared;
+ if (const ClassTemplateSpecializationDecl *SD =
+ dyn_cast<ClassTemplateSpecializationDecl>(RD))
+ Spec = SD->getSpecializationKind();
+
+ if (Spec == TSK_ExplicitInstantiationDeclaration &&
+ hasExplicitMemberDefinition(CXXDecl->method_begin(),
+ CXXDecl->method_end()))
+ return true;
+
+ return false;
+}
+
/// CreateType - get structure or union type.
llvm::DIType CGDebugInfo::CreateType(const RecordType *Ty) {
RecordDecl *RD = Ty->getDecl();
- const CXXRecordDecl *CXXDecl = dyn_cast<CXXRecordDecl>(RD);
- // Always emit declarations for types that aren't required to be complete when
- // in limit-debug-info mode. If the type is later found to be required to be
- // complete this declaration will be upgraded to a definition by
- // `completeRequiredType`.
- // If the type is dynamic, only emit the definition in TUs that require class
- // data. This is handled by `completeClassData`.
llvm::DICompositeType T(getTypeOrNull(QualType(Ty, 0)));
- // If we've already emitted the type, just use that, even if it's only a
- // declaration. The completeType, completeRequiredType, and completeClassData
- // callbacks will handle promoting the declaration to a definition.
- if (T ||
- // Under -fno-standalone-debug:
- (DebugKind <= CodeGenOptions::LimitedDebugInfo &&
- // Emit only a forward declaration unless the type is required.
- ((!RD->isCompleteDefinitionRequired() && CGM.getLangOpts().CPlusPlus) ||
- // If the class is dynamic, only emit a declaration. A definition will
- // be emitted whenever the vtable is emitted.
- (CXXDecl && CXXDecl->hasDefinition() && CXXDecl->isDynamicClass())))) {
+ if (T || shouldOmitDefinition(DebugKind, RD, CGM.getLangOpts())) {
if (!T)
T = getOrCreateRecordFwdDecl(
Ty, getContextDescriptor(cast<Decl>(RD->getDeclContext())));
return llvm::DIType(cast_or_null<llvm::MDNode>(V));
}
+void CGDebugInfo::completeTemplateDefinition(
+ const ClassTemplateSpecializationDecl &SD) {
+ completeClassData(&SD);
+ // In case this type has no member function definitions being emitted, ensure
+ // it is retained
+ RetainedTypes.push_back(CGM.getContext().getRecordType(&SD).getAsOpaquePtr());
+}
+
/// getCachedInterfaceTypeOrNull - Get the type from the interface
/// cache, unless it needs to regenerated. Otherwise return null.
llvm::Value *CGDebugInfo::getCachedInterfaceTypeOrNull(QualType Ty) {
--- /dev/null
+// RUN: %clang_cc1 -S -emit-llvm -g %s -o - | FileCheck %s
+
+template <typename T>
+struct a {
+};
+extern template class a<int>;
+// CHECK-NOT: ; [ DW_TAG_structure_type ] [a<int>]
+
+template <typename T>
+struct b {
+};
+extern template class b<int>;
+b<int> bi;
+// CHECK: ; [ DW_TAG_structure_type ] [b<int>] {{.*}} [def]
+
+template <typename T>
+struct c {
+ void f() {}
+};
+extern template class c<int>;
+c<int> ci;
+// CHECK: ; [ DW_TAG_structure_type ] [c<int>] {{.*}} [decl]
+
+template <typename T>
+struct d {
+ void f();
+};
+extern template class d<int>;
+d<int> di;
+// CHECK: ; [ DW_TAG_structure_type ] [d<int>] {{.*}} [def]
+
+template <typename T>
+struct e {
+ void f();
+};
+template <typename T>
+void e<T>::f() {
+}
+extern template class e<int>;
+e<int> ei;
+// CHECK: ; [ DW_TAG_structure_type ] [e<int>] {{.*}} [decl]
+
+template <typename T>
+struct f {
+ void g();
+};
+extern template class f<int>;
+template <typename T>
+void f<T>::g() {
+}
+f<int> fi;
+// Is this right? We don't seem to emit a def for 'f<int>::g' (even if it is
+// called in this translation unit) so I guess if we're relying on its
+// definition to be wherever the explicit instantiation definition is, we can do
+// the same for the debug info.
+// CHECK: ; [ DW_TAG_structure_type ] [f<int>] {{.*}} [decl]
+
+template <typename T>
+struct g {
+ void f();
+};
+template <>
+void g<int>::f();
+extern template class g<int>;
+g<int> gi;
+// CHECK: ; [ DW_TAG_structure_type ] [g<int>] {{.*}} [def]
+
+template <typename T>
+struct h {
+};
+template class h<int>;
+// CHECK: ; [ DW_TAG_structure_type ] [h<int>] {{.*}} [def]