nickdesaulniers created this revision. nickdesaulniers added a reviewer: rsmith. Herald added subscribers: cfe-commits, kristof.beyls, javed.absar. Herald added a project: clang.
It seems that CodeGen was always using ExternalLinkage when emitting a GlobalDecl with __attribute__((alias)). This leads to symbol redefinitions (ODR) that cause failures at link time for static aliases. This is readily attempting to link an ARM (32b) allyesconfig Linux kernel built with Clang. Reported-by: nathanchance Suggested-by: ihalip Link: https://github.com/ClangBuiltLinux/linux/issues/631 Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D66492 Files: clang/lib/CodeGen/CodeGenModule.cpp clang/test/CodeGen/alias.c Index: clang/test/CodeGen/alias.c =================================================================== --- clang/test/CodeGen/alias.c +++ clang/test/CodeGen/alias.c @@ -2,6 +2,7 @@ // RUN: %clang_cc1 -triple i386-pc-linux-gnu -emit-llvm -o - %s | FileCheck -check-prefix=CHECKBASIC %s // RUN: %clang_cc1 -triple armv7a-eabi -mfloat-abi hard -emit-llvm -o - %s | FileCheck -check-prefix=CHECKCC %s // RUN: %clang_cc1 -triple armv7a-eabi -mfloat-abi hard -S -o - %s | FileCheck -check-prefix=CHECKASM %s +// RUN: %clang_cc1 -emit-llvm -o - %s | FileCheck -check-prefix=CHECKGLOBALS %s int g0; // CHECKBASIC-DAG: @g0 = common global i32 0 @@ -88,3 +89,9 @@ void test9_bar(void) { } void test9_zed(void) __attribute__((section("test"))); void test9_zed(void) __attribute__((alias("test9_bar"))); + +// Test that the alias gets its linkage from its declared qual type. +// CHECKGLOBALS: @test10_foo = internal +// CHECKGLOBALS-NOT: @test10_foo = dso_local +int test10; +static int test10_foo __attribute__((alias("test10"))); Index: clang/lib/CodeGen/CodeGenModule.cpp =================================================================== --- clang/lib/CodeGen/CodeGenModule.cpp +++ clang/lib/CodeGen/CodeGenModule.cpp @@ -4363,17 +4363,22 @@ // Create a reference to the named value. This ensures that it is emitted // if a deferred decl. llvm::Constant *Aliasee; - if (isa<llvm::FunctionType>(DeclTy)) + llvm::GlobalValue::LinkageTypes LT; + if (isa<llvm::FunctionType>(DeclTy)) { Aliasee = GetOrCreateLLVMFunction(AA->getAliasee(), DeclTy, GD, /*ForVTable=*/false); - else + LT = getFunctionLinkage(GD); + } else { Aliasee = GetOrCreateLLVMGlobal(AA->getAliasee(), llvm::PointerType::getUnqual(DeclTy), /*D=*/nullptr); + LT = getLLVMLinkageVarDefinition(cast<VarDecl>(GD.getDecl()), + D->getType().isConstQualified()); + } // Create the new alias itself, but don't set a name yet. - auto *GA = llvm::GlobalAlias::create( - DeclTy, 0, llvm::Function::ExternalLinkage, "", Aliasee, &getModule()); + auto *GA = + llvm::GlobalAlias::create(DeclTy, 0, LT, "", Aliasee, &getModule()); if (Entry) { if (GA->getAliasee() == Entry) {
Index: clang/test/CodeGen/alias.c =================================================================== --- clang/test/CodeGen/alias.c +++ clang/test/CodeGen/alias.c @@ -2,6 +2,7 @@ // RUN: %clang_cc1 -triple i386-pc-linux-gnu -emit-llvm -o - %s | FileCheck -check-prefix=CHECKBASIC %s // RUN: %clang_cc1 -triple armv7a-eabi -mfloat-abi hard -emit-llvm -o - %s | FileCheck -check-prefix=CHECKCC %s // RUN: %clang_cc1 -triple armv7a-eabi -mfloat-abi hard -S -o - %s | FileCheck -check-prefix=CHECKASM %s +// RUN: %clang_cc1 -emit-llvm -o - %s | FileCheck -check-prefix=CHECKGLOBALS %s int g0; // CHECKBASIC-DAG: @g0 = common global i32 0 @@ -88,3 +89,9 @@ void test9_bar(void) { } void test9_zed(void) __attribute__((section("test"))); void test9_zed(void) __attribute__((alias("test9_bar"))); + +// Test that the alias gets its linkage from its declared qual type. +// CHECKGLOBALS: @test10_foo = internal +// CHECKGLOBALS-NOT: @test10_foo = dso_local +int test10; +static int test10_foo __attribute__((alias("test10"))); Index: clang/lib/CodeGen/CodeGenModule.cpp =================================================================== --- clang/lib/CodeGen/CodeGenModule.cpp +++ clang/lib/CodeGen/CodeGenModule.cpp @@ -4363,17 +4363,22 @@ // Create a reference to the named value. This ensures that it is emitted // if a deferred decl. llvm::Constant *Aliasee; - if (isa<llvm::FunctionType>(DeclTy)) + llvm::GlobalValue::LinkageTypes LT; + if (isa<llvm::FunctionType>(DeclTy)) { Aliasee = GetOrCreateLLVMFunction(AA->getAliasee(), DeclTy, GD, /*ForVTable=*/false); - else + LT = getFunctionLinkage(GD); + } else { Aliasee = GetOrCreateLLVMGlobal(AA->getAliasee(), llvm::PointerType::getUnqual(DeclTy), /*D=*/nullptr); + LT = getLLVMLinkageVarDefinition(cast<VarDecl>(GD.getDecl()), + D->getType().isConstQualified()); + } // Create the new alias itself, but don't set a name yet. - auto *GA = llvm::GlobalAlias::create( - DeclTy, 0, llvm::Function::ExternalLinkage, "", Aliasee, &getModule()); + auto *GA = + llvm::GlobalAlias::create(DeclTy, 0, LT, "", Aliasee, &getModule()); if (Entry) { if (GA->getAliasee() == Entry) {
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits