<html><head><meta http-equiv="Content-Type" content="text/html charset=windows-1252"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;">Hey David<div><br></div><div>We had a failure with this test on our buildbots.  Seems Mac OS doesn’t generate the same debug info for ‘c’:</div><div><br></div><div><div style="margin: 0px; font-size: 11px; font-family: Menlo;">llvm/tools/clang/test/CodeGenCXX/debug-info-template-explicit-specialization.cpp:22:11: error: expected string not found in input</div><div style="margin: 0px; font-size: 11px; font-family: Menlo;">// CHECK: ; [ DW_TAG_structure_type ] [c<int>] {{.*}} [decl]</div><div style="margin: 0px; font-size: 11px; font-family: Menlo;">          ^</div><div style="margin: 0px; font-size: 11px; font-family: Menlo;"><stdin>:27:252: note: scanning from here</div><div style="margin: 0px; font-size: 11px; font-family: Menlo;">!4 = metadata !{i32 786451, metadata !5, null, metadata !"b<int>", i32 12, i64 8, i64 8, i32 0, i32 0, null, metadata !2, i32 0, null, metadata !6, metadata !"_ZTS1bIiE"} ; [ DW_TAG_structure_type ] [b<int>] [line 12, size 8, align 8, offset 0] [def] [from ]</div><div style="margin: 0px; font-size: 11px; font-family: Menlo;">                                                                                                                                                                                                                                                           ^</div><div style="margin: 0px; font-size: 11px; font-family: Menlo;"><stdin>:32:170: note: possible intended match here</div><div style="margin: 0px; font-size: 11px; font-family: Menlo;">!9 = metadata !{i32 786451, metadata !5, null, metadata !"c<int>", i32 20, i64 8, i64 8, i32 0, i32 0, null, metadata !10, i32 0, null, metadata !6, metadata !"_ZTS1cIiE"} ; [ DW_TAG_structure_type ] [c<int>] [line 20, size 8, align 8, offset 0] [def] [from ]</div><div style="margin: 0px; font-size: 11px; font-family: Menlo;"><br></div><div style="margin: 0px; font-size: 11px; font-family: Menlo;">I committed a fix in 202777.  Please take a look and see if you think its ok.</div><div style="margin: 0px; font-size: 11px; font-family: Menlo;"><br></div><div style="margin: 0px; font-size: 11px; font-family: Menlo;">Thanks,</div><div style="margin: 0px; font-size: 11px; font-family: Menlo;">Pete</div><div><div>On Mar 3, 2014, at 3:48 PM, David Blaikie <<a href="mailto:dblaikie@gmail.com">dblaikie@gmail.com</a>> wrote:</div><br class="Apple-interchange-newline"><blockquote type="cite">Author: dblaikie<br>Date: Mon Mar  3 17:48:23 2014<br>New Revision: 202769<br><br>URL: <a href="http://llvm.org/viewvc/llvm-project?rev=202769&view=rev">http://llvm.org/viewvc/llvm-project?rev=202769&view=rev</a><br>Log:<br>DebugInfo: Emit only the declaration of a class template that has an explicit instantiation declaration (& always emit such a type when there's an explicit instantiation definition)<br><br>We should only have this optimization fire when the explicit<br>instantiation definition would cause at  least one member function to be<br>emitted, thus ensuring that even a compiler not performing this<br>optimization would still emit the full type information elsewhere.<br><br>But we should also pessimize output still by always emitting the<br>definition when the explicit instantiation definition appears so that at<br>some point in the future we can depend on that information even when no<br>code had to be emitted in that TU. (this shouldn't happen very often,<br>since people mostly use explicit spec decl/defs to reduce code size -<br>but perhaps one day they could use it to explicitly reduce debug info<br>size too)<br><br>This was worth about 2% for Clang and LLVM - so not a huge win, but a<br>win. It looks really great for simple STL programs (include <string> and<br>just declare a string - 14k -> 1.4k of .dwo)<br><br>Added:<br>    cfe/trunk/test/CodeGenCXX/debug-info-template-explicit-specialization.cpp<br>Modified:<br>    cfe/trunk/lib/CodeGen/CGDebugInfo.cpp<br>    cfe/trunk/lib/CodeGen/CGDebugInfo.h<br>    cfe/trunk/lib/CodeGen/CodeGenModule.cpp<br><br>Modified: cfe/trunk/lib/CodeGen/CGDebugInfo.cpp<br>URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGDebugInfo.cpp?rev=202769&r1=202768&r2=202769&view=diff">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGDebugInfo.cpp?rev=202769&r1=202768&r2=202769&view=diff</a><br>==============================================================================<br>--- cfe/trunk/lib/CodeGen/CGDebugInfo.cpp (original)<br>+++ cfe/trunk/lib/CodeGen/CGDebugInfo.cpp Mon Mar  3 17:48:23 2014<br>@@ -1458,28 +1458,53 @@ void CGDebugInfo::completeClassData(cons<br>   TypeCache[TyPtr] = Res;<br> }<br><br>+static bool hasExplicitMemberDefinition(CXXRecordDecl::method_iterator I,<br>+                                        CXXRecordDecl::method_iterator End) {<br>+  for (; I != End; ++I)<br>+    if (FunctionDecl *Tmpl = I->getInstantiatedFromMemberFunction())<br>+      if (!Tmpl->isImplicit() && Tmpl->hasBody())<br>+        return true;<br>+  return false;<br>+}<br>+<br>+static bool shouldOmitDefinition(CodeGenOptions::DebugInfoKind DebugKind,<br>+                                 const RecordDecl *RD,<br>+                                 const LangOptions &LangOpts) {<br>+  if (DebugKind > CodeGenOptions::LimitedDebugInfo)<br>+    return false;<br>+<br>+  if (!LangOpts.CPlusPlus)<br>+    return false;<br>+<br>+  if (!RD->isCompleteDefinitionRequired())<br>+    return true;<br>+<br>+  const CXXRecordDecl *CXXDecl = dyn_cast<CXXRecordDecl>(RD);<br>+<br>+  if (!CXXDecl)<br>+    return false;<br>+<br>+  if (CXXDecl->hasDefinition() && CXXDecl->isDynamicClass())<br>+    return true;<br>+<br>+  TemplateSpecializationKind Spec = TSK_Undeclared;<br>+  if (const ClassTemplateSpecializationDecl *SD =<br>+          dyn_cast<ClassTemplateSpecializationDecl>(RD))<br>+    Spec = SD->getSpecializationKind();<br>+<br>+  if (Spec == TSK_ExplicitInstantiationDeclaration &&<br>+      hasExplicitMemberDefinition(CXXDecl->method_begin(),<br>+                                  CXXDecl->method_end()))<br>+    return true;<br>+<br>+  return false;<br>+}<br>+<br> /// CreateType - get structure or union type.<br> llvm::DIType CGDebugInfo::CreateType(const RecordType *Ty) {<br>   RecordDecl *RD = Ty->getDecl();<br>-  const CXXRecordDecl *CXXDecl = dyn_cast<CXXRecordDecl>(RD);<br>-  // Always emit declarations for types that aren't required to be complete when<br>-  // in limit-debug-info mode. If the type is later found to be required to be<br>-  // complete this declaration will be upgraded to a definition by<br>-  // `completeRequiredType`.<br>-  // If the type is dynamic, only emit the definition in TUs that require class<br>-  // data. This is handled by `completeClassData`.<br>   llvm::DICompositeType T(getTypeOrNull(QualType(Ty, 0)));<br>-  // If we've already emitted the type, just use that, even if it's only a<br>-  // declaration. The completeType, completeRequiredType, and completeClassData<br>-  // callbacks will handle promoting the declaration to a definition.<br>-  if (T ||<br>-      // Under -fno-standalone-debug:<br>-      (DebugKind <= CodeGenOptions::LimitedDebugInfo &&<br>-       // Emit only a forward declaration unless the type is required.<br>-       ((!RD->isCompleteDefinitionRequired() && CGM.getLangOpts().CPlusPlus) ||<br>-        // If the class is dynamic, only emit a declaration. A definition will<br>-        // be emitted whenever the vtable is emitted.<br>-        (CXXDecl && CXXDecl->hasDefinition() && CXXDecl->isDynamicClass())))) {<br>+  if (T || shouldOmitDefinition(DebugKind, RD, CGM.getLangOpts())) {<br>     if (!T)<br>       T = getOrCreateRecordFwdDecl(<br>           Ty, getContextDescriptor(cast<Decl>(RD->getDeclContext())));<br>@@ -2014,6 +2039,14 @@ llvm::DIType CGDebugInfo::getCompletedTy<br>   return llvm::DIType(cast_or_null<llvm::MDNode>(V));<br> }<br><br>+void CGDebugInfo::completeTemplateDefinition(<br>+    const ClassTemplateSpecializationDecl &SD) {<br>+  completeClassData(&SD);<br>+  // In case this type has no member function definitions being emitted, ensure<br>+  // it is retained<br>+  RetainedTypes.push_back(CGM.getContext().getRecordType(&SD).getAsOpaquePtr());<br>+}<br>+<br> /// getCachedInterfaceTypeOrNull - Get the type from the interface<br> /// cache, unless it needs to regenerated. Otherwise return null.<br> llvm::Value *CGDebugInfo::getCachedInterfaceTypeOrNull(QualType Ty) {<br><br>Modified: cfe/trunk/lib/CodeGen/CGDebugInfo.h<br>URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGDebugInfo.h?rev=202769&r1=202768&r2=202769&view=diff">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGDebugInfo.h?rev=202769&r1=202768&r2=202769&view=diff</a><br>==============================================================================<br>--- cfe/trunk/lib/CodeGen/CGDebugInfo.h (original)<br>+++ cfe/trunk/lib/CodeGen/CGDebugInfo.h Mon Mar  3 17:48:23 2014<br>@@ -288,6 +288,8 @@ public:<br>   void completeRequiredType(const RecordDecl *RD);<br>   void completeClassData(const RecordDecl *RD);<br><br>+  void completeTemplateDefinition(const ClassTemplateSpecializationDecl &SD);<br>+<br> private:<br>   /// EmitDeclare - Emit call to llvm.dbg.declare for a variable declaration.<br>   void EmitDeclare(const VarDecl *decl, unsigned Tag, llvm::Value *AI,<br><br>Modified: cfe/trunk/lib/CodeGen/CodeGenModule.cpp<br>URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenModule.cpp?rev=202769&r1=202768&r2=202769&view=diff">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenModule.cpp?rev=202769&r1=202768&r2=202769&view=diff</a><br>==============================================================================<br>--- cfe/trunk/lib/CodeGen/CodeGenModule.cpp (original)<br>+++ cfe/trunk/lib/CodeGen/CodeGenModule.cpp Mon Mar  3 17:48:23 2014<br>@@ -3000,7 +3000,15 @@ void CodeGenModule::EmitTopLevelDecl(Dec<br><br>     ImportedModules.insert(Import->getImportedModule());<br>     break;<br>- }<br>+  }<br>+<br>+  case Decl::ClassTemplateSpecialization: {<br>+    const ClassTemplateSpecializationDecl *Spec =<br>+        cast<ClassTemplateSpecializationDecl>(D);<br>+    if (DebugInfo &&<br>+        Spec->getSpecializationKind() == TSK_ExplicitInstantiationDefinition)<br>+      DebugInfo->completeTemplateDefinition(*Spec);<br>+  }<br><br>   default:<br>     // Make sure we handled everything we should, every other kind is a<br><br>Added: cfe/trunk/test/CodeGenCXX/debug-info-template-explicit-specialization.cpp<br>URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/debug-info-template-explicit-specialization.cpp?rev=202769&view=auto">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/debug-info-template-explicit-specialization.cpp?rev=202769&view=auto</a><br>==============================================================================<br>--- cfe/trunk/test/CodeGenCXX/debug-info-template-explicit-specialization.cpp (added)<br>+++ cfe/trunk/test/CodeGenCXX/debug-info-template-explicit-specialization.cpp Mon Mar  3 17:48:23 2014<br>@@ -0,0 +1,72 @@<br>+// RUN: %clang_cc1 -S -emit-llvm -g %s -o - | FileCheck %s<br>+<br>+template <typename T><br>+struct a {<br>+};<br>+extern template class a<int>;<br>+// CHECK-NOT: ; [ DW_TAG_structure_type ] [a<int>]<br>+<br>+template <typename T><br>+struct b {<br>+};<br>+extern template class b<int>;<br>+b<int> bi;<br>+// CHECK: ; [ DW_TAG_structure_type ] [b<int>] {{.*}} [def]<br>+<br>+template <typename T><br>+struct c {<br>+  void f() {}<br>+};<br>+extern template class c<int>;<br>+c<int> ci;<br>+// CHECK: ; [ DW_TAG_structure_type ] [c<int>] {{.*}} [decl]<br>+<br>+template <typename T><br>+struct d {<br>+  void f();<br>+};<br>+extern template class d<int>;<br>+d<int> di;<br>+// CHECK: ; [ DW_TAG_structure_type ] [d<int>] {{.*}} [def]<br>+<br>+template <typename T><br>+struct e {<br>+  void f();<br>+};<br>+template <typename T><br>+void e<T>::f() {<br>+}<br>+extern template class e<int>;<br>+e<int> ei;<br>+// CHECK: ; [ DW_TAG_structure_type ] [e<int>] {{.*}} [decl]<br>+<br>+template <typename T><br>+struct f {<br>+  void g();<br>+};<br>+extern template class f<int>;<br>+template <typename T><br>+void f<T>::g() {<br>+}<br>+f<int> fi;<br>+// Is this right? We don't seem to emit a def for 'f<int>::g' (even if it is<br>+// called in this translation unit) so I guess if we're relying on its<br>+// definition to be wherever the explicit instantiation definition is, we can do<br>+// the same for the debug info.<br>+// CHECK: ; [ DW_TAG_structure_type ] [f<int>] {{.*}} [decl]<br>+<br>+template <typename T><br>+struct g {<br>+  void f();<br>+};<br>+template <><br>+void g<int>::f();<br>+extern template class g<int>;<br>+g<int> gi;<br>+// CHECK: ; [ DW_TAG_structure_type ] [g<int>] {{.*}} [def]<br>+<br>+template <typename T><br>+struct h {<br>+};<br>+template class h<int>;<br>+// CHECK: ; [ DW_TAG_structure_type ] [h<int>] {{.*}} [def]<br><br><br>_______________________________________________<br>cfe-commits mailing list<br><a href="mailto:cfe-commits@cs.uiuc.edu">cfe-commits@cs.uiuc.edu</a><br>http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits<br></blockquote></div><br></div></body></html>