[clang] [Clang] Avoid assertion failure for initialized extern aliases (PR #223124)
via cfe-commits
cfe-commits at lists.llvm.org
Sun Sep 20 08:32:51 PDT 2026
https://github.com/keepyixiao updated https://github.com/llvm/llvm-project/pull/223124
>From 8e91d4cec9718746258fb632eac5f73b6792d66a Mon Sep 17 00:00:00 2001
From: yixiao <yixiao at hygon.cn>
Date: Sat, 12 Sep 2026 13:50:35 +0800
Subject: [PATCH] [Clang] Avoid assertion failure for initialized extern
aliases
Attributes are processed before the initializer is attached to the VarDecl,
so an initialized extern variable appears declaration-only in
handleAliasAttr() and can reach a late assertion.
Use Declarator::hasInitializer() and VarDecl::hasExternalStorage() to diagnose
and drop the alias during attribute processing. Keep the late assertion as an
invariant check, and add a regression test and release note.
---
clang/docs/ReleaseNotes.md | 4 ++++
clang/lib/Sema/SemaDeclAttr.cpp | 14 ++++++++++++++
clang/test/Sema/alias-redefinition.c | 5 +++++
3 files changed, 23 insertions(+)
diff --git a/clang/docs/ReleaseNotes.md b/clang/docs/ReleaseNotes.md
index 59b5c14c59242..1ba85521baeb3 100644
--- a/clang/docs/ReleaseNotes.md
+++ b/clang/docs/ReleaseNotes.md
@@ -536,6 +536,10 @@ features cannot lower the translation-unit ABI level;
written after the declarator-id, where it appertains to the declared entity
rather than to a declarator chunk. (#GH196982, #GH111463)
+- Fixed an assertion failure when the `alias` attribute was applied to an
+ `extern` variable with an initializer. Clang now correctly diagnoses that
+ such a declaration is a definition and cannot also be an alias.
+
#### Bug Fixes to C++ Support
- Fixed false-positive module ODR diagnostics when a type is found through a
diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp
index eb4a8c2ab9ae0..ffa0cddb5de92 100644
--- a/clang/lib/Sema/SemaDeclAttr.cpp
+++ b/clang/lib/Sema/SemaDeclAttr.cpp
@@ -8907,6 +8907,20 @@ void Sema::ProcessDeclAttributes(Scope *S, Decl *D, const Declarator &PD) {
// Look for API notes that map to attributes.
ProcessAPINotes(D);
+
+ // An initializer makes a variable declaration incompatible with an alias
+ // attribute. Attributes are processed before the initializer is attached to
+ // the VarDecl, so an extern variable with an initializer still appears to be
+ // a declaration in handleAliasAttr(). Use the information recorded by the
+ // parser and do not let the AliasAttr escape attribute processing.
+ if (auto *VD = dyn_cast<VarDecl>(D)) {
+ if (PD.hasInitializer() && VD->hasExternalStorage()) {
+ if (const auto *Attr = VD->getAttr<AliasAttr>()) {
+ Diag(Attr->getLocation(), diag::err_alias_is_definition) << VD << 0;
+ VD->dropAttr<AliasAttr>();
+ }
+ }
+ }
}
/// Is the given declaration allowed to use a forbidden type?
diff --git a/clang/test/Sema/alias-redefinition.c b/clang/test/Sema/alias-redefinition.c
index 526b67d9be7f2..6ecfdf957af9a 100644
--- a/clang/test/Sema/alias-redefinition.c
+++ b/clang/test/Sema/alias-redefinition.c
@@ -24,6 +24,11 @@ void __attribute((alias("f5"))) fun5(void) {} // expected-error {{definition 'fu
int var1 __attribute((alias("v1"))); // expected-error {{definition 'var1' cannot also be an alias}}
static int var2 __attribute((alias("v2"))) = 2; // expected-error {{definition 'var2' cannot also be an alias}}
+extern int var_with_extern_initializer __attribute__((alias(""))) = 42; // expected-error {{definition 'var_with_extern_initializer' cannot also be an alias}}
+// expected-warning at -1 {{'extern' variable has an initializer}}
+extern int var_with_extern_initializer1 __attribute__((alias("v1"))) = 42; // expected-error {{definition 'var_with_extern_initializer1' cannot also be an alias}}
+// expected-warning at -1 {{'extern' variable has an initializer}}
+
extern int var3 __attribute__((alias("C"))); // expected-note{{previous definition is here}}
int var3 = 3; // expected-error{{redefinition of 'var3'}}
More information about the cfe-commits
mailing list