https://github.com/SharonXSharon updated 
https://github.com/llvm/llvm-project/pull/219261

>From dcb89b24bafaaac774a6a532f21230acc226b4f6 Mon Sep 17 00:00:00 2001
From: Sharon Xu <[email protected]>
Date: Mon, 24 Aug 2026 13:52:01 -0700
Subject: [PATCH 1/2] [clang] Apply -funique-internal-linkage-names to internal
 global variables

-funique-internal-linkage-names appends a `.__uniq.<module hash>` suffix to
internal-linkage symbols so they are distinguishable across a build. Until
now the suffix was applied only to functions; internal global variables were
left alone, which was originally deferred until demanglers could cope with a
suffix on a data symbol.

Apply the suffix to internal-linkage variables as well. This lets profiling
tools map a sampled data address back to the exact symbol that produced it,
which is otherwise ambiguous when several translation units define
same-named statics.

LLVM's demangler handles suffixed data symbols today:

  $ llvm-cxxfilt _ZL8glob_foo.__uniq.123
  glob_foo (.__uniq.123)

GNU libiberty does not yet. Its clone-suffix handling only runs for symbols
carrying a <bare-function-type>, so `nm -C`, `objdump -C` and gdb still print
suffixed *data* symbols unchanged. This is a pre-existing libiberty
limitation rather than something specific to this suffix -- `.part.N` on a
data symbol fails the same way -- and it needs a separate fix in
libiberty/cp-demangle.c. Since -funique-internal-linkage-names is opt-in,
default builds are unaffected.

The asm-label exclusion added in 774c4c9b098 is preserved and now applies to
variables too: a static variable with an asm label keeps its label verbatim.
---
 clang/lib/AST/ItaniumMangle.cpp               | 12 ++++-----
 clang/lib/CodeGen/CodeGenModule.cpp           | 11 +++++---
 .../CodeGen/unique-internal-linkage-names.cpp | 27 ++++++++++++-------
 .../unique-internal-linkage-names-dwarf.c     |  6 ++---
 .../unique-internal-linkage-names-dwarf.cpp   | 14 +++++-----
 5 files changed, 40 insertions(+), 30 deletions(-)

diff --git a/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp
index 7fb162a68fe88..dad83fb12ece6 100644
--- a/clang/lib/AST/ItaniumMangle.cpp
+++ b/clang/lib/AST/ItaniumMangle.cpp
@@ -725,20 +725,18 @@ bool 
ItaniumMangleContextImpl::isInternalLinkageDecl(const NamedDecl *ND) {
   return false;
 }
 
-// Check if this Function Decl needs a unique internal linkage name.
+// Check if this Decl needs a unique internal linkage name.
 bool ItaniumMangleContextImpl::isUniqueInternalLinkageDecl(
     const NamedDecl *ND) {
   if (!NeedsUniqueInternalLinkageNames || !ND)
     return false;
 
-  const auto *FD = dyn_cast<FunctionDecl>(ND);
-  if (!FD)
-    return false;
-
   // For C functions without prototypes, return false as their
   // names should not be mangled.
-  if (!FD->getType()->getAs<FunctionProtoType>())
-    return false;
+  if (const auto *FD = dyn_cast<FunctionDecl>(ND)) {
+    if (!FD->getType()->getAs<FunctionProtoType>())
+      return false;
+  }
 
   if (isInternalLinkageDecl(ND))
     return true;
diff --git a/clang/lib/CodeGen/CodeGenModule.cpp 
b/clang/lib/CodeGen/CodeGenModule.cpp
index 435f67542268a..25c6c3d2bf63d 100644
--- a/clang/lib/CodeGen/CodeGenModule.cpp
+++ b/clang/lib/CodeGen/CodeGenModule.cpp
@@ -2460,14 +2460,17 @@ static void AppendCPUSpecificCPUDispatchMangling(const 
CodeGenModule &CGM,
     Out << ".resolver";
 }
 
-// Returns true if GD is a function decl with internal linkage and
+// Returns true if GD is a function/var decl with internal linkage and
 // needs a unique suffix after the mangled name.
 static bool isUniqueInternalLinkageDecl(GlobalDecl GD,
                                         CodeGenModule &CGM) {
   const Decl *D = GD.getDecl();
-  return !CGM.getModuleNameHash().empty() && isa<FunctionDecl>(D) &&
-         !D->hasAttr<AsmLabelAttr>() &&
-         (CGM.getFunctionLinkage(GD) == llvm::GlobalValue::InternalLinkage);
+  if (CGM.getModuleNameHash().empty() || D->hasAttr<AsmLabelAttr>())
+    return false;
+  return (isa<FunctionDecl>(D) &&
+          CGM.getFunctionLinkage(GD) == llvm::GlobalValue::InternalLinkage) ||
+         (isa<VarDecl>(D) && CGM.getContext().GetGVALinkageForVariable(
+                                 cast<VarDecl>(D)) == GVA_Internal);
 }
 
 static std::string getMangledNameImpl(CodeGenModule &CGM, GlobalDecl GD,
diff --git a/clang/test/CodeGen/unique-internal-linkage-names.cpp 
b/clang/test/CodeGen/unique-internal-linkage-names.cpp
index b5c4824575372..a65813a6fb338 100644
--- a/clang/test/CodeGen/unique-internal-linkage-names.cpp
+++ b/clang/test/CodeGen/unique-internal-linkage-names.cpp
@@ -64,8 +64,13 @@ static int asm_label() asm("custom_label");
 static int asm_label() { return 0; }
 int call_asm_label() { return asm_label(); }
 
+// Likewise for a static variable with an asm label.
+static int asm_label_var asm("custom_var_label");
+int read_asm_label_var() { return asm_label_var; }
+
 // PLAIN: @_ZL4glob = internal global
 // PLAIN: @_ZZ8retAnonMvE5fGlob = internal global
+// PLAIN: @custom_var_label = internal global
 // PLAIN: @_ZN12_GLOBAL__N_16anon_mE = internal global
 // PLAIN: define internal noundef i32 @_ZL3foov()
 // PLAIN: define internal noundef i32 @_ZN12_GLOBAL__N_14getMEv
@@ -76,10 +81,11 @@ int call_asm_label() { return asm_label(); }
 // PLAIN: define internal noundef i32 @_ZL4mverv()
 // PLAIN: define internal noundef i32 @_ZL4mverv.sse4.2()
 // PLAIN-NOT: "sample-profile-suffix-elision-policy"
-// UNIQUE: @_ZL4glob = internal global
-// UNIQUE: @_ZZ8retAnonMvE5fGlob = internal global
-// UNIQUE: @_ZN12_GLOBAL__N_16anon_mE = internal global
-// UNIQUE: define internal noundef i32 @_ZL3foov.[[MODHASH:__uniq.[0-9]+]]() 
#[[#ATTR:]] {
+// UNIQUE: @_ZL4glob.[[MODHASH:__uniq.[0-9]+]] = internal global
+// UNIQUE: @_ZZ8retAnonMvE5fGlob.[[MODHASH]] = internal global
+// UNIQUE: @custom_var_label = internal global
+// UNIQUE: @_ZN12_GLOBAL__N_16anon_mE.[[MODHASH]] = internal global
+// UNIQUE: define internal noundef i32 @_ZL3foov.[[MODHASH]]() #[[#ATTR:]] {
 // UNIQUE: define internal noundef i32 @_ZN12_GLOBAL__N_14getMEv.[[MODHASH]]
 // UNIQUE: define internal ptr @_ZL4mverv.[[MODHASH]].resolver()
 // UNIQUE: define internal void 
@_ZN12_GLOBAL__N_11AC1Ev.__uniq.68358509610070717889884130747296293671
@@ -92,9 +98,10 @@ int call_asm_label() { return asm_label(); }
 // Expected module path and unique ID
 // /repro/src/path/unique-internal-linkage-names.cpp => 
__uniq.5283619504002921413211664429594652319
 
-// UNIQUE-PATH-MAP-LINUX: @_ZL4glob = internal global
-// UNIQUE-PATH-MAP-LINUX: @_ZZ8retAnonMvE5fGlob = internal global
-// UNIQUE-PATH-MAP-LINUX: @_ZN12_GLOBAL__N_16anon_mE = internal global
+// UNIQUE-PATH-MAP-LINUX: 
@_ZL4glob.__uniq.5283619504002921413211664429594652319 = internal global
+// UNIQUE-PATH-MAP-LINUX: 
@_ZZ8retAnonMvE5fGlob.__uniq.5283619504002921413211664429594652319 = internal 
global
+// UNIQUE-PATH-MAP-LINUX: @custom_var_label = internal global
+// UNIQUE-PATH-MAP-LINUX: 
@_ZN12_GLOBAL__N_16anon_mE.__uniq.5283619504002921413211664429594652319 = 
internal global
 // UNIQUE-PATH-MAP-LINUX: define internal noundef i32 
@_ZL3foov.__uniq.5283619504002921413211664429594652319() #[[#ATTR:]] {
 // UNIQUE-PATH-MAP-LINUX: define internal noundef i32 
@_ZN12_GLOBAL__N_14getMEv.__uniq.5283619504002921413211664429594652319
 // UNIQUE-PATH-MAP-LINUX: define internal ptr 
@_ZL4mverv.__uniq.5283619504002921413211664429594652319.resolver()
@@ -107,9 +114,11 @@ int call_asm_label() { return asm_label(); }
 // Expected module path and unique ID
 // \repro\src\path\unique-internal-linkage-names.cpp => 
__uniq.68451533753012730514350177221027644473
 
+// Note: 'glob' is not mangled under the MS ABI, so it gets no unique suffix.
 // UNIQUE-PATH-MAP-WINDOWS: @glob = internal global
-// UNIQUE-PATH-MAP-WINDOWS: @"?fGlob@?1??retAnonM@@YAHXZ@4HA" = internal global
-// UNIQUE-PATH-MAP-WINDOWS: @"?anon_m@?{{.*}}@@3HA" = internal global
+// UNIQUE-PATH-MAP-WINDOWS: 
@"?fGlob@?1??retAnonM@@YAHXZ@4HA.__uniq.68451533753012730514350177221027644473" 
= internal global
+// UNIQUE-PATH-MAP-WINDOWS: @custom_var_label = internal global
+// UNIQUE-PATH-MAP-WINDOWS: 
@"?anon_m@?{{.*}}@@3HA.__uniq.68451533753012730514350177221027644473" = 
internal global
 // UNIQUE-PATH-MAP-WINDOWS: ret ptr 
@"?foo@@YAHXZ.__uniq.68451533753012730514350177221027644473"
 // UNIQUE-PATH-MAP-WINDOWS: define internal noundef i32 
@"?foo@@YAHXZ.__uniq.68451533753012730514350177221027644473"
 // UNIQUE-PATH-MAP-WINDOWS: define internal i32 
@"?mver@@YAHXZ.__uniq.68451533753012730514350177221027644473.resolver"()
diff --git a/clang/test/DebugInfo/Generic/unique-internal-linkage-names-dwarf.c 
b/clang/test/DebugInfo/Generic/unique-internal-linkage-names-dwarf.c
index 5a401182450ab..8f9dc143654c9 100644
--- a/clang/test/DebugInfo/Generic/unique-internal-linkage-names-dwarf.c
+++ b/clang/test/DebugInfo/Generic/unique-internal-linkage-names-dwarf.c
@@ -33,9 +33,9 @@ void baz(void) {
 // PLAIN: distinct !DISubprogram(name: "bar"{{.*}})
 // PLAIN-NOT: linkageName:
 //
-// UNIQUE: @glob = internal global i32
-// UNIQUE: define internal i32 @_ZL3foov.[[MODHASH:__uniq.[0-9]+]]()
+// UNIQUE: @_ZL4glob.[[MODHASH:__uniq.[0-9]+]] = internal global i32
+// UNIQUE: define internal i32 @_ZL3foov.[[MODHASH]]()
 // UNIQUE: define internal i32 @_ZL3bari.[[MODHASH]](i32 noundef %a)
-// UNIQUE: distinct !DIGlobalVariable(name: "glob"{{.*}})
+// UNIQUE: distinct !DIGlobalVariable(name: "glob", linkageName: 
"_ZL4glob.[[MODHASH]]"{{.*}})
 // UNIQUE: distinct !DISubprogram(name: "foo", linkageName: 
"_ZL3foov.[[MODHASH]]"{{.*}})
 // UNIQUE: distinct !DISubprogram(name: "bar", linkageName: 
"_ZL3bari.[[MODHASH]]"{{.*}})
diff --git 
a/clang/test/DebugInfo/Generic/unique-internal-linkage-names-dwarf.cpp 
b/clang/test/DebugInfo/Generic/unique-internal-linkage-names-dwarf.cpp
index cdd7062a3a009..e49fe5736092d 100644
--- a/clang/test/DebugInfo/Generic/unique-internal-linkage-names-dwarf.cpp
+++ b/clang/test/DebugInfo/Generic/unique-internal-linkage-names-dwarf.cpp
@@ -46,15 +46,15 @@ void baz() {
 // PLAIN-DAG: distinct !DIGlobalVariable(name: "glob_zip", linkageName: 
"_ZL8glob_zip"{{.*}})
 // PLAIN-DAG: distinct !DISubprogram(name: "zip", linkageName: 
"_ZL3zipv"{{.*}})
 
-// UNIQUE-DAG: @_ZL8glob_foo = internal global i32
-// UNIQUE-DAG: define internal noundef i32 
@_ZL3foov.[[MODHASH:__uniq\.[0-9]+]]()
-// UNIQUE-DAG: distinct !DIGlobalVariable(name: "glob_foo", linkageName: 
"_ZL8glob_foo"{{.*}})
+// UNIQUE-DAG: @_ZL8glob_foo.[[MODHASH:__uniq\.[0-9]+]] = internal global i32
+// UNIQUE-DAG: define internal noundef i32 @_ZL3foov.[[MODHASH]]()
+// UNIQUE-DAG: distinct !DIGlobalVariable(name: "glob_foo", linkageName: 
"_ZL8glob_foo.[[MODHASH]]"{{.*}})
 // UNIQUE-DAG: distinct !DISubprogram(name: "foo", linkageName: 
"_ZL3foov.[[MODHASH]]"{{.*}})
-// UNIQUE-DAG: @_ZN12_GLOBAL__N_18glob_barE = internal global i32
+// UNIQUE-DAG: @_ZN12_GLOBAL__N_18glob_barE.[[MODHASH]] = internal global i32
 // UNIQUE-DAG: define internal noundef i32 
@_ZN12_GLOBAL__N_13barEv.[[MODHASH]]()
-// UNIQUE-DAG: distinct !DIGlobalVariable(name: "glob_bar", linkageName: 
"_ZN12_GLOBAL__N_18glob_barE"{{.*}})
+// UNIQUE-DAG: distinct !DIGlobalVariable(name: "glob_bar", linkageName: 
"_ZN12_GLOBAL__N_18glob_barE.[[MODHASH]]"{{.*}})
 // UNIQUE-DAG: distinct !DISubprogram(name: "bar", linkageName: 
"_ZN12_GLOBAL__N_13barEv.[[MODHASH]]"{{.*}})
-// UNIQUE-DAG: @_ZL8glob_zip = internal global i32
+// UNIQUE-DAG: @_ZL8glob_zip.[[MODHASH]] = internal global i32
 // UNIQUE-DAG: define internal noundef i32 @_ZL3zipv.[[MODHASH]]()
-// UNIQUE-DAG: distinct !DIGlobalVariable(name: "glob_zip", linkageName: 
"_ZL8glob_zip"{{.*}})
+// UNIQUE-DAG: distinct !DIGlobalVariable(name: "glob_zip", linkageName: 
"_ZL8glob_zip.[[MODHASH]]"{{.*}})
 // UNIQUE-DAG: distinct !DISubprogram(name: "zip", linkageName: 
"_ZL3zipv.[[MODHASH]]"{{.*}})

>From 2714a9763911851f11ef2f927d1be7e45c2c4de4 Mon Sep 17 00:00:00 2001
From: Sharon Xu <[email protected]>
Date: Fri, 4 Sep 2026 13:49:28 -0700
Subject: [PATCH 2/2] add documentation

---
 clang/docs/ReleaseNotes.md | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/clang/docs/ReleaseNotes.md b/clang/docs/ReleaseNotes.md
index ca0dbfa2af229..7b06d0ebd34a0 100644
--- a/clang/docs/ReleaseNotes.md
+++ b/clang/docs/ReleaseNotes.md
@@ -228,6 +228,14 @@ features cannot lower the translation-unit ABI level;
 
 - All options of the `-fzero-call-used-regs` compiler flag are now allowed on 
RISC-V.
 
+- `-funique-internal-linkage-names` now gives internal global variables a
+  unique `.__uniq.<module-hash>` suffix, as it already does for functions. This
+  helps profiling tools distinguish static variables with the same name in
+  different source files. LLVM can demangle these suffixes for both functions
+  and data symbols. GNU libiberty can demangle suffixed function symbols, but
+  leaves suffixed data symbols unchanged. The option remains opt-in, and
+  variables with explicit assembly labels keep their original names.
+
 ### Removed Compiler Flags
 
 ### Attribute Changes in Clang

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to