break;
case MCSA_Global:
+ // For `.weak x; .global x`, GNU as sets the binding to STB_WEAK while we
+ // traditionally set the binding to STB_GLOBAL. This is error-prone, so we
+ // error on such cases. Note, we also disallow changed binding from .local.
+ if (Symbol->isBindingSet() && Symbol->getBinding() != ELF::STB_GLOBAL)
+ getContext().reportError(SMLoc(), Symbol->getName() +
+ " changed binding to STB_GLOBAL");
Symbol->setBinding(ELF::STB_GLOBAL);
Symbol->setExternal(true);
break;
case MCSA_WeakReference:
case MCSA_Weak:
+ // For `.global x; .weak x`, both MC and GNU as set the binding to STB_WEAK.
+ // We emit a warning for now but may switch to an error in the future.
+ if (Symbol->isBindingSet() && Symbol->getBinding() != ELF::STB_WEAK)
+ getContext().reportWarning(SMLoc(), Symbol->getName() +
+ " changed binding to STB_WEAK");
Symbol->setBinding(ELF::STB_WEAK);
Symbol->setExternal(true);
break;
case MCSA_Local:
+ if (Symbol->isBindingSet() && Symbol->getBinding() != ELF::STB_LOCAL)
+ getContext().reportError(SMLoc(), Symbol->getName() +
+ " changed binding to STB_LOCAL");
Symbol->setBinding(ELF::STB_LOCAL);
Symbol->setExternal(false);
break;
--- /dev/null
+# RUN: not llvm-mc -filetype=obj -triple=x86_64 %s -o /dev/null 2>&1 | FileCheck %s --implicit-check-not=error:
+
+# CHECK: error: local changed binding to STB_GLOBAL
+local:
+.local local
+.globl local
+
+## `.globl x; .weak x` matches the GNU as behavior. We issue a warning for now.
+# CHECK: warning: global changed binding to STB_WEAK
+global:
+.global global
+.weak global
+
+# CHECK: error: weak changed binding to STB_LOCAL
+weak:
+.weak weak
+.local weak
+
+# CHECK-NOT: error:
+multi_local:
+.local multi_local
+.local multi_local
+multi_global:
+.global multi_global
+.global multi_global
+multi_weak:
+.weak multi_weak
+.weak multi_weak