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
