[clang] [Clang] Avoid assertion failure for initialized extern aliases (PR #223124)
via cfe-commits
cfe-commits at lists.llvm.org
Sat Oct 3 02:10:35 PDT 2026
https://github.com/keepyixiao updated https://github.com/llvm/llvm-project/pull/223124
>From a632b459912d1fc82b0194ada9d0358ef117cfb6 Mon Sep 17 00:00:00 2001
From: nudt_yixiao <1272950933 at qq.com>
Date: Wed, 23 Sep 2026 10:39:13 +0800
Subject: [PATCH] [Clang] Fix handling of alias variable definitions
Fix an assertion when an alias variable has an initializer, and treat
defining attributes on in-class static data members as definitions so that
later out-of-line definitions are correctly diagnosed.
Add regression tests and a release note.
---
clang/docs/ReleaseNotes.md | 5 ++
clang/lib/AST/Decl.cpp | 2 +-
clang/lib/Sema/SemaDecl.cpp | 2 +-
clang/test/Sema/alias-redefinition.c | 69 ++++++++++++++++++++++++++--
4 files changed, 73 insertions(+), 5 deletions(-)
diff --git a/clang/docs/ReleaseNotes.md b/clang/docs/ReleaseNotes.md
index f6cdca91cea1035..bdad85326c6263e 100644
--- a/clang/docs/ReleaseNotes.md
+++ b/clang/docs/ReleaseNotes.md
@@ -590,6 +590,11 @@ 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. Static data members declared with
+ `alias` are now correctly diagnosed as definitions when followed by an
+ out-of-line definition. (#GH204762)
+
#### Bug Fixes to C++ Support
- Fixed lambdas with specifiers or attributes after the capture list being
diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp
index ffd9bd33c7501c4..b094137cee347b3 100644
--- a/clang/lib/AST/Decl.cpp
+++ b/clang/lib/AST/Decl.cpp
@@ -2268,7 +2268,7 @@ VarDecl::isThisDeclarationADefinition(ASTContext &C) const {
TSK_ExplicitSpecialization) ||
isa<VarTemplatePartialSpecializationDecl>(this)))
return Definition;
- if (!isOutOfLine() && isInline())
+ if (!isOutOfLine() && (isInline() || hasDefiningAttr()))
return Definition;
return DeclarationOnly;
}
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index db5e66cb96c3ec0..94da9e77e4d972b 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -7192,7 +7192,7 @@ static void checkAliasAttr(Sema &S, NamedDecl &ND) {
if (VD->hasInit()) {
if (const auto *Attr = VD->getAttr<AliasAttr>()) {
assert(VD->isThisDeclarationADefinition() &&
- !VD->isExternallyVisible() && "Broken AliasAttr handled late!");
+ "Broken AliasAttr handled late!");
S.Diag(Attr->getLocation(), diag::err_alias_is_definition) << VD << 0;
VD->dropAttr<AliasAttr>();
}
diff --git a/clang/test/Sema/alias-redefinition.c b/clang/test/Sema/alias-redefinition.c
index 526b67d9be7f298..7b5a8a0fe5993dc 100644
--- a/clang/test/Sema/alias-redefinition.c
+++ b/clang/test/Sema/alias-redefinition.c
@@ -1,4 +1,5 @@
-// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -Wno-strict-prototypes -fsyntax-only -verify %s
+// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -Wno-strict-prototypes -fsyntax-only -verify=expected,c %s
+// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -Wno-strict-prototypes -x c++ -fsyntax-only -verify=expected,cxx %s
void f0() {}
void fun0(void) __attribute((alias("f0")));
@@ -22,11 +23,73 @@ void fun4(void);
void f5() {}
void __attribute((alias("f5"))) fun5(void) {} // expected-error {{definition 'fun5' cannot also be an alias}}
+typedef void (*func_ptr)(void);
+
+static void implementation(void) {}
+
+static func_ptr resolver1(void) {
+ return implementation;
+}
+
+void f6(void) __attribute__((ifunc("resolver1"))); // expected-note {{previous definition is here}}
+void f6(void) __attribute__((alias("implementation"))); // expected-error {{redefinition of 'f6'}}
+
+void f7(void) __attribute__((alias("implementation"))); // expected-note {{previous definition is here}}
+void f7(void) __attribute__((ifunc("resolver1"))); // expected-error {{redefinition of 'f7'}}
+
+void f8(void) __attribute__((ifunc("resolver1"), alias("implementation"))); // expected-error {{definition 'f8' cannot also be an alias}}
+
+void f9(void) __attribute__((alias("implementation"), ifunc("resolver1"))); // expected-error {{definition 'f9' cannot also be an ifunc}}
+
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}}
+
+int target;
+int loader_then_alias __attribute((loader_uninitialized, alias("target"))); // expected-error {{definition 'loader_then_alias' cannot also be an alias}}
+
+int alias_then_loader __attribute((alias("target"), loader_uninitialized)); // expected-error {{definition 'alias_then_loader' cannot also be an alias}}
+
+int loader_redecl_alias __attribute((loader_uninitialized)); // expected-note {{previous definition is here}}
+extern int loader_redecl_alias __attribute((alias("target"))); // expected-error {{redefinition of 'loader_redecl_alias'}}
+
+extern int loader_redecl_alias1 __attribute((alias("target"))); // c-note {{previous definition is here}} cxx-note 2 {{previous definition is here}}
+int loader_redecl_alias1 __attribute((loader_uninitialized));
+// c-error at -1 {{redeclaration cannot add 'loader_uninitialized' attribute}}
+// cxx-error at -2 {{redefinition of 'loader_redecl_alias1'}}
+// cxx-warning at -3 {{attribute declaration must precede definition}}
extern int var3 __attribute__((alias("C"))); // expected-note{{previous definition is here}}
int var3 = 3; // expected-error{{redefinition of 'var3'}}
-int var4; // expected-note{{previous definition is here}}
-extern int var4 __attribute__((alias("v4"))); // expected-error{{alias definition of 'var4' after tentative definition}}
+int var4; // expected-note {{previous definition is here}}
+extern int var4 __attribute__((alias("v4")));
+// c-error at -1 {{alias definition of 'var4' after tentative definition}}
+// cxx-error at -2 {{redefinition of 'var4'}}
+
+
+#ifdef __cplusplus
+
+int foo;
+struct S {
+ static const int i __attribute__((alias("foo"))) = 12; // expected-error {{definition 'i' cannot also be an alias}}
+};
+
+struct OutOfLineDefinitionWithInitializer {
+ static int i __attribute__((alias("foo"))); // expected-note {{previous definition is here}}
+};
+int OutOfLineDefinitionWithInitializer::i = 12; // expected-error {{redefinition of 'i'}}
+
+struct OutOfLineDefinitionWithoutInitializer {
+ static int i1 __attribute__((alias("foo"))); // expected-note {{previous definition is here}}
+};
+int OutOfLineDefinitionWithoutInitializer::i1; // expected-error {{redefinition of 'i1'}}
+
+struct AliasDefinition {
+ static int i2 __attribute__((alias("foo")));
+};
+
+#endif
More information about the cfe-commits
mailing list