Author: nudt_yixiao
Date: 2026-10-06T08:24:15Z
New Revision: a7f05671c9037b7bec6ef6608b97485ff6768d2c

URL: 
https://github.com/llvm/llvm-project/commit/a7f05671c9037b7bec6ef6608b97485ff6768d2c
DIFF: 
https://github.com/llvm/llvm-project/commit/a7f05671c9037b7bec6ef6608b97485ff6768d2c.diff

LOG: [Clang] Avoid assertion failure for initialized extern aliases (#223124)

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.

AI was used to assist with code analysis, debugging, and drafting the PR
description. I personally debugged, reviewed and verified the changes,
tested the code, and fully understand the submitted contribution.

Fixes https://github.com/llvm/llvm-project/issues/204762

Added: 
    

Modified: 
    clang/docs/ReleaseNotes.md
    clang/lib/AST/Decl.cpp
    clang/lib/Sema/SemaDecl.cpp
    clang/test/Sema/alias-redefinition.c

Removed: 
    


################################################################################
diff  --git a/clang/docs/ReleaseNotes.md b/clang/docs/ReleaseNotes.md
index 7b878a0abbab3..cb3657952dbe8 100644
--- a/clang/docs/ReleaseNotes.md
+++ b/clang/docs/ReleaseNotes.md
@@ -648,6 +648,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 b145560508e95..f7a635e35336a 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 094601a58d508..59c0faa67364a 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -7191,7 +7191,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 526b67d9be7f2..7b5a8a0fe5993 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@-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@-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@-1 {{redeclaration cannot add 'loader_uninitialized' attribute}}
+// cxx-error@-2 {{redefinition of 'loader_redecl_alias1'}}
+// cxx-warning@-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@-1 {{alias definition of 'var4' after tentative definition}}
+// cxx-error@-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


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

Reply via email to