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

Reply via email to