[clang] [llvm] Disentangle DISubprogram ODR type method uniquing from metadata uniquing (PR #217042)
Vladislav Dzhidzhoev via cfe-commits
cfe-commits at lists.llvm.org
Thu Oct 22 19:04:40 PDT 2026
================
@@ -0,0 +1,106 @@
+//===- llvm/IR/DebugInfoODRUniquer.h - Debug info metadata ------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Defines a class used to merge debug info for ODR types.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/IR/DebugInfoMetadata.h"
+#include "llvm/IR/Metadata.h"
+
+namespace llvm {
+class MDString;
+class Metadata;
+class DICompositeType;
+
+/// Dense set/map find_as key for use alongside DISubprogramODRInfo to
+/// merge function declarations of ODR types.
+struct DISubprogramODRKey {
+ StringRef ScopeIdentifier;
+ StringRef LinkageName;
+
+ DISubprogramODRKey(StringRef ScopeIdentifier, StringRef LinkageName)
+ : ScopeIdentifier(ScopeIdentifier), LinkageName(LinkageName) {}
+
+ DISubprogramODRKey(const DISubprogram *SP) {
+ auto *CT = dyn_cast_or_null<DICompositeType>(SP->getRawScope());
+ ScopeIdentifier = CT ? CT->getIdentifier() : StringRef();
+ LinkageName = SP->getLinkageName();
+ }
+
+ static bool isEqual(const DISubprogramODRKey &LHS, const DISubprogram *RHS) {
+ StringRef RHSIdentifier;
+ if (auto *CT = dyn_cast_or_null<DICompositeType>(RHS->getRawScope()))
+ RHSIdentifier = CT->getIdentifier();
+
+ return LHS.LinkageName == RHS->getLinkageName() &&
+ LHS.ScopeIdentifier == RHSIdentifier;
+ }
+
+ static bool isEqual(const DISubprogram *LHS, const DISubprogram *RHS) {
+ assert(!LHS->isDefinition() && !RHS->isDefinition());
+ return isEqual(DISubprogramODRKey(LHS), RHS);
+ }
+};
+
+/// Dense set/map info to merge function declarations of ODR types.
+struct DISubprogramODRInfo {
+ static unsigned getHashValue(const DISubprogramODRKey &SP) {
+ return hash_combine(SP.ScopeIdentifier, SP.LinkageName);
+ }
+
+ static bool isEqual(const DISubprogramODRKey &LHS, const DISubprogram *RHS) {
+ return DISubprogramODRKey::isEqual(LHS, RHS);
+ }
+
+ static bool isEqual(const DISubprogram *LHS, const DISubprogram *RHS) {
+ assert(!LHS->isDefinition() && !RHS->isDefinition());
+ return DISubprogramODRKey::isEqual(DISubprogramODRKey(LHS), RHS);
+ }
+};
+
+class DebugInfoODRUniquer {
+ /// Function declarations keyed by DISubprogramODRKey to unique on a subset
+ /// of fields, rather than the built-in metadata uniquing which requires
+ /// full structural equality.
+ DenseSet<DISubprogram *, DISubprogramODRInfo> FnDecls;
+
+ /// Function declarations that cannot be ODR-uniqued yet due to a temporary
+ /// scope operand.
+ SmallVector<TempDISubprogram> PendingFnDecls;
+
+public:
+ ~DebugInfoODRUniquer() {
+ assert(PendingFnDecls.empty() &&
+ "Unexpected unresolved maybe-ODR-unqiue DISubprograms");
----------------
dzhidzhoev wrote:
This may crash in case of a broken .ll file:
```
$ cat undefined.ll
!named = !{!0}
!0 = !DISubprogram(name: "f", linkageName: "f", scope: !1, type: !2, spFlags: 0)
!2 = !DISubroutineType(types: !3)
!3 = !{null}
$ llvm-as undefined.ll
llvm-as: undefined.ll:2:57: error: use of undefined metadata '!1'
!0 = !DISubprogram(name: "f", linkageName: "f", scope: !1, type: !2, spFlags: 0)
^
llvm-as: /home/vlad/llvm/llvm-project/llvm/include/llvm/IR/DebugInfoODRUniquer.h:81: llvm::DebugInfoODRUniquer::~DebugInfoODRUniquer(): Assertion `PendingFnDecls.empty() && "Unexpected unresolved maybe-ODR-unqiue DISubprograms"' failed.
PLEASE submit a bug report to https://github.com/llvm/llvm-project/issues/ and include the crash backtrace and instructions to reproduce the bug.
Stack dump:
```
https://github.com/llvm/llvm-project/pull/217042
More information about the cfe-commits
mailing list