https://github.com/aokblast updated https://github.com/llvm/llvm-project/pull/228809
>From de2e0aad18a3146a8f608a5ce9eac6637a7b6d05 Mon Sep 17 00:00:00 2001 From: ShengYi Hung <[email protected]> Date: Sat, 3 Oct 2026 21:33:47 -0500 Subject: [PATCH 1/2] [Clang][Smea] Accept weak reference after declaration GCC accepts a weak reference even after there is a declaration. It is fine for us to just append a weak attribute in the previous declaration directly. --- clang/docs/ReleaseNotes.md | 3 +++ clang/lib/Sema/SemaDeclAttr.cpp | 25 +++++++++++++++++++++ clang/test/CodeGen/pragma-weak.c | 37 ++++++++++++++++++++++++++++++++ clang/test/Sema/pragma-weak.c | 17 +++++++++++++++ 4 files changed, 82 insertions(+) diff --git a/clang/docs/ReleaseNotes.md b/clang/docs/ReleaseNotes.md index b71758e4b9647..88537fd63e481 100644 --- a/clang/docs/ReleaseNotes.md +++ b/clang/docs/ReleaseNotes.md @@ -580,6 +580,9 @@ features cannot lower the translation-unit ABI level; #### Bug Fixes to Attribute Support +- `#pragma weak alias = target` no longer makes every later use of `alias` + ambiguous when `alias` was already declared: the alias is now attached to the + existing declaration, and a definition of `alias` is diagnosed. (#GH35478), (#GH56760) - Fixed crash (assertion) when the `alloc_align` attribute was applied to a declaration whose type has a `FunctionProtoType` but which is not itself a `FunctionDecl`, such as a function-pointer variable. (#GH122058) - Fixed a crash on `bool` vectors declared with `ext_vector_type` and more than diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index eb4a8c2ab9ae0..0d9f2eb2029dd 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -8804,6 +8804,31 @@ NamedDecl *Sema::DeclClonePragmaWeak(NamedDecl *ND, const IdentifierInfo *II, void Sema::DeclApplyPragmaWeak(Scope *S, NamedDecl *ND, const WeakInfo &W) { if (W.getAlias()) { // clone decl, impersonate __attribute(weak,alias(...)) IdentifierInfo *NDId = ND->getIdentifier(); + + // Append attribute on previous declaration only. + NamedDecl *Prev = LookupSingleName(TUScope, W.getAlias(), W.getLocation(), + LookupOrdinaryName); + if (Prev && (isa<FunctionDecl>(Prev) || isa<VarDecl>(Prev)) && + Prev->getDeclContext()->getRedeclContext()->isTranslationUnit()) { + if (Prev->hasAttr<AliasAttr>()) + return; + bool IsDefinition = false; + if (auto *FD = dyn_cast<FunctionDecl>(Prev)) + IsDefinition = FD->isDefined(); + else + IsDefinition = + cast<VarDecl>(Prev)->hasDefinition() != VarDecl::DeclarationOnly; + if (IsDefinition) { + Diag(W.getLocation(), diag::err_alias_is_definition) << Prev << 0; + return; + } + Prev->addAttr( + AliasAttr::CreateImplicit(Context, NDId->getName(), W.getLocation())); + Prev->addAttr(WeakAttr::CreateImplicit(Context, W.getLocation())); + WeakTopLevelDecl.push_back(Prev); + return; + } + NamedDecl *NewD = DeclClonePragmaWeak(ND, W.getAlias(), W.getLocation()); NewD->addAttr( AliasAttr::CreateImplicit(Context, NDId->getName(), W.getLocation())); diff --git a/clang/test/CodeGen/pragma-weak.c b/clang/test/CodeGen/pragma-weak.c index ea508a485ef61..9d32e1f177294 100644 --- a/clang/test/CodeGen/pragma-weak.c +++ b/clang/test/CodeGen/pragma-weak.c @@ -21,6 +21,10 @@ // CHECK-DAG: @undecfunc_alias2 = weak{{.*}} alias void (), ptr @undecfunc // CHECK-DAG: @undecfunc_alias3 = weak{{.*}} alias void (), ptr @undecfunc // CHECK-DAG: @undecfunc_alias4 = weak{{.*}} alias void (), ptr @undecfunc +// CHECK-DAG: @predecl_alias = weak{{.*}} alias i32 (i32), ptr @__predecl_alias +// CHECK-DAG: @predecl_noproto_alias = weak{{.*}} alias i32 (...), ptr @__predecl_noproto_alias +// CHECK-DAG: @predecl_alias2 = weak{{.*}} alias i32 (i32), ptr @__predecl_alias2 +// CHECK-DAG: @predecl_var_alias = weak{{.*}} alias i32, ptr @__predecl_var_alias @@ -149,6 +153,39 @@ __attribute((noinline,const)) int __xxx(void) { return 0; } void undecfunc_alias2(void); void undecfunc(void) { } +///////////// GH35478, GH56760: the weak name is declared before the pragma. The +// pragma must apply to that declaration rather than introduce a second one, so +// uses of the name stay unambiguous. +int predecl_alias(int), __predecl_alias(int); +#pragma weak predecl_alias = __predecl_alias +int __predecl_alias(int i) { return 0; } +int use_predecl_alias(void) { return predecl_alias(0); } +// CHECK-LABEL: define{{.*}} i32 @use_predecl_alias() +// CHECK: call i32 @predecl_alias(i32 noundef 0) + +// Same, without a prototype (GH35478). +extern int predecl_noproto_alias(); +#pragma weak predecl_noproto_alias = __predecl_noproto_alias +int __predecl_noproto_alias() { return 0; } +int use_predecl_noproto_alias(void) { return predecl_noproto_alias(); } +// CHECK-LABEL: define{{.*}} i32 @use_predecl_noproto_alias() +// CHECK: call i32 (...) @predecl_noproto_alias() + +// Same, but with the pragma preceding both declarations. +#pragma weak predecl_alias2 = __predecl_alias2 +int predecl_alias2(int), __predecl_alias2(int); +int __predecl_alias2(int i) { return 0; } +int use_predecl_alias2(void) { return predecl_alias2(0); } +// CHECK-LABEL: define{{.*}} i32 @use_predecl_alias2() +// CHECK: call i32 @predecl_alias2(i32 noundef 0) + +extern int predecl_var_alias; +int __predecl_var_alias = 3; +#pragma weak predecl_var_alias = __predecl_var_alias +int use_predecl_var_alias(void) { return predecl_var_alias; } +// CHECK-LABEL: define{{.*}} i32 @use_predecl_var_alias() +// CHECK: load i32, ptr @predecl_var_alias + ///////////// PR10878: Make sure we can call a weak alias void SHA512Pad(void *context) {} #pragma weak SHA384Pad = SHA512Pad diff --git a/clang/test/Sema/pragma-weak.c b/clang/test/Sema/pragma-weak.c index c14125eac9f7c..3b9991cc82052 100644 --- a/clang/test/Sema/pragma-weak.c +++ b/clang/test/Sema/pragma-weak.c @@ -9,3 +9,20 @@ void __a3(void) __attribute((noinline)); #pragma weak a3 = __a3 // expected-note {{previous definition}} void a3(void) __attribute((alias("__a3"))); // expected-error {{redefinition of 'a3'}} void __a3(void) {} + +// The weak name is already defined: a definition cannot also be an alias. +void __defined_fn(void); +void defined_fn(void) {} +#pragma weak defined_fn = __defined_fn // expected-error {{definition 'defined_fn' cannot also be an alias}} +void __defined_fn(void) {} + +int __defined_var = 1; +int defined_var; +#pragma weak defined_var = __defined_var // expected-error {{definition 'defined_var' cannot also be an alias}} + +// GH35478, GH56760: a pre-existing declaration of the weak name must not make +// uses ambiguous. +int predecl(int), __predecl(int); +#pragma weak predecl = __predecl +int __predecl(int i) { return 0; } +int use_predecl(void) { return predecl(0); } >From 860e0b56f244f0d776ba534b12b4ccb7f3d9f87c Mon Sep 17 00:00:00 2001 From: ShengYi Hung <[email protected]> Date: Tue, 13 Oct 2026 00:11:37 -0500 Subject: [PATCH 2/2] fixup! Merge branch 'main' into users/aokblast/clang/sema_accept_weak_after_decl --- clang/docs/ReleaseNotes.md | 3 --- clang/test/Sema/pragma-weak.c | 35 +++++++++++++++++------------------ 2 files changed, 17 insertions(+), 21 deletions(-) diff --git a/clang/docs/ReleaseNotes.md b/clang/docs/ReleaseNotes.md index da32229b68f4a..611571d3aa87c 100644 --- a/clang/docs/ReleaseNotes.md +++ b/clang/docs/ReleaseNotes.md @@ -713,8 +713,6 @@ features cannot lower the translation-unit ABI level; #### Bug Fixes to Attribute Support - - - Fixed an assertion failure when parsing malformed GNU `__attribute__` syntax followed by a parenthesized expression list in C code. (#GH225045) @@ -725,7 +723,6 @@ features cannot lower the translation-unit ABI level; ambiguous when `alias` was already declared: the alias is now attached to the existing declaration, and a definition of `alias` is diagnosed. (#GH35478), (#GH56760) ->>>>>>> main - Fixed crash (assertion) when the `alloc_align` attribute was applied to a declaration whose type has a `FunctionProtoType` but which is not itself a `FunctionDecl`, such as a function-pointer variable. (#GH122058) - Fixed a crash on `bool` vectors declared with `ext_vector_type` and more than diff --git a/clang/test/Sema/pragma-weak.c b/clang/test/Sema/pragma-weak.c index 3c1573ebb6b0f..bb5e99f4f4a4b 100644 --- a/clang/test/Sema/pragma-weak.c +++ b/clang/test/Sema/pragma-weak.c @@ -10,23 +10,6 @@ void __a3(void) __attribute((noinline)); void a3(void) __attribute((alias("__a3"))); // expected-error {{redefinition of 'a3'}} void __a3(void) {} -// The weak name is already defined: a definition cannot also be an alias. -void __defined_fn(void); -void defined_fn(void) {} -#pragma weak defined_fn = __defined_fn // expected-error {{definition 'defined_fn' cannot also be an alias}} -void __defined_fn(void) {} - -int __defined_var = 1; -int defined_var; -#pragma weak defined_var = __defined_var // expected-error {{definition 'defined_var' cannot also be an alias}} - -// GH35478, GH56760: a pre-existing declaration of the weak name must not make -// uses ambiguous. -int predecl(int), __predecl(int); -#pragma weak predecl = __predecl -int __predecl(int i) { return 0; } -int use_predecl(void) { return predecl(0); } -======= void *resolver(void) { return 0; } // Pragma weak can be applied before or after the ifunc declaration. @@ -53,4 +36,20 @@ void pragma_ifunc_on_redecl(void) __attribute__((ifunc("resolver"))); // A weak alias of an ifunc does not make the ifunc itself weak. #pragma weak pragma_alias = ifunc_alias_target void ifunc_alias_target(void) __attribute__((ifunc("resolver"))); ->>>>>>> main + +// The weak name is already defined: a definition cannot also be an alias. +void __defined_fn(void); +void defined_fn(void) {} +#pragma weak defined_fn = __defined_fn // expected-error {{definition 'defined_fn' cannot also be an alias}} +void __defined_fn(void) {} + +int __defined_var = 1; +int defined_var; +#pragma weak defined_var = __defined_var // expected-error {{definition 'defined_var' cannot also be an alias}} + +// GH35478, GH56760: a pre-existing declaration of the weak name must not make +// uses ambiguous. +int predecl(int), __predecl(int); +#pragma weak predecl = __predecl +int __predecl(int i) { return 0; } +int use_predecl(void) { return predecl(0); } _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
