Repository: llvm/llvm-project
File: clang/lib/CodeGen/CGDebugInfo.cpp (C++)

Code before:
    return VTablePtrType;

  ASTContext &Context = CGM.getContext();

  /* Function type */
  llvm::Metadata *STy = getOrCreateType(Context.IntTy, Unit);
  llvm::DITypeArray SElements = DBuilder.getOrCreateTypeArray(STy);
  llvm::DIType *SubTy = DBuilder.createSubroutineType(SElements);
  unsigned Size = Context.getTypeSize(Context.VoidPtrTy);
  unsigned VtblPtrAddressSpace = CGM.getTarget().getVtblPtrAddressSpace();
  std::optional<unsigned> DWARFAddressSpace =
      CGM.getTarget().getDWARFAddressSpace(VtblPtrAddressSpace);

  llvm::DIType *vtbl_ptr_type = DBuilder.createPointerType(
      SubTy, Size, 0, DWARFAddressSpace, "__vtbl_ptr_type");
  VTablePtrType = DBuilder.createPointerType(vtbl_ptr_type, Size);
  return VTablePtrType;
}

StringRef CGDebugInfo::getVTableName(const CXXRecordDecl *RD) {
  // Copy the gdb compatible name on the side and use its reference.
  return internString("_vptr$", RD->getNameAsString());
}

// Emit symbol for the debugger that points to the vtable address for
// the given class. The symbol is named as '__clang_vtable$'.
// The debugger does not need to know any details about the contents of the
// vtable as it can work this out using its knowledge of the ABI and the
// existing information in the DWARF. The type is assumed to be 'void *'.
void CGDebugInfo::emitVTableSymbol(llvm::GlobalVariable *VTable,
                                   const CXXRecordDecl *RD) {
  if (!CGM.getTarget().getCXXABI().isItaniumFamily())
    return;
  if (DebugKind <= llvm::codegenoptions::DebugLineTablesOnly)
    return;

  // On COFF platform, we shouldn't emit a reference to an external entity (i.e.
  // VTable) into debug info, which is constructed within a discardable section.
  // If that entity ends up implicitly dllimported from another DLL, the linker
  // may produce a runtime pseudo-relocation for it (BFD-ld only. LLD prohibits
  // to emit such relocation). If the debug section is stripped, the runtime
  // pseudo-relocation points to memory space outside of the module, causing an
  // access violation.
  if (CGM.getTarget().getTriple().isOSBinFormatCOFF() &&
      VTable->isDeclarationForLinker())
    return;

  ASTContext &Context = CGM.getContext();
  StringRef SymbolName = "__clang_vtable$";
  SourceLocation Loc;
  QualType VoidPtr = Context.getPointerType(Context.VoidTy);

Review comment (bug):
Nit: Could we add a brief note on why the __clang_ prefix? Something like:

```
// the given class. The symbol is named as '__clang_vtable$', using a
// reserved identifier prefix so debuggers can reliably distinguish it
// from user-defined symbols.
```

Code after:
    return VTablePtrType;

  ASTContext &Context = CGM.getContext();

  /* Function type */
  llvm::Metadata *STy = getOrCreateType(Context.IntTy, Unit);
  llvm::DITypeArray SElements = DBuilder.getOrCreateTypeArray(STy);
  llvm::DIType *SubTy = DBuilder.createSubroutineType(SElements);
  unsigned Size = Context.getTypeSize(Context.VoidPtrTy);
  unsigned VtblPtrAddressSpace = CGM.getTarget().getVtblPtrAddressSpace();
  std::optional<unsigned> DWARFAddressSpace =
      CGM.getTarget().getDWARFAddressSpace(VtblPtrAddressSpace);

  llvm::DIType *vtbl_ptr_type = DBuilder.createPointerType(
      SubTy, Size, 0, DWARFAddressSpace, "__vtbl_ptr_type");
  VTablePtrType = DBuilder.createPointerType(vtbl_ptr_type, Size);
  return VTablePtrType;
}

StringRef CGDebugInfo::getVTableName(const CXXRecordDecl *RD) {
  // Copy the gdb compatible name on the side and use its reference.
  return internString("_vptr$", RD->getNameAsString());
}

// Emit symbol for the debugger that points to the vtable address for
// the given class. The symbol is named as '__clang_vtable'.
// The debugger does not need to know any details about the contents of the
// vtable as it can work this out using its knowledge of the ABI and the
// existing information in the DWARF. The type is assumed to be 'void *'.
void CGDebugInfo::emitVTableSymbol(llvm::GlobalVariable *VTable,
                                   const CXXRecordDecl *RD) {
  if (!CGM.getTarget().getCXXABI().isItaniumFamily())
    return;
  if (DebugKind <= llvm::codegenoptions::DebugLineTablesOnly)
    return;

  // On COFF platform, we shouldn't emit a reference to an external entity (i.e.
  // VTable) into debug info, which is constructed within a discardable section.
  // If that entity ends up implicitly dllimported from another DLL, the linker
  // may produce a runtime pseudo-relocation for it (BFD-ld only. LLD prohibits
  // to emit such relocation). If the debug section is stripped, the runtime
  // pseudo-relocation points to memory space outside of the module, causing an
  // access violation.
  if (CGM.getTarget().getTriple().isOSBinFormatCOFF() &&
      VTable->isDeclarationForLinker())
    return;

  ASTContext &Context = CGM.getContext();
  StringRef SymbolName = "__clang_vtable";
  SourceLocation Loc;
  QualType VoidPtr = Context.getPointerType(Context.VoidTy);