[clang] [clang] Revert "Disable Unique Internal Linkage Names for internal global vars." (PR #219261)
via cfe-commits
cfe-commits at lists.llvm.org
Fri Sep 4 13:49:57 PDT 2026
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 <sharonxu at fb.com>
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 at 4HA" = internal global
-// UNIQUE-PATH-MAP-WINDOWS: @"?anon_m@?{{.*}}@@3HA" = internal global
+// UNIQUE-PATH-MAP-WINDOWS: @"?fGlob@?1??retAnonM@@YAHXZ at 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 <sharonxu at fb.com>
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
More information about the cfe-commits
mailing list