dblaikie added inline comments.

================
Comment at: clang/lib/CodeGen/CGDecl.cpp:103-118
+  case Decl::CXXRecord: // struct/union/class X; [C++]
+    if (CGDebugInfo *DI = getDebugInfo())
+      if (CGM.getCodeGenOpts().hasMaybeUnusedDebugInfo() &&
+          cast<CXXRecordDecl>(D).hasDefinition())
+        DI->completeUnusedClass(cast<CXXRecordDecl>(D));
+    return;
   case Decl::Record:    // struct/union/class X;
----------------
nickdesaulniers wrote:
> nickdesaulniers wrote:
> > dblaikie wrote:
> > > All of these might be able to be collapsed together - using 
> > > "cast<TagDecl>(D).hasDefinition()" ... to have a common implementation.
> > `TagDecl` doesn't have a method `hasDefinition`.  Only `CXXRecordDecl` does.
> Also, how to get the `QualType` differs between `Decl::Enum` an 
> `Decl::Record`; `getEnumType` vs `getRecordType` respectively.
Looks like ASTContext::getTypeDeclType could be used, if it makes things 
especially tidier. But perhaps the TagDecl/hasDefinition difference is enough 
for it not to be especially significant.


================
Comment at: clang/lib/CodeGen/CGDecl.cpp:116
+    if (CGDebugInfo *DI = getDebugInfo())
+      if (cast<EnumDecl>(&D)->getDefinition())
+        DI->EmitAndRetainType(getContext().getEnumType(cast<EnumDecl>(&D)));
----------------
nickdesaulniers wrote:
> dblaikie wrote:
> > I think the right thing to call here (& the other places in this patch) is 
> > "hasDefinition" rather than "getDefinition" (this will avoid the definition 
> > being deserialized when it's not needed yet (then if we don't end up 
> > emitting the type because the flag hasn't been given, it won't be 
> > deserialized unnecessarily))
> `TagDecl` doesn't have a method `hasDefinition`.  Only `CXXRecordDecl` does.
Ah, fair enough!


================
Comment at: clang/lib/CodeGen/CodeGenModule.cpp:5385
+      if (getCodeGenOpts().hasMaybeUnusedDebugInfo() && CRD->hasDefinition())
+        DI->completeUnusedClass(*CRD);
+      else if (auto *ES = D->getASTContext().getExternalSource())
----------------
nickdesaulniers wrote:
> dblaikie wrote:
> > I think this might not work as intended if the type trips over the other 
> > class deduplication optimizations (try manually testing with a type that 
> > has an external VTable?) - and perhaps this codepath should use the 
> > EmitAndRetain functionality.
> completeUnusedClass eventually calls into CGDebugInfo::completeClass which 
> makes use of the TypeCache.  What does it mean for a class to have "an 
> external vtable?"  Can you give me an example?
Here's some sample code that uses a type in the DWARF but due to the vtable 
being external (an external vtable is one that's guaranteed to be emitted in 
some other object file - due to the key function optimization in the Itanium 
ABI - since all virtual functions must be defined if a type is ODR used, the 
compiler can make a shared assumption that the vtable will only be emitted with 
a single consistently chosen virtual function (ideally: the first non-inline 
one) and emit the vtable only in that object and nowhere else) the type is 
emitted as a declaration (when using "-fno-standalone-debug"):

```
struct t1 {
  virtual void f1();
};
t1 v1;
```


================
Comment at: clang/lib/Driver/ToolChains/Clang.cpp:3825-3828
+  if (EmitDwarf &&
+      Args.hasFlag(options::OPT_fno_eliminate_unused_debug_types,
+                   options::OPT_feliminate_unused_debug_types, false))
+    DebugInfoKind = codegenoptions::UnusedTypeInfo;
----------------
How does GCC compose this with -gmlt, for instance? I'd suspect that the 
desired behavior might be for -gmlt to override this -f flag? So maybe this 
should be predicated on "if (EmitDwarf && DebugInfoKind >= 
codegenoptions::LimitedDebugInfo && ... "?

(so if someone wants to use only -gmlt in certain parts of their build that 
doesn't get upgraded by the presence of this -f flag)


================
Comment at: clang/test/CodeGen/debug-info-unused-types.c:46-60
+struct aaaaaaaaaaaa;
+enum bbbbbbbbbbbb;
+union cccccccccccc;
+void b0(void) {
+  struct dddddddddddd;
+  enum eeeeeeeeeeee;
+  union ffffffffffff;
----------------
Maybe give these more specific names (similarly in the other test) - and/or you 
could use a pattern in the naming that might make the -NOT lines easier?

eg:

```
struct decl_struct;
enum decl_enum;
...
// NODBG-NOT: name: "decl_
```

(also best to include a bit more context in the -NOT checks, otherwise there's 
risk that a users build directory (even with these longer names) or other paths 
might accidentally fail the checks)


================
Comment at: clang/test/CodeGen/debug-info-unused-types.cpp:15-21
+// CHECK: !DICompositeType(tag: DW_TAG_enumeration_type, name: "baz"
+// CHECK: !DIEnumerator(name: "BAZ"
+// CHECK: !DICompositeType(tag: DW_TAG_enumeration_type, name: "z"
+// CHECK: !DIEnumerator(name: "Z"
+// CHECK: !DIDerivedType(tag: DW_TAG_typedef, name: "foo"
+// CHECK: !DICompositeType(tag: DW_TAG_class_type, name: "bar"
+// CHECK: !DICompositeType(tag: DW_TAG_class_type, name: "y"
----------------
Probably good to check these end up in the retained types list


================
Comment at: clang/test/CodeGen/debug-info-unused-types.cpp:23-29
+// NODBG-NOT: !DICompositeType(tag: DW_TAG_enumeration_type, name: "baz"
+// NODBG-NOT: !DIEnumerator(name: "BAZ"
+// NODBG-NOT: !DICompositeType(tag: DW_TAG_enumeration_type, name: "z"
+// NODBG-NOT: !DIEnumerator(name: "Z"
+// NODBG-NOT: !DIDerivedType(tag: DW_TAG_typedef, name: "foo"
+// NODBG-NOT: !DICompositeType(tag: DW_TAG_class_type, name: "bar"
+// NODBG-NOT: !DICompositeType(tag: DW_TAG_class_type, name: "y"
----------------
With a uniform naming scheme, perhaps this could be `// NODBG-NOT: name: 
"unused_` ?


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D80242/new/

https://reviews.llvm.org/D80242



_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to